2017年にGoでWebアプリを作成します。 パート4


このパートでは、非常に単純化されたGo Webアプリケーションの欠落している場所について簡単に説明します。


HTTPハンドラーラッパー


少し振り返ります。「ミドルウェア」という言葉は好きではありません。 ラッパーの概念は計算の開始以来存在していたため、新しい単語を考案する必要はないと思います。


しかし、それはさておき、特定のURLの認証が必要だとしましょう。 これで、メインページハンドラは次のようになります。


func indexHandler(m *model.Model) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, indexHTML) }) } 

http.Handlerを引数として取り、(異なる) http.Handlerを返す関数を書くことができます。 返されたハンドラーは、ユーザーがm.IsAuthenticated()を使用して認証されているかどうかをm.IsAuthenticated()そこで何が起きても)、ユーザーをログインページにリダイレクトするか、 ServeHTTP()メソッドを呼び出して元のハンドラーを実行します。


 func requireLogin(h http.Handler, m *model.Model) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !m.IsAuthenticated(r) { http.Redirect(w, r, loginURL, http.StatusFound) return } h.ServeHTTP(w, r) }) } 

これを念頭に置いて、ハンドラーの登録は次のようになります。


  http.Handle("/", requireLogin(indexHandler(m), m)) 

このようにして、必要な数のレイヤーでハンドラーをラップできます。これは非常に柔軟なアプローチです。 ヘッダーの設定から出力の圧縮まで、すべてをラッパーで実行できます。 また、必要な引数、たとえば*model.Modelを渡すこともできます。


URLのパラメーター


ある時点で、URLにパラメーターが必要になる場合があります(例: /Person/3 )。ここで、 3は個人の識別子です。 Go標準ライブラリはこのために何も提供していないため、このタスクは開発者の課題として残されています。 そのようなことを担当するソフトウェアコンポーネントはMuxと呼ばれます。 「マルチプレクサ」または「ルーター」。非標準の実装に置き換えることができます。 ルーターは、 ServeHTTP()メソッドも実装します。これは、http.Handlerインターフェースを満たす、つまりハンドラーであることを意味します。


非常に人気のあるルーターオプションはGorilla Muxです。 彼は、より柔軟性が必要な場所で、パス全体を委任することができます。 たとえば、 /person以下のすべてがGorillaルーターによって処理され、すべて認証されるようにしたい場合、次のようになります。


  // import "github.com/gorilla/mux" pr := mux.NewRouter().PathPrefix("/person").Subrouter() pr.Handle("/{id}", personGetHandler(m)).Methods("GET") pr.Handle("/", personPostHandler(m)).Methods("POST") pr.Handle("/{id}", personPutHandler(m)).Methods("PUT") http.Handle("/person/", requireLogin(pr)) 

注:最後のスラッシュは重要であり、それらがいつ必要になるかについての規則は少しわかりにくいことがわかりました。


さらに多くのルーター/マルチプレクサの実装があります。 すばらしい点は、フレームワークに縛られることなく、自分に最も適したルーターを選択するか、独自のルーターを作成できることです(簡単に実装できます)。


静的処理


Goの最もエレガントな点の1つは、コンパイルされたプログラムが単一のバイナリファイルであり、多くのスクリプト言語やコンパイルされた言語の場合でもよくあるような大量のファイルではないことです。 ただし、プログラムが静的ファイル(JS、CSS、画像、およびその他のファイル)に依存している場合、展開中にそれらをサーバーにコピーする必要があります。


プログラムのこの特徴的な機能(「1つのバイナリ」)を保存できます。これには、バイナリファイル自体の一部としての静的要素も含まれます。 これを行うために、 go-bindataプロジェクトと彼のne go-bindata-assetsfsがあります。


バイナリファイルに静的にパックgo buildことは、 go buildできることをやや上回るgo build 、これを処理する何らかのスクリプトが必要です。 個人的には、試された真の「 makemakeを使用することを好みます。Goプロジェクトで「Makefile」が表示されることは珍しくありません。


適切なMakefileルールの例を次に示します。


 ASSETS_DIR = "assets" build: @export GOPATH=$${GOPATH-~/go} && \ go get github.com/jteeuwen/go-bindata/... github.com/elazarl/go-bindata-assetfs/... && \ $$GOPATH/bin/go-bindata -o bindata.go -tags builtinassets ${ASSETS_DIR}/... && \ go build -tags builtinassets -ldflags "-X main.builtinAssets=${ASSETS_DIR}" 

このルールは、 bindata.goファイルを作成します。このファイルは、 bindata.goと同じディレクトリに配置され、それに応じてmainパッケージの一部になります。 main.go何らかの方法で静的ファイルが埋め込まれていることを発見します-これはトリック-ldflags "-X main.builtinAssets=${ASSETS_DIR}"-ldflags "-X main.builtinAssets=${ASSETS_DIR}"ため、コンパイル時に変数に値を割り当てることができます。 これは、コードがbuiltinAssets値をチェックして、 builtinAssets何をするかを決定できるようになったことを意味します。たとえば、


  if builtinAssets != "" { log.Printf("Running with builtin assets.") cfg.UI.Assets = &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: builtinAssets} } else { log.Printf("Assets served from %q.", assetsPath) cfg.UI.Assets = http.Dir(assetsPath) } 

2番目に重要なことは、 builtinassetsというbuiltinassetsを定義すること builtinassets 。 また、それについてgo-bindataに伝えます。これは、「builtinassetsがインストールされている場合にのみコンパイルする」ことを意味し、これによりbindata.go (Goコードの形式で静的を含む)のコンパイルに必要な条件を制御できます。


JavaScriptの事前翻訳


最後に(重要ではなく、順番に)、Web静的のパッケージ化について簡単に説明します。 まったく新しいシリーズの記事でこれを適切に説明するのに十分な資料であり、Goとは関係ありません。 しかし、少なくともいくつかのポイントをリストすることができます。



おわりに


この4部構成のシリーズで説明している例では、Goは確かに輝いていますが、JavaScriptはそうではありません。 しかし、すべてを機能させるために最初の困難を克服するとすぐに、React / JSXはシンプルで、おそらく作業が快適になりました。


これで私はおそらく終了します。 記事がお役に立てば幸いです。



Source: https://habr.com/ru/post/J329622/


All Articles