in

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

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

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

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

  • Рис
  • Statik
  • Bindata

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

Приступая к работе

Сначала давайте создадим 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/" определите часть пути для static
  • -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 шаблона ко всем входящим запросам на /. Если у вас возникли проблемы с пониманием этого кода, ознакомьтесь с официальной документацией по http package Go.

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

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

What do you think?

Начинающий

Written by Жендос

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

GIPHY App Key not set. Please check settings