package main import ( "reflect" ) type privateOne struct { m1 string m2 string } func sub(from interface{}) interface{} { t := reflect.ValueOf(from).Elem().Type() obj := reflect.New(t) p := obj.Elem() p.Field(0).SetString("foo") p.Field(1).SetString("bar") return obj.Interface() } func main() { value := sub(&privateOne{"a", "b"}) if val, ok := value.(*privateOne); ok { println(val.m1, val.m2) } else { println(reflect.TypeOf(value).String()) } }
実行してみよう!
$ ./privateStruct.exe panic: reflect: reflect.Value.SetString using value obtained using unexported field goroutine 1 [running]: reflect.flag.mustBeAssignable(0x1b8) c:/go/src/reflect/value.go:231 +0x1fa reflect.Value.SetString(0x478260, 0xc042052040, 0x1b8, 0x492f30, 0x3) c:/go/src/reflect/value.go:1551 +0x32 main.sub(0x473aa0, 0xc042052020, 0x0, 0x4660bc) C:/Users/hymko/go/src/github.com/zetamatta/experimental/privateStruct/main.go:16 +0x141 main.main() C:/Users/hymko/go/src/github.com/zetamatta/experimental/privateStruct/main.go:22 +0x97 exit status 2
普通に怒られた。ちなみに m1 → M1 、m2 → M2 などとフィールドの名前を変えると、期待動作する。
$ ./privateStruct.exe foo bar
仕様動作を無理やり超えようとしたので、無理かなーとは思ってたんだが、やっぱりか!残念!(強引な解決が無理なら、ライブラリの開発元への「お願い」が通るのを期待するしかないなー)