Overview
タイトルの通りなんですが、Go の struct をするときにその struct のあるフィールドを参照型にすることがあると思います。
この参照型のフィールドに値を代入するために、プリミティブな型を参照型に変換するだけの関数を作成することがあるかと思いますが、そのために unexported な toIntPtr
みたいな関数を作成するのではなく func を使って代入することができるなーと思ったのでそのことについて書いてみます。
どう言うときに使うの?
主にテストを書くときのことを想定しています。
例えば、時刻を扱う表現で MySQL の DATETIME 型の初期値を NULL にしたいケースではフィールドの型を *time.Time
にするケースは多くあります。こういった struct を使ったテストをするときにシンプルに時刻を生成してフィールドにアサインしようとするとコンパイルエラーが発生してしまいます(※)
※ time.Time
と *time.Time
は別の型なので。
こう言うときにわざわざ参照型の変数をフィールドに代入するためだけに toDatetimePtr
みたいなメソッドを定義することがありますが、実装で使うならまだしもテストの時だけに使うためにこういった参照型変換関数を用意するのは微妙です。
Example
type User struct { BirthDay *time.Time }
みたいな User エンティティを使ったテストを書くときに
func TestUserXXXX(t *testing.T) { tests := [] struct { name string src User }{ {name: "xxxxx....", src: User{ BirthDay: toDatetimePtr(time.Now())} }, } } func toDatetimePtr(t time.Time) *time.Time { return &t }
わざわざ time.Time
の参照型である Birthday のためだけに toDatetimePtr
を定義するのはちょっと微妙なので以下のようにしたらいいのではないかなと思いました。
func TestUserXXXX(t *testing.T) { tests := [] struct { name string src User }{ { name: "xxxxx....", src: User{ BirthDay: func(t time.Time) *time.Time { return &t }(time.Now()), }, }, } }
まとめ
これを書いてる最中にじゃあ参照型の型を新しく定義すれば?と思いましたが、いずれにしても利用用途が限定的なケースにおいてあんまり書きたいコードではないなと思いました。
Go では通常の実装においても func をそのまま使うと有用なケースが多いですね。
追伸
func の方が func を呼び出すコストがかかるので使いどころは選ばないといけません。
教えてもらった以下の Compier Explore によると確かに func を持っている時の方がコストが高いです。