Go言語でGO(勉強記録4)
そろそろ基本文法は置いといて、なんとなく遊べそうなものを作ろうと思います。
特にサーバーバックエンドでも使われてるっぽいので、目指す方向はそっちで。
モジュール管理 go modules
pyenvみたいな感じ?の、モジュール管理機能だそうです。
プロジェクトフォルダにて、以下のコマンドを実行。(当方Windows10)
> go mod init pokete.dev/first
pokete.dev/first
の部分はモジュール名です。

実行すると、go.mod
というファイルができました。
たぶんここに外部パッケージが増えていくんだとおもう。

ちなみにファイルを見ての通り、go 1.16を使っていますが、Modules周りで大きな変更があったようです。
とりあえず初心者なので、以下の理解をしておきます。
- go.modの更新は基本的に
go mod tidy
で行う。従来はgo buildなどでも書き換わっていた。 - 外部バイナリ(=buildして出来たexeファイル)のインストールには
go install
を使う。従来はgo getを使っていたが、そのうち消えるらしい。 - バイナリじゃないパッケージの導入は
go get
を使う。
Gin
ジン。
Go言語で一番有名なWebフレームワーク、という理解。
日本での案件数も多いらしい。知らんけど。
入れてみる
go get github.com/gin-gonic/gin
go.modに行が増えました。

試しに使ってみる
以降は↓のQiitaに概ね乗っかります(時々脱線しようと思います)
ファイル構成は、こんな感じにしました。

前回まで使っていたhelloworld.goと同exeは、oldへ退避。
代わりにcontent/index.htmlと、main.goを作りました。
content/index.htmlは、こんなかんじ。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TestHtml</title>
</head>
<body>
This is My Homepage!!
</body>
</html>
main.goは、こんなかんじ。
※Go言語のシンタックスハイライターを持ち合わせていない…
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.LoadHTMLGlob("content/*.html")
router.GET("/", func(ctx *gin.Context) {
ctx.HTML(200, "index.html", gin.H{})
})
router.Run()
}
一旦よく分からないまま書いてみて、go run main.go
で動かしてみます。
実行すると、こんなかんじ。
(ネットワーク通信プログラムなので、起動時にWindowsが確認してくる)
(Avastさんが怪しんでCaptureするので、起動まで時間はかかる)

これで localhost:8080 にアクセスすると、

やったぜ。
コンソールのほうにも、アクセスログが出てきました。

サーバはCtrl+Cで止めて、プログラムの中身を見てみます。
コードを見てみる
func main() {
router := gin.Default() // デフォルトのルータを生成(そのまま)
router.LoadHTMLGlob("content/*.html") // レンダリングするHTMLパスを指定
router.GET("/", func(c *gin.Context) {
// "/"に対してGETリクエストがあったときになだれ込む
// 引数cはContext
c.HTML(200, "index.html", gin.H{})
// c.HTMLの引数1つめはHTTPステータスコード
// 2つめはベースとして利用するテンプレート
// 3つめはテンプレートを埋めるモノ
// gin.Hはmap[string]interface{}のショートカットらしい
})
router.Run() // サーバ機能を開始
// Run()の引数としてアドレスを取れる
// なおポート番号は "PORT" の環境変数にセットして代用可
}
分かった範囲を、コメントで書いてみました。
LoadHTMLGlobとgin.H{}は次の節でもう少し見てみることに。
router.Run()のカッコ内は、何も書かない&環境変数PORTが空だとrouter.Run(":8080")
引数が空で、環境変数PORTに何か入っているとrouter.Run(os.Getenv("PORT"))
引数があると、その引数の値がエンドポイントになる模様。
テンプレート
さっきのindex.htmlをこう変えて
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TestHtml</title>
</head>
<body>
This is My {{.text}}!! <!-- Homepageを{{.text}}にした -->
</body>
</html>
main.goのmain()をこう変えてみました
func main() {
router := gin.Default()
router.LoadHTMLGlob("content/*.html")
router.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{"text": "hogehoge"}) // {}に追記
})
router.Run()
}
すると、HTMLの{{.text}}に、hogehogeが入ります。
なるほどね。

パスパラメータとクエリストリング
APIを作るにあたって必須の要素。
HTMLはシンプルにしました。
<body>
{{.text}}!!
</body>
main()はこんな感じ
func main() {
router := gin.Default()
router.LoadHTMLGlob("content/*.html")
router.GET("/:param", func(c *gin.Context) {
param := c.Param("param")
query := c.DefaultQuery("query", "くえりさんぷる")
c.String(200, "Param: %s, Query: %s", param, query)
})
router.Run()
}
これで、 localhost:8080/test にアクセスすると、testがParamで取れているのが分かります。

localhost:8080/test?query=piyo にアクセスすると、さらにpiyoがQueryで取れているのが分かります。
ちなみにc.DefaultQuery()はデフォルト値を入れられるタイプ、c.Query()はデフォルト値がないタイプのようです。

次回はこれらを使って、ちょっとしたアプリケーションを作ってみようかと。
ディスカッション
コメント一覧
まだ、コメントがありません