Go 1.16以降、goツールは静的ファイルを実行可能バイナリに直接埋め込むことをサポートしています。
embed
パッケージをインポートし、//go:embed
ディレクティブを使用して、埋め込みたいファイルとそれらを保存したい変数をマークする必要があります。
実行可能ファイルにファイルを埋め込む3つの方法hello.txt
:
import "embed"
//go:embed hello.txt
var s string
print(s)
//go:embed hello.txt
var b []byte
print(string(b))
//go:embed hello.txt
var f embed.FS
data, _ := f.ReadFile("hello.txt")
print(string(data))
変数の型を使用embed.FS
すると、単純なファイルシステムインターフェイスを提供する変数に複数のファイルを含めることもできます。
// content holds our static web server content.
//go:embed image/* template/*
//go:embed html/index.html
var content embed.FS
は、次のように使用net/http
する値からファイルを提供するためのサポートを備えています。embed.FS
http.FS()
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))
テンプレートパッケージはtext/template.ParseFS()
、html/template.ParseFS()
関数とtext/template.Template.ParseFS()
メソッドhtml/template.Template.ParseFS()
を使用してテンプレートを解析することもできます。
template.ParseFS(content, "*.tmpl")
次の回答は、古いオプションを示しています(Go 1.16より前)。
テキストファイルの埋め込み
テキストファイルについて話している場合、それらはソースコード自体に簡単に埋め込むことができます。後ろの引用符を使用して、string
次のようにリテラルを宣言します。
const html = `
<html>
<body>Example embedded HTML content.</body>
</html>
`
// Sending it:
w.Write([]byte(html)) // w is an io.Writer
最適化のヒント:
ほとんどの場合、リソースをに書き込むだけでよいので、変換io.Writer
の結果を保存することもできます。[]byte
var html = []byte(`
<html><body>Example...</body></html>
`)
// Sending it:
w.Write(html) // w is an io.Writer
注意する必要があるのは、生の文字列リテラルに逆引用符( `)を含めることができないことだけです。生の文字列リテラルにはシーケンスを含めることができないため(解釈された文字列リテラルとは異なり)、埋め込みたいテキストに逆引用符が含まれている場合は、次の例のように、生の文字列リテラルを分割し、逆引用符を解釈された文字列リテラルとして連結する必要があります。
var html = `<p>This is a back quote followed by a dot: ` + "`" + `.</p>`
これらの連結はコンパイラーによって実行されるため、パフォーマンスは影響を受けません。
バイナリファイルの埋め込み
バイトスライスとして保存
バイナリファイル(画像など)の場合、最もコンパクトで(結果のネイティブバイナリに関して)、最も効率的なのは、ファイルのコンテンツを[]byte
ソースコードに含めることです。これは、 go-bindataなどのサードパーティのtoos/librariesによって生成できます。
これにサードパーティのライブラリを使用したくない場合は、バイナリファイルを読み取り、ファイル[]byte
の正確なコンテンツで初期化される型の変数を宣言するGoソースコードを出力する単純なコードスニペットを次に示します。
imgdata, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Print("var imgdata = []byte{")
for i, v := range imgdata {
if i > 0 {
fmt.Print(", ")
}
fmt.Print(v)
}
fmt.Println("}")
ファイルに0〜16のバイトが含まれる場合の出力例(Go Playgroundで試してください):
var imgdata = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
base64として保存string
ファイルが「大きすぎない」場合(ほとんどの画像/アイコンが適格)、他の実行可能なオプションもあります。ファイルの内容をBase64に変換し、string
それをソースコードに保存できます。アプリケーションの起動時( )または必要に応じて、元のコンテンツfunc init()
にデコードできます。Goは、パッケージ[]byte
内のBase64エンコーディングを適切にサポートしています。encoding/base64
(バイナリ)ファイルをbase64に変換するのstring
は、次のように簡単です。
data, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(data))
結果のbase64文字列をソースコードに保存します(例:const
。
デコードは1つの関数呼び出しです。
const imgBase64 = "<insert base64 string here>"
data, err := base64.StdEncoding.DecodeString(imgBase64) // data is of type []byte
引用どおりに保存string
base64として保存するよりも効率的ですが、ソースコードでは、バイナリデータの引用符で囲まれた文字列リテラルを保存する方が長い場合があります。strconv.Quote()
次の関数を使用して、任意の文字列の引用符付き形式を取得できます。
data, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Println(strconv.Quote(string(data))
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()
(引用符を追加および追加することに注意してください。)
この引用符で囲まれた文字列をソースコードで直接使用できます。次に例を示します。
const imgdata = "\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:;<=>?"
すぐに使用でき、デコードする必要はありません。引用符の解除は、コンパイル時にGoコンパイラによって行われます。
次のように必要な場合は、バイトスライスとして保存することもできます。
var imgdata = []byte("\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:;<=>?")