本文へスキップ
BecomeCoder

Goコース · 第8章 実務のGo · レッスン35

embed・go:generate・reflect ― もう少し先の道具

ローカル実施

導入

最後に、頻度は高くないものの、Goのプロジェクトを読んでいるとしばしば出会う3つの機能を紹介します。今すぐ使いこなす必要はありませんが、「見たことがある」状態にしておくと、他人のコードを読むときに戸惑いません。

説明

embed は、静的ファイル(HTML・画像・設定ファイルなど)をコンパイル時にバイナリへ埋め込む仕組みです。

package main

import (
	_ "embed"
	"fmt"
)

//go:embed message.txt
var message string

func main() {
	fmt.Println(message) // message.txt の中身がそのまま入っている
}

//go:embed ファイル名 というコメントディレクティブ)を変数の直前に書くと、ビルド時にそのファイルの中身が変数に埋め込まれます。Webサーバーの静的ファイルを1つの実行ファイルに同梱して配布したいときなどに使われます。

go:generate は、コード生成ツールを呼び出すためのディレクティブです。

//go:generate mockgen -source=user.go -destination=mock_user.go

このコメントを書いておくと、go generate ./... コマンドを実行したときに指定したツール(例ではモック生成ツール)が走り、別のGoファイルを自動生成してくれます。「手で書くと大変な定型コードを、コマンド一発で作る」ための仕組みです。

reflect は、実行時に値の型情報を調べたり操作したりするパッケージです。

package main

import (
	"fmt"
	"reflect"
)

func main() {
	x := 42
	t := reflect.TypeOf(x)
	v := reflect.ValueOf(x)

	fmt.Println(t)        // int
	fmt.Println(v.Kind())  // int
}

encoding/json が構造体タグ(`json:"name"`)を読み取れるのも、内部で reflect を使って構造体のフィールド情報を実行時に調べているからです。ただし reflect を使ったコードは読みにくく遅くなりがちなので、実務でアプリケーションのロジックとして直接使う場面は多くありません。ライブラリの内部実装として触れることが多い、と覚えておけば十分です。

これでGoコースの実務編は終わりです。文法の基礎から標準ライブラリ、エラー処理・テストHTTPサーバー・ジェネリクスまで、実際の開発現場で必要になる土台を一通りたどりました。ここから先は、手元の環境や Go Playground で、実際に小さなツールやAPIサーバーを作りながら手を動かしてみてください。