Go の 構造体のタグを取得する

備忘録。

json などで構造体のフィールドに付ける json:omitempty などのタグを取得する方法について。


構造体フィールドのタグは標準パッケージ reflect を使って実行時に取得する。

以下、構造体 Tagged のフィールド Foo に付いているタグを取得するサンプル。

package main

import (
    "fmt"
    "reflect"
)

type Tagged struct {
    Foo string `tagA:"aaa" tagB:"bbb,ccc"`
}

func main() {
    var tagged Tagged

    // 型情報を取得
    var t reflect.Type = reflect.TypeOf(tagged)

    // Foo のフィールド情報を取得
    var f reflect.StructField
    var ok bool
    f, ok = t.FieldByName("Foo")
    if !ok {
        panic("Foo is not found")
    }

    // Foo のタグを取得
    var tag reflect.StructTag
    tag = f.Tag

    // tagA の値を取得
    fmt.Printf("tagA: %#v\n", tag.Get("tagA")) // => "aaa"

    // tagB の値を取得
    fmt.Printf("tagB: %#v\n", tag.Get("tagB")) // => "aaa"

    // 存在しないタグに対しては空文字列を返す
    fmt.Printf("tagC: %#v\n", tag.Get("tagC")) // => ""

    // Lookup を使うと存在判定ができる
    _, ok = tag.Lookup("tagC")
    fmt.Printf("tagC exists: %#v\n", ok)
}

Gatling のシナリオをデバッグする

備忘録。

Scala DSL でシナリオを書けるパフォーマンステストツール Gatling を使い始めたが、シナリオをデバッグしたいことがままあるので、そのメモ。

バージョンは3.2。

続きを読む

t.Run で Go のテストをサブテストに分割する

備忘録。

Go のテスト関数内でサブテストに分割する方法について。

testing.TErrorSkip などのように関数で実装しているテストの制御を行うメソッドがあるが、サブテストに分割するためのメソッド Run も実装されている。以下のように使える:

func TestFoo(t *testing.T) {
  t.Run("Sub Test 1", func (t *testing.T) {
    if foo(1, 2) != 42 {
      t.Error("foo(1, 2) is not 42")
    }
  })
}

第1引数にサブテストの名前、第2引数にサブテストの内容を関数で渡す。

これは Table Driven Test で書く場合に有効である。

for i, tt := range cases {
  // テストケースごとにサブテストにする
  t.Run(fmt.Sprintf("case %d", i), func (t *testing.T) {
    ...
  })
}

これは t.Run を使わない場合と比べて以下のメリットがある

  • 必要に応じて各ケースに名前をつけられる
  • 独立したテストになるので、どのケースが成功してどのケースが失敗したかがわかりやすい