Я работаю над небольшим веб-приложением на Go, которое предназначено для использования на компьютере разработчика в качестве инструмента для отладки их приложений / веб-сервисов. Интерфейс программы представляет собой веб-страницу, которая включает не только HTML, но и некоторый JavaScript (для функциональности), изображения и CSS (для стилизации). Я планирую сделать это приложение открытым исходным кодом, поэтому пользователи должны просто иметь возможность запускать Makefile, и все ресурсы будут направляться туда, куда им нужно. Однако я также хотел бы иметь возможность просто распространять исполняемый файл с как можно меньшим количеством файлов / зависимостей. Есть ли хороший способ связать HTML / CSS / JS с исполняемым файлом, чтобы пользователям нужно было загружать только один файл и беспокоиться о нем?
Прямо сейчас в моем приложении обслуживание статического файла выглядит примерно так:
// called via http.ListenAndServe
func switchboard(w http.ResponseWriter, r *http.Request) {
// snipped dynamic routing...
// look for static resource
uri := r.URL.RequestURI()
if fp, err := os.Open("static" + uri); err == nil {
defer fp.Close()
staticHandler(w, r, fp)
return
}
// snipped blackhole route
}
Так что это довольно просто: если запрошенный файл существует в моем статическом каталоге, вызовите обработчик, который просто открывает файл и пытается установить товар Content-Type
перед обслуживанием. Я думал, что нет причин, по которым это должно быть основано на реальной файловой системе: если бы были скомпилированные ресурсы, я мог бы просто проиндексировать их по URI запроса и обслуживать их как таковые.
Если нет хорошего способа сделать это, или я лаю не на то дерево, пытаясь сделать это, дайте мне знать. Я просто подумал, что конечный пользователь будет признателен за управление как можно меньшим количеством файлов.
Если подходящих тегов больше, чем идти, пожалуйста, добавьте их или дайте мне знать.
go generate
небольшую утилиту командной строки (упакованную с моим исходным кодом) для преобразования файлов в[]byte
фрагменты, которые встраиваются как переменные в код, аналогично тому, какstringer
это делается (см. Blog.golang.org / генерировать ).Ответы:
Пакет go-bindata выглядит так, как будто это может быть то, что вас интересует.
https://github.com/go-bindata/go-bindata
Это позволит вам преобразовать любой статический файл в вызов функции, который может быть встроен в ваш код, и при вызове вернет байтовый фрагмент содержимого файла.
источник
Встраивание текстовых файлов
Если мы говорим о текстовых файлах, их можно легко встроить в сам исходный код. Просто используйте обратные кавычки, чтобы объявить
string
литерал следующим образом:Совет по оптимизации:
Поскольку в большинстве случаев вам нужно будет только записать ресурс в объект
io.Writer
, вы также можете сохранить результат[]byte
преобразования:Единственное, с чем следует быть осторожным, это то, что необработанные строковые литералы не могут содержать символ обратной кавычки (`). Необработанные строковые литералы не могут содержать последовательности (в отличие от интерпретируемых строковых литералов), поэтому, если текст, который вы хотите вставить, действительно содержит обратные кавычки, вы должны разбить необработанный строковый литерал и объединить обратные кавычки как интерпретированные строковые литералы, как в этом примере:
На производительность это не влияет, так как эти конкатенации будут выполняться компилятором.
Встраивание двоичных файлов
Сохранение в виде байтового среза
Для двоичных файлов (например, изображений) наиболее компактным (относительно результирующего нативного двоичного файла) и наиболее эффективным было бы иметь содержимое файла как
[]byte
в исходном коде. Это может быть создано сторонними toos / библиотеками, такими как go-bindata .Если вы не хотите использовать для этого стороннюю библиотеку, вот простой фрагмент кода, который читает двоичный файл и выводит исходный код Go, который объявляет переменную типа,
[]byte
которая будет инициализирована точным содержимым файла:Пример вывода, если файл будет содержать байты от 0 до 16 (попробуйте на Go Playground ):
Хранение как base64
string
Если файл не «слишком большой» (подходит для большинства изображений / значков), есть и другие жизнеспособные варианты. Вы можете преобразовать содержимое файла в Base64
string
и сохранить его в исходном коде. При запуске приложения (func init()
) или при необходимости вы можете декодировать его в исходное[]byte
содержимое. Вencoding/base64
пакете Go есть хорошая поддержка кодировки Base64 .Преобразование (двоичного) файла в base64
string
так же просто, как:Сохраните строку результата base64 в исходном коде, например, как файл
const
.Расшифровка - это всего лишь вызов одной функции:
Хранение как указано
string
Более эффективным, чем хранение в формате base64, но может быть больше в исходном коде, является хранение строкового литерала в кавычках двоичных данных. Мы можем получить цитированную форму любой строки с помощью
strconv.Quote()
функции:Для двоичных данных, содержащих значения от 0 до 64, результат будет выглядеть следующим образом (попробуйте на Go Playground ):
"\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?"
(Обратите внимание, что
strconv.Quote()
к нему добавляются кавычки.)Вы можете напрямую использовать эту строку в кавычках в своем исходном коде, например:
Готово к использованию, расшифровывать не нужно; снятие кавычек выполняется компилятором Go во время компиляции.
Вы также можете сохранить его как байтовый фрагмент, если вам это понадобится:
источник
sh
файл к исполняемому файлу go?также есть экзотический способ - я использую плагин maven для создания проектов GoLang, который позволяет использовать препроцессор JCP для встраивания двоичных блоков и текстовых файлов в исходники. В этом случае код просто выглядит как строка ниже ( и здесь можно найти пример )
источник
sh
или исполняемый файл, как указано вышеsh
файл? Не уверен, что вы имеете в виду. Если вы хотите, чтобы все в каталоге было встроено, я это сделалgo-bindata
. Например, если я вставлю//go:generate $GOPATH/bin/go-bindata -prefix=data/ -pkg=$GOPACKAGE data/
(не сгенерированный) файл go,go generate ./...
запустит go-bindata в каталоге пакета, встраивая все в подкаталог данных, но с удаленным префиксом data /.В качестве популярной альтернативы
go-bindata
упомянутому в другом ответе mjibson / esc также встраивает произвольные файлы, но особенно удобно обрабатывает деревья каталогов.источник