Цикл инициализации Голанга
Привет, я пытаюсь сделать мой функциональный блок тестируемым. Одним из предложений было присвоить функцию переменной и сделать ее доступной в глобальном масштабе. Я только что сделал это, но теперь я испытываю цикл инициализации ниже мой код
////////////////////////
// main.go
////////////////////////
func DownloadFile(filename string) {
// Initialized request variable here
// ... doing initialization
// End of initialization
res = ProcessDownload(request)
if res == 401 {
return doRetry(filename)
}
// some code here
return downloadFile(filename)
}
func DoRetry(filename string) {
// Doing some database insert/updating
return downloadFile(string)
}
И в моем другом файле я назначаю эту функцию в переменную
//////////////////////
// global.go
//////////////////////
var downloadFile = DownloadFile
var doRetry = DoRetry
Причина, по которой я сделал это в global.go, состояла в том, чтобы сделать модуль DoRetry и DownloadFile тестируемым. Имея в виду этот метод, я могу МОКРИТЬ функцию без создания интерфейса. Так как это всего лишь отдельная функция, и она не должна быть в определенном классе. Все остальные переменные в порядке, но когда дело доходит до функции, выполняющей рекурсивное поведение, я получаю ошибку ниже
./global.go:22:5: initialization loop:
/go/src/project/global.go:22:5 downloadFile refers to
/go/src/project/process.go:403:99 DownloadFile refers to
/go/src/project/global.go:23:5 doRetry refers to
/go/src/project/process.go:394:89 DoRetry refers to
/go/src/project/global.go:22:5 downloadFile
FAIL project [build failed]
Я знаю, что это может быть дубликатом здесь, но я не вижу, как решение здесь решает мою проблему.
Пожалуйста помоги мне с этим. Спасибо, я читал о насмешке функции в этой ссылке
https://husobee.github.io/golang/testing/unit-test/2015/06/08/golang-unit-testing.html
1 ответ
Решение состоит в том, чтобы не назначать значения, когда вы объявляете downloadFile
а также doRetry
переменные функции, но "откладывают" инициализацию в пакет init()
функция, как это:
var downloadFile func(string) //= DownloadFile
var doRetry func(string) //= DoRetry
func init() {
downloadFile = DownloadFile
doRetry = DoRetry
}
Таким образом, переменные сначала будут инициализированы с nil
(нулевое значение для типов функций), что означает, что они не зависят от DownloadFile()
а также DoRetry()
функции, а позже, когда пакет init()
запускается функция, которая присваивает значения функции переменным, поэтому цикл инициализации не произойдет.