Я много раз видел в рубиновых кодах непревзойденные File.open
звонки
Вы можете привести пример? Я только когда-либо видел это в коде, написанном новичками, которым не хватает «общих знаний о большинстве языков программирования, что поток для работы с файлами открыт-использует-закрывает».
Опытные рубисты либо явно закрывают свои файлы, либо, что более идиоматично, используют блочную форму File.open
, которая автоматически закрывает файл за вас. Его реализация в основном выглядит примерно так:
def File.open(*args, &block)
return open_with_block(*args, &block) if block_given?
open_without_block(*args)
end
def File.open_without_block(*args)
end
def File.open_with_block(*args)
yield f = open_without_block(*args)
ensure
f.close
end
Скрипты - особый случай. Сценарии обычно работают так быстро и используют так мало файловых дескрипторов, что их просто не имеет смысла закрывать, поскольку операционная система все равно закроет их при выходе из сценария.
Нужно ли закрывать явно?
Да.
Если да, то почему ГХ автоматически закрывается?
Потому что после того, как он собрал объект, у вас больше нет возможности закрыть файл, и, таким образом, вы получите утечку файловых дескрипторов.
Обратите внимание, что файлы закрывает не сборщик мусора. Сборщик мусора просто выполняет любые финализаторы для объекта, прежде чем он его соберет. Так уж получилось, что File
класс определяет финализатор, который закрывает файл.
Если нет, то почему вариант?
Потому что потраченная впустую память - это дешево, а потраченные впустую файловые дескрипторы - нет. Следовательно, не имеет смысла связывать время жизни файлового дескриптора со временем жизни некоторого фрагмента памяти.
Вы просто не можете предсказать, когда запустится сборщик мусора. Вы даже не можете предсказать , запустится ли он вообще : если у вас никогда не закончится память, сборщик мусора никогда не запустится, поэтому финализатор никогда не запустится, поэтому файл никогда не будет закрыт.