Хотя вы, конечно, можете получить размер файла до чтения
Исходя из этого (см. другой ответ), делать это обычно бесполезно
по ряду причин:
Файловая система - это по своей природе колоритный носитель: любое количество процессов
может обновить данный файл одновременно и даже удалить его.
В файловой системе с семантикой POSIX (большинство обычных ОС
кроме Windows) единственная гарантия успешного открытия файла
дает вам то, что можно читать данные из него,
и это в основном все. (Ну, чтение может произойти сбой из-за ошибки
в основной информации, но давайте не будем отступать дальше).
Что бы вы сделали, если бы вы сделали эквивалент вызова fstat(2)
,
как предложено, и он сказал вам, что файл содержит 42 терабайта данных?
Вы бы попытались выделить достаточно большой массив для хранения его содержимого?
Реализуете ли вы какую-то собственную логику, которая классифицирует файл
размер в несколько диапазонов и выполняет пользовательскую обработку на основе этого, например,
скажем, прихлебывая файлы размером менее N мегабайт и читая
большие файлы по частям?
Что, если файл увеличился (был добавлен) после того, как вы получили его размер?
Что если позже вы решите быть более подготовленными к Unix и сделаете это возможным
читать данные из стандартного потока ввода вашей программы - например, cat
программа на Unix (или ее type
Windows двоюродный брат) делает?
Вы не можете знать, сколько данных будет передано через этот поток;
и потенциально это может быть неопределенной длины (рассмотрим
содержимое некоторого файла журнала занятости в постоянно работающей системе).
Конечно, в некоторых приложениях вы предполагаете, содержимое файлов не
переодеться под ногами; Одним из примеров являются архиваторы, такие как zip
или tar
, которые
запишите метаданные файла, включая его размер, вместе с файлом.
(Кстати, tar
обнаруживает, что файл мог измениться, пока программа
читал его содержимое и предупреждает пользователя в этом случае).
Но к чему я вас веду, так это к такой простой задаче, как ваша,
нет никакого смысла делать это так, как вы придумали.
Вместо этого просто используйте буфер некоторого «разумного» размера и шлюз данных
между его источником и назначением через этот буфер.
То есть вы выделяете буфер, вводите цикл и на каждой итерации
если вы попытаетесь прочитать столько данных, сколько уместится в буфере, обработать что угодно
функция Read
показала, что она может читать, а затем обрабатывать
условие конца файла или ошибка, если она была указана.
Чтобы округлить этот небольшой ускоренный курс, я бы намекнул, что стандартная библиотека
уже имеет io.Copy
, который в вашем
случай, может быть назван как
_, err := io.Copy(os.Stdout, f)
и переложит все содержимое f
на стандартный вывод вашего
запрограммируйте до EOF или до обнаружения ошибки.
В прошлый раз, когда я проверял, эта функция использовала внутренний буфер размером 32 КиБ,
но вы всегда можете проверить исходный код вашей установки Go.