CDN や Nginx などの HTTP サーバーを介してリソースが個別に提供される通常の Web アプリケーションとは逆に、Go で小さなスタンドアロン Web アプリケーションを作成したいと考えていました。
ただし、パフォーマンスが重要な問題ではない場合、またはアプリケーションが低トラフィックを目的としている場合は、スタンドアロン アプリケーションを使用すると、単なる実行可能なバイナリであるため、展開と配布が簡素化されます。
Go アプリケーションにリソースを埋め込むために、いくつかのパッケージが利用可能です。
各ライブラリの詳細については詳しく説明しませんが、使いやすさと積極的なサポートのため、私はbindataアプローチを好みます。
まず、プロジェクトのfrontend/
ディレクトリ内にindex.html
を作成しましょう。
<html> <body> Hello, World! </body> </html>
プロジェクトのセットアップとテストする静的リソースが準備できたので、次のコマンドを使用してバインデータをインストールしましょう。
go get -u github.com/jteeuwen/go-bindata/...
Web アプリケーションのバックエンド コードを実行する準備ができました。 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 generate
呼び出されたときにgo-bindata
コマンドを実行できるようになります。バージョン 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
関数内にあり、この関数はリクエストを受け取り、パスが静的パスと一致するかどうかを確認します。チェックは、 bindata.go
ユーザーによって自動的にエクスポートされるAsset
関数を使用して行われます。リソースが存在しない場合は404
を返し、存在しない場合はリソースの内容を返します。
コードの残りの部分は、Web アプリケーションを作成し、 /
に対するすべての受信リクエストに一致するようにstatic_handler
テンプレートをバインドするためのものです。このコードを理解するのが難しい場合は、 http package
に関する Go の公式ドキュメントを確認してください。
Go がパッケージを処理する方法について簡単に思い出してください。識別子の名前の最初の文字が大文字で始まる場合、すべての識別子は同じ名前を持つ他のパッケージに自動的にエクスポートされます。
このルールに基づいて、 bindata.go
ファイルはmain
パッケージのAsset
機能を提供します。これにより、指定された名前のアセットがロードされて返されます。リソースが見つからない場合、またはロードできない場合は、エラーが返されます。