👣 Нужен ли второй defer file.Close(), после перезаписи переменной?



▶️Итак, есть такой код:

jsonFile, err := os.Open("referenceData/ex.json")

if err != nil {

return err

}

defer jsonFile.Close() // первый defer

byteValue, err := ioutil.ReadAll(jsonFile)

if err != nil {

return err

}



err = json.Unmarshal(byteValue, &exToParse)

if err != nil {

return err

}



jsonFile, err = os.Open("referenceData/di.json") // перезапись jsonFile

if err != nil {

return err

}

defer jsonFile.Close() // нужно ли заново объявлять defer jsonFile.Close()?

byteValue, err = ioutil.ReadAll(jsonFile)

if err != nil {

return err

}



err = json.Unmarshal(byteValue, &diToParse)

if err != nil {

return err

}


Сначала инициализируем переменную не через var, а сразу передаём значение. Потом сразу пишем defer jsonFile.Close(). Потом в этот же файл загружаем другой json, и так же пишем defer jsonFile.Close().



Вопрос — а нужен ли второй defer? По идеи в ОЗУ, после перезаписи, jsonFile один и тоже, с тем же адресом, но только с другим содержанием.





▶️Да, нужен, так как аргументы функции, вызываемой defer, вычисляются в момент использования defer. Вот простой пример, где это видно:

type T int



func (t T) Close() { fmt.Println(int(t)) }



// ...



t := T(1)

defer t.Close()



t = T(2)

defer t.Close()



// 2

// 1


Вообще, не рекомендуется переиспользовать переменные подобным образом, так как это усложняет понимание текста программы.



@golang_interview