Goでサーバサイド導入
はじめに
1年後にGoを使う可能性があるため、勉強がてら久々のブログ更新をしてみようと思いました。
やることは、ほんとにチュートリアル程度のことなので、何もやったことないよーといった人にしか役立たないと思います。(どちらかといえば知見が欲しい)
Goについてはガチ初心者なので、間違った点などがあればご教授ください。
それではお勉強を始めます。
開発環境
Goのインストール
MacなのでHomebrewでインストールします。
$ brew install go
環境変数
環境変数なのですが、Go 1.11 から追加されたGo Modulesにより必要ない可能性もあるのですが念の為設定しておきます。(要らなければ飛ばしてください)
環境変数はconfig.fish
に以下を追記します。
# golang set -x GOPATH $HOME/go set -x PATH $PATH $GOPATH/bin
bashの場合は.bash_profile
に以下を追記で設定できると思います。(not 検証)
# golang export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin
これでGoの環境は揃いました。
プロジェクトの作成
今回は、先程述べたGo Modulesを使用してモジュール管理をしていきたいと思います。
このページを参考にさせていただきました。
blog.mmmcorp.co.jp
適当にディレクトリを作成して以下のコマンドを打ちます。
$ go mod init <プロジェクト名>
実際の私のプロジェクト名を入れた例はこちらになります。
$ go mod init github.com/tokutatsu/go-web-app-practice
そうすると、go.mod
ファイルが作成されます。
これで準備は整いました。
さぁコーディング
main.go
を作成してコードを書いていきます。
まずはHello Worldから
以下を実行してhttp://localhost:8080/hello
にアクセスするとHello World!を返してくれます。
package main import ( "fmt" "html/template" "net/http" ) func main() { http.HandleFunc("/hello", helloHandler) http.ListenAndServe(":8080", nil) } func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello World!") }
実行するには、Goはコンパイル言語なのでコンパイルして実行という形が一般的です。
しかし、Goではgo run
をすると自動でコンパイルと実行をしてくれるため今回はそちらを使用します。
ブラウザ
やcurlでhttp://localhost:8080/hello
にアクセスすると結果が確認できます。
レンダリング
次にhtml/templateを使ってレンダリングをしていきます。
text/templateというのもあるみたいですが、どうもhtml/templateのほうが良さげなので今回はそちらを使用します。
importにhtml/templatの追加が必要です。
先程のコードのfunc main()に以下を追加します。
http.HandleFunc("/template", templateHandler)
これは、ハンドラの関数を追加しただけです。
では、追加するハンドラの関数を定義していきます。
ここでは、テンプレートファイル(HTMLファイル)を読み込んでそれを描画しています。
また、tmpl.Execute()の第2引数に値を指定してあげることで、テンプレートに埋め込むことができます。
この埋め込みは、構造体やマップでも可能です。
func templateHandler(w http.ResponseWriter, r *http.Request) { tmpl := template.Must(template.ParseFiles("./views/index.html")) tmpl.Execute(w, nil) }
素朴なHTML(index.html)↓
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello</title> </head> <body> <h1>Hello World!</h1> </body> </html>
結果はこんな感じです。
埋め込みを利用したときには以下のようになります。
変更点は、func templateHandler()のtmpl.Execute(w, nil)
をtmpl.Execute(w, "tokutatsu")
にしたことと、index.html
の<h1>Hello World!</h1>
を<h1>Hello {{.}}!</h1>
にしただけです。(簡単)
jsonを返す
APIではjsonを返すことが多いのでやってみます。
まず、importにencoding/jsonを追加します。
次に、構造体を次のように定義してあげます。
type Human struct { Name string Age int }
そして、先ほどと同様にfunc main()で以下を追加。
http.HandleFunc("/json", jsonHandler)
そして、ハンドラの関数を次のように定義していきます。
はじめに先ほど定義した構造体を初期化します。
次に、jsonを返すためにはContent-Typeヘッダにapplication/jsonを指定する必要があるためセットします。
func jsonHandler(w http.ResponseWriter, r *http.Request) { my := Human{ Name: "tokutatsu", Age: 21, } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(my) }
curlで確認した結果がこちらです。
{"Name":"tokutatsu","Age":21}
うまくできましたね。
さいごに
Goの環境すらない状態からWebサーバを構築しました(超簡易)が、標準ライブラリでここまでできるので使い勝手はいいなぁと感じました。
ただ、パッケージの構成は自由度が高いためいい構成などがあれば教えて下さい。
これからいくつかのWebアプリを作りながら、設計などを詰めていければなと。
一応今回のもの↓