变量的类型输出如下:
Type is and kind is slice
Contained type:
Type is int and kind is int
Type is string and kind is string
Type is and kind is ptr
Contained type:
Type is string and kind is string
Type is Foo and kind is struct
Field 1 name is A type is int and kind is int
Tag is tag1:"First Tag" tag2:"Second Tag"
tag1 is First Tag tag2 is Second Tag
Field 2 name is B type is string and kind is string
Type is and kind is ptr
Contained type:
Type is Foo and kind is struct
Field 1 name is A type is int and kind is int
Tag is tag1:"First Tag" tag2:"Second Tag"
tag1 is First Tag tag2 is Second Tag
Field 2 name is B type is string and kind is string
Run in go playground: https://play.golang.org/p/lZ97yAUHxX
使用反射创建新实例
除了检查变量的类型外,还可以使用反射来读取,设置或创建值。首先,需要使用refVal := reflect.ValueOf(var) 为变量创建一个reflect.Value实例。如果希望能够使用反射来修改值,则必须使用refPtrVal := reflect.ValueOf(&var);获得指向变量的指针。如果不这样做,则可以使用反射来读取该值,但不能对其进行修改。
一旦有了reflect.Value实例就可以使用Type()方法获取变量的reflect.Type。
如果要修改值,请记住它必须是一个指针,并且必须首先对其进行解引用。使用refPtrVal.Elem().Set(newRefVal)来修改值,并且传递给Set()的值也必须是reflect.Value。
如果要创建一个新值,可以使用函数newPtrVal := reflect.New(varType)来实现,并传入一个reflect.Type。这将返回一个指针值,然后可以像上面那样使用Elem().Set()对其进行修改。
最后,你可以通过调用Interface()方法从reflect.Value回到普通变量值。由于Go没有泛型,因此变量的原始类型会丢失;该方法返回类型为interface{}的值。如果创建了一个指针以便可以修改该值,则需要使用Elem().Interface()解引用反射的指针。在这两种情况下,都需要将空接口转换为实际类型才能使用它。
下面的代码来演示这些概念:
type Foo struct {
A int `tag1:"First Tag" tag2:"Second Tag"`
B string
}
func main() {
greeting := "hello"
f := Foo{A: 10, B: "Salutations"}
gVal := reflect.ValueOf(greeting)
// not a pointer so all we can do is read it
fmt.Println(gVal.Interface())
gpVal := reflect.ValueOf(&greeting)
// it's a pointer, so we can change it, and it changes the underlying variable
gpVal.Elem().SetString("goodbye")
fmt.Println(greeting)
fType := reflect.TypeOf(f)
fVal := reflect.New(fType)
fVal.Elem().Field(0).SetInt(20)
fVal.Elem().Field(1).SetString("Greetings")
f2 := fVal.Elem().Interface().(Foo)
fmt.Printf("%+v, %d, %sn", f2, f2.A, f2.B)
}
他们的输出如下:
hello
goodbye
{A:20 B:Greetings}, 20, Greetings









