Паника по блокировке файлов Golang flock: ошибка во время выполнения: неверный адрес памяти или разыменование нулевого указателя
У меня есть программа go, которая изменяет мой файл конфигурации. Я пытаюсь создать блокировку файла из функции main(), но panic: runtime error: invalid memory address or nil pointer dereference
ошибка. Без блокировки программа работает нормально, как и ожидалось. Кусок кода, который выдает исключение
lockProgram, err := os.Create("/var/.daemon.lock")
defer lockProgram.Close()
CheckForError(err)
GetLock(lockProgram, syscall.LOCK_EX)
defer UngetLock(lockProgram)
// Это в отдельном пакете
func CheckForError(e error) {
if e != nil {
Error.Println(e)
panic(e)
}
}
func GetLock(file *os.File, locktype int ) {
fmt.Println("Acquiring lock on ", file.Name())
syscall.Flock(int(file.Fd()), locktype)
fmt.Println("Acquired filelock on ", file.Name())
}
func UngetLock(file *os.File) {
syscall.Flock(int(file.Fd()), syscall.LOCK_UN);
}
Это же flock
работает, когда я вызываю его в моем файле конфигурации, но из другого пакета, а не из основного пакета, но выдает ту же ошибку при попытке установить блокировку из основного пакета. Пожалуйста, помогите мне выяснить, что я делаю здесь не так.
1 ответ
Когда ошибка возникает при создании блокировки, lockProgram
будет nil
, Это вызовет последующий (отложенный) вызов lockProgram.Close()
терпеть неудачу.
Обратите внимание, что когда вы паникуете (как в вашем CheckForError
функция), отложенные вызовы методов по-прежнему будут выполняться. Это подробно объясняется в этой статье блога (выделено мной):
Паника - это встроенная функция, которая останавливает обычный поток контроля и начинает паниковать. Когда функция F вызывает панику, выполнение F останавливается, все отложенные функции в F выполняются нормально, а затем F возвращается к своему вызывающему. Для вызывающего абонента F ведет себя как призыв к панике. Процесс продолжается вверх по стеку до тех пор, пока не будут возвращены все функции в текущей процедуре, после чего программа вылетает.
Решение. Сначала проверьте ошибки, а затем отложите Close()
вызов:
lockProgram, err := os.Create("/var/.daemon.lock")
CheckForError(err)
defer lockProgram.Close()