paint-brush
Как встроить статические ресурсы в проект Goк@kibizovd
837 чтения
837 чтения

Как встроить статические ресурсы в проект Go

к David Kibizov3m2023/11/28
Read on Terminal Reader

Слишком долго; Читать

Использование автономного приложения упрощает развертывание и распространение, поскольку это всего лишь исполняемый двоичный файл. Rice, Statik и Bindata доступны для встраивания ресурсов в приложение Go. Давайте создадим шаблон index.html и протестируем его со статическим ресурсом для проверки кода Go.
featured image - Как встроить статические ресурсы в проект Go
David Kibizov HackerNoon profile picture

Я хотел создать небольшое автономное веб-приложение на Go, противоположное обычному веб-приложению, в котором ресурсы будут обслуживаться отдельно через CDN или HTTP-сервер, такой как Nginx.


Однако если производительность не является критической проблемой или приложение предназначено для низкого трафика, использование автономного приложения упрощает развертывание и распространение, поскольку это всего лишь исполняемый двоичный файл.


Доступно несколько пакетов для встраивания ресурсов в приложение Go:



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

Начиная

Сначала давайте создадим index.html внутри каталога frontend/ вашего проекта:

 <html> <body> Hello, World! </body> </html>


Теперь, когда у нас есть настройка проекта и статический ресурс для тестирования, давайте установим Bindata с помощью команды:

 go get -u github.com/jteeuwen/go-bindata/...


Мы готовы запустить серверный код веб-приложения. Создайте файл main.go и скопируйте следующий код:

 package main import ( "bytes" "io" "net/http" ) //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/... func static_handler(rw http.ResponseWriter, req *http.Request) { var path string = req.URL.Path if path == "" { path = "index.html" } if bs, err := Asset(path); err != nil { rw.WriteHeader(http.StatusNotFound) } else { var reader = bytes.NewBuffer(bs) io.Copy(rw, reader) } } func main() { http.Handle("/", http.StripPrefix("/", http.HandlerFunc(static_handler))) http.ListenAndServe(":3000", nil) }


Важная строка в этом коде:

 //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...


Строка выше позволяет нам запускать команду go-bindata при вызове go generate . Начиная с версии 1.4, вы можете запускать собственные команды на этапе генерации. Это просто вопрос добавления //go:generate command argument... в ваш файл go.


Командная строка go-bindata имеет несколько параметров, поэтому ознакомьтесь с документацией по ее использованию. В нашем случае мы говорим:


  • -prefix "frontend/" определяет часть пути для статических


  • -pkg main определяет имя пакета, используемое в сгенерированном коде.


  • -o bindata.go определить имя сгенерированного файла


После запуска команды go generate вы должны увидеть сгенерированный файл с bindata.go . Структура вашего проекта должна выглядеть следующим образом:

 . │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go


Логика обслуживания статических файлов находится в функции static_handler , которая принимает запрос и проверяет, соответствует ли путь статическому пути. Проверка осуществляется с помощью функции Asset , автоматически экспортируемой bindata.go . Если ресурс не существует, мы возвращаем 404 , в противном случае мы возвращаем содержимое ресурса.


Остальная часть кода предназначена для создания веб-приложения и привязки нашего шаблона static_handler для соответствия всем входящим запросам для / . Если у вас возникли проблемы с пониманием этого кода, ознакомьтесь с официальной документацией Go для http package .


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


На основании этого правила bindata.go предоставляет функцию Asset для main пакета. Это загружает и возвращает актив для данного имени. Он возвращает ошибку, если ресурс не может быть найден или не может быть загружен.