Skip to content

golang reflect

foolmacky edited this page May 12, 2023 · 1 revision

■ Goのreflectについて

  • Goではreflectとinterface{}を使って型を抽象的に扱うことができる
  • その際に登場するのは
    • reflect.Value : 抽象的に値を扱う
    • reflect.Type : 抽象的に型を扱う
    • interface{} : 任意の値を扱う
      reflect
  • 実際の実装の場面で、interface{}側に寄せるか、reflect側に寄せるか迷うことがあるが、interface{}側に寄せると、本来的にはtypeAssertionでpanicが発生するケースをちゃんとハンドリングしないといけないので、reflect側に寄せれば、変換前にresとexpの型の互換性をチェックできて良い気がする。
//interface{}側に寄せる
func getField(v interface{}, field string) string {
    r := reflect.ValueOf(v)
    f := reflect.Indirect(r).FieldByName(field)
    fieldValue := f.Interface()

    switch v := fieldValue.(type) {
    case int64:
        return strconv.FormatInt(v, 10)
    case int32:
        return strconv.FormatInt(int64(v), 10)
    case int:
        return strconv.FormatInt(int64(v), 10)
    case string:
        return v
    case bool:
        if v {
            return "true"
        }
        return "false"
    case time.Time:
        return v.String()
    default:
        return ""
    }
}

//feflect.Valueを維持する
var timeKind = reflect.TypeOf(time.Time{}).Kind()

func getField(v interface{}, field string) string {
    r := reflect.ValueOf(v)
    f := reflect.Indirect(r).FieldByName(field)
    t := f.Kind()

    switch t {
    case reflect.Int, reflect.Int64:
        return strconv.FormatInt(f.Int(), 10)
    case reflect.String:
        return f.String()
    case reflect.Bool:
        if f.Bool() {
            return "true"
        }
        return "false"
    case timeKind:
        // do whatever
    case default:
        return ""
    }
}
  • typeAssertionで、2つの値をリターンする関数で、変換できるか判定できる
x, ok := i.(T)
  • reflectの型変換も、String()以外はpanicを起こすので、reflectの型判定関数を使って、変換前にチェックする

Clone this wiki locally