Пакет embed
Обзор
Пакет embed предоставляет доступ к файлам, встроенным в работающую программу Go.
Исходные файлы Go, импортирующие "embed", могут использовать директиву //go:embed для инициализации переменной типа string, []byte или FS содержимым файлов, считанных из каталога пакета или его подкаталогов во время компиляции.
Например, ниже показаны три способа встроить файл с именем hello.txt, а затем вывести его содержимое во время выполнения программы.
Встраивание одного файла в строку:
import _ "embed" //go:embed hello.txt var s string print(s)
Встраивание одного файла в срез байтов:
import _ "embed" //go:embed hello.txt var b []byte print(string(b))
Встраивание одного или нескольких файлов в файловую систему:
import "embed"
//go:embed hello.txt
var f embed.FS
data, _ := f.ReadFile("hello.txt")
print(string(data))
Директивы
Директива //go:embed перед объявлением переменной указывает, какие файлы следует встроить, с помощью одного или нескольких шаблонов path.Match.
Директива должна непосредственно предшествовать строке с объявлением одной переменной. Между директивой и объявлением допускаются только пустые строки и построчные комментарии ‘//’.
Тип переменной должен быть строковым типом, срезом байтового типа или FS (либо псевдонимом FS).
Например:
package server import "embed" // content holds our static web server content. //go:embed image/* template/* //go:embed html/index.html var content embed.FS
Система сборки Go распознает директивы и позаботится о том, чтобы объявленная переменная (в приведенном выше примере — content) была заполнена файлами файловой системы, соответствующими шаблону.
Для краткости директива //go:embed может принимать несколько разделенных пробелами шаблонов, но ее также можно повторять, чтобы избежать слишком длинных строк при большом количестве шаблонов. Шаблоны интерпретируются относительно каталога пакета, содержащего исходный файл. В качестве разделителя пути используется косая черта, даже в системах Windows. Шаблоны не могут содержать ‘.’, ‘..’ или пустые элементы пути, а также начинаться или заканчиваться косой чертой. Чтобы сопоставить все содержимое текущего каталога, используйте ‘*’ вместо ‘.’. Чтобы можно было указывать имена файлов с пробелами, шаблоны можно записывать в виде строковых литералов Go в двойных кавычках или обратных кавычках.
Если шаблон задает каталог, встраиваются все файлы в поддереве этого каталога (рекурсивно), за исключением файлов, имена которых начинаются с ‘.’ или ‘_’. Таким образом, переменная в приведенном выше примере почти эквивалентна следующей:
// content is our static web server content. //go:embed image template html/index.html var content embed.FS
Разница в том, что ‘image/*’ встраивает ‘image/.tempfile’, а ‘image’ — нет. Ни один из шаблонов не встраивает ‘image/dir/.tempfile’.
Если шаблон начинается с префикса ‘all:’, правило обхода каталогов изменяется: в него включаются файлы, начинающиеся с ‘.’ или ‘_’. Например, ‘all:image’ встраивает и ‘image/.tempfile’, и ‘image/dir/.tempfile’.
Директива //go:embed может использоваться как с экспортируемыми, так и с неэкспортируемыми переменными — в зависимости от того, хочет ли пакет сделать данные доступными другим пакетам. Ее можно использовать только с переменными уровня пакета, но не с локальными переменными.
Шаблоны не должны соответствовать файлам за пределами модуля пакета, например ‘.git/*’, символическим ссылкам, 'vendor/' или каталогам, содержащим go.mod (это отдельные модули). Шаблоны не должны соответствовать файлам, имена которых содержат специальные знаки пунктуации " * < > ? ` ' | / \ и :. Совпадения с пустыми каталогами игнорируются. После этого каждый шаблон в строке //go:embed должен соответствовать как минимум одному файлу или непустому каталогу.
Если какие-либо шаблоны недопустимы или им соответствуют недопустимые элементы, сборка завершится с ошибкой.
Строки и байты
Строка //go:embed для переменной типа string или []byte может содержать только один шаблон, и этот шаблон может соответствовать только одному файлу. Строка или []byte инициализируется содержимым этого файла.
Для директивы //go:embed требуется импортировать "embed", даже если используется string или []byte. В исходных файлах, где нет ссылок на embed.FS, используйте пустой импорт (import _ "embed").
Файловые системы
Для встраивания одного файла обычно лучше всего подходит переменная типа string или []byte. Тип FS позволяет встраивать дерево файлов, например каталог со статическим содержимым веб-сервера, как в примере выше.
FS реализует интерфейс FS пакета io/fs, поэтому его можно использовать с любым пакетом, поддерживающим файловые системы, включая net/http, text/template и html/template.
Например, используя переменную content из приведенного выше примера, можно написать:
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))
template.ParseFS(content, "*.tmpl")
Инструменты
Для поддержки инструментов, анализирующих пакеты Go, шаблоны из строк //go:embed доступны в выводе “go list”. См. поля EmbedPatterns, TestEmbedPatterns и XTestEmbedPatterns в выводе команды “go help list”.
Пример
Код:
package embed_test
import (
"embed"
"log"
"net/http"
)
//go:embed internal/embedtest/testdata/*.txt
var content embed.FS
func Example() {
mux := http.NewServeMux()
mux.Handle("/", http.FileServer(http.FS(content)))
err := http.ListenAndServe(":8080", mux)
if err != nil {
log.Fatal(err)
}
}
Указатель
Примеры
Файлы пакета
embed.go
тип FS 1.16
FS — это доступная только для чтения коллекция файлов, обычно инициализируемая директивой //go:embed. Если FS объявлена без директивы //go:embed, она представляет собой пустую файловую систему.
FS — это значение, доступное только для чтения, поэтому его безопасно одновременно использовать из нескольких горутин, а также присваивать друг другу значения типа FS.
FS реализует fs.FS, поэтому его можно использовать с любым пакетом, поддерживающим интерфейсы файловых систем, включая net/http, text/template и html/template.
Дополнительные сведения об инициализации FS см. в документации пакета.
type FS struct {
// contains filtered or unexported fields
}
func (FS) Open 1.16
func (f FS) Open(name string) (fs.File, error)
Open открывает указанный файл для чтения и возвращает его как fs.File.
Возвращенный файл реализует io.Seeker и io.ReaderAt, если файл не является каталогом.
func (FS) ReadDir 1.16
func (f FS) ReadDir(name string) ([]fs.DirEntry, error)
ReadDir читает и возвращает содержимое указанного каталога целиком.
func (FS) ReadFile 1.16
func (f FS) ReadFile(name string) ([]byte, error)
ReadFile читает и возвращает содержимое указанного файла.
© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/embed/