golang reflect - foolmacky/DevelopDocs GitHub Wiki
■ Goのreflectについて
- Goではreflectとinterface{}を使って型を抽象的に扱うことができる
- その際に登場するのは
- reflect.Value : 抽象的に値を扱う
- reflect.Type : 抽象的に型を扱う
- interface{} : 任意の値を扱う

- 実際の実装の場面で、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の型判定関数を使って、変換前にチェックする