Goプログラムから読み込んだテキストファイルがあります。追加でテキストファイルを提供せずに、単一の実行可能ファイルを出荷したいと考えています。 WindowsとLinuxでコンパイルに組み込む方法を教えてください。
go-bindata を使用します。 READMEから:
このツールは、任意のファイルを管理可能なGoソースコードに変換します。バイナリデータをgoプログラムに埋め込むのに便利です。ファイルデータは、生のバイトスライスに変換される前に、オプションでgzip圧縮されます。
Go 1.4以降、より柔軟性が必要な場合は go generate を使用できます。
複数のテキストファイルがある場合、またはテキストファイルが変更される可能性がある場合は、テキストファイルをハードコーディングせずに、コンパイル時に含めます。
次のファイルがある場合:
main.go
scripts/includetxt.go
a.txt
b.txt
また、main.go内のすべての.txtファイルのコンテンツにアクセスしたい場合は、go generateコマンドを含む特別なコメントを含めることができます。
package main
import "fmt"
//go:generate go run scripts/includetxt.go
func main() {
fmt.Println(a)
fmt.Println(b)
}
Go generateコマンドは、go:generate
の後にスクリプトを実行します。この場合、すべてのテキストファイルを読み取り、文字列リテラルとして新しいファイルに出力するgoスクリプトを実行します。短いコードではエラー処理をスキップしました。
package main
import (
"io"
"io/ioutil"
"os"
"strings"
)
// Reads all .txt files in the current folder
// and encodes them as strings literals in textfiles.go
func main() {
fs, _ := ioutil.ReadDir(".")
out, _ := os.Create("textfiles.go")
out.Write([]byte("package main \n\nconst (\n"))
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".txt") {
out.Write([]byte(strings.TrimSuffix(f.Name(), ".txt") + " = `"))
f, _ := os.Open(f.Name())
io.Copy(out, f)
out.Write([]byte("`\n"))
}
}
out.Write([]byte(")\n"))
}
すべての.txtファイルをexectutableにコンパイルするには:
$ go generate
$ go build -o main
これで、ディレクトリ構造は次のようになります。
main.go
main
scripts/includetxt.go
textfiles.go
a.txt
b.txt
Textfiles.goがgo generateおよびscript/includetxt.goによって生成された場所
package main
const (
a = `hello`
b = `world`
)
そしてメインを実行すると
$ ./main
hello
world
UTF8エンコードされたファイルをエンコードしている限り、これは問題なく動作します。他のファイルをエンコードしたい場合は、go言語(またはその他のツール)の能力をフルに活用してください。この手法を使用して hex encode png:sを1つの実行可能ファイルに変換しました。これには、includetxt.goを少し変更する必要があります。
string literal
は、テキストを定数または変数として定義します。文字列リテラルは、文字列を逆引用符で囲むことによって定義されます。例えば`string`。
例えば:
package main
import "fmt"
func main() {
const text = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit
amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante
hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet
vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut
libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a
semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis.
Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut
convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis
quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae
nisi at sem facilisis semper ac in est.
`
fmt.Println(text)
}
同じことを探していて、偶然出会った esc:静的アセットをGoに埋め込む (2014年11月19日までに)ここで、著者 Matt Jibson は、主張する他の3つの人気のあるパッケージを評価していますファイルの埋め込みを行うには:
そして、彼が最終的に独自のパッケージを思い付く理由を説明します。
だから、それらをすべて(この順序で)簡単に試した後、自然にマットの esc に落ち着きました。それは、箱から出して必要な唯一のものだったからです。 機能、つまり:
//go:generate
を介して作業を行うことができますポイント#2は私にとって重要であり、残りのパッケージは何らかの理由でうまく機能しませんでした。
EscのREADMEから:
escはgoプログラムにファイルを埋め込み、それらにhttp.FileSystemインターフェイスを提供します。
指定されたパスにある名前付きディレクトリの下に、すべての名前付きファイルまたは再帰的にファイルを追加します。出力ファイルは、標準ライブラリの外部のパッケージへの依存性がゼロのhttp.FileSystemインターフェースを提供します。
単純な関数を使用して、_go generate
_実行で外部テンプレートを読み取り、そこからGoコードを生成しました。テンプレートを文字列として返す関数が生成されます。次に、tpl, err := template.New("myname").Parse(mynameTemplate())
を使用して、返されたテンプレート文字列を解析できます
私はそのコードをgithubに配置しました。あなたは試してみたいかもしれません https://github.com/wlbr/templify
とてもシンプルですが、私にとってはとてもうまくいきます。
@CoreyOgburnコメントとこの Githubコメント に基づいて、次のスニペットが作成されました。
//go:generate statik -src=./html
package main
import (
_ "./statik"
"github.com/rakyll/statik/fs"
)
func statikFile() {
s, _ := fs.New() f, _ := s.Open("/tmpl/login.html") b, _ := ioutil.ReadAll(f) t, _ := template.New("login").Parse(string(b)) t.Execute(w, nil) }
そして走る
go generate
そしてその後
go build
ファイルを含むバイナリを作成する必要があります
チェック packr 、使用するのはとてもフレンドリー
package main
import (
"net/http"
"github.com/gobuffalo/packr"
)
func main() {
box := packr.NewBox("./templates")
http.Handle("/", http.FileServer(box))
http.ListenAndServe(":3000", nil)
}