Отсрочка отсрочек в Golang

Я новичок в Go, и мне нужно написать приложение, которое должно открывать множество файлов в разных точках. Код для открытия каждого файла будет

fl, err := os.Open(..)
check(err)
defer fl.Close()

где check просто вызывает panic, если что-то пойдет не так.

Как я уже сказал, этот фрагмент повторяется несколько раз. Я хотел бы иметь что-то вроде этого:

func foo(f string){
    fl, err := os.Open(f)
    check(err)
    defer fl.Close() //lolwut
}

Конечно, как только foo вернется, defer включится и закроет файл.

Есть ли способ отложить отсрочки для функции до тех пор, пока ее вызывающая сторона не решит, что пришло время?

Что я пытался сделать до сих пор, так это поместить отсрочку в анонимную функцию, заставить foo вернуть ее и заставить вызывающую выполнить это (предпочтительно в однострочном режиме). Тем не менее, я сталкиваюсь с некоторыми препятствиями при реализации этого, и я даже не уверен, что это правильный подход.

tl;dr: Есть ли способ отложить отсрочку до вызывающей функции в Go?


person rath    schedule 03.08.2014    source источник
comment
Нет. И не стоит паниковать по поводу каждой возможной ошибки. Научитесь правильно с ними обращаться.   -  person Wessie    schedule 03.08.2014
comment
@Весси прямо здесь. Кроме того, os.Open() возвращает nil при ошибке, что является допустимым аргументом для Close(). Вы можете безопасно отложить Close() сразу после вызова Open().   -  person fuz    schedule 03.08.2014
comment
@Wessie Жесткий и быстрый сбой из-за ошибки файла в моем случае является требованием, но в остальном я согласен. Ваше здоровье   -  person rath    schedule 03.08.2014
comment
@rath Вы все равно можете потерпеть неудачу с log.Fatal(). Пожалуйста, не паникуйте, это плохой стиль.   -  person fuz    schedule 04.08.2014


Ответы (1)


Я думаю, что вы ошиблись в своем дизайне. То, что вы хотели сделать изначально, на самом деле не имеет смысла: если вы хотите отложить Close() в вызывающем объекте, вы лишаете всю гибкость принятия решения об освобождении от вызывающего объекта. Что, если вызывающая сторона должна хранить файл дольше, чем его собственная продолжительность?

Вы можете рассматривать foo() как функцию распределения ресурсов, точно так же, как io.Open(). Таким образом, если функция вызывает foo(), она только что выделила ресурс. foo() не несет ответственности за освобождение этого ресурса, а вызывающая сторона, как и в случае с io.Open().

person fuz    schedule 03.08.2014
comment
What if [..] duration? Не использовать foo или передать эту отсрочку его вызывающему. Шутки в сторону, я думал сделать что-то похожее на OO, где каждый класс имеет деструктор (defer), и все подклассы (вызывающие foo) просто не будут беспокоиться об этом. Но да, мне нужно переосмыслить дизайн с точки зрения Go. Ваше здоровье - person rath; 03.08.2014
comment
@rath Go — это язык, который явно спроектирован следующим образом: вы должны явно отслеживать и освобождать все внешние ресурсы. - person fuz; 03.08.2014