return
}
p.Age++
fmt.Printf("%+vn", u)
}
输出:
{Name:q.yuhen Age:61}
也可以直接使用 Value.Int、Bool 等方法进行类型转换,但失败时会引发 pani,且不支持 ok-idiom。
复合类型对象设置示例:
func main() {
c := make(chan int, 4)
v := reflect.ValueOf(c)
if v.TrySend(reflect.ValueOf(100)) {
fmt.Println(v.TryRecv())
}
}
输出:
100 true
接口有两种 nil 状态,这一直是个潜在麻烦。解决方法是用 IsNil() 判断值是否为 nil。
func main() {
var a interface{} = nil
var b interface{} = (*int)(nil)
fmt.Println(a == nil)
fmt.Println(b == nil, reflect.ValueOf(b).IsNil())
}
输出:
true
false true
也可用 unsafe 转换后直接判断 iface.data 是否为零值。
func main() {
var b interface{} = (*int)(nil)
iface := (*[2]uintptr)(unsafe.Pointer(&b))
fmt.Println(iface, iface[1] == 0)
}
输出:
&[712160 0] true
让人很无奈的是,Value 里的某些方法并未实现 ok-idom 或返回 error,所以得自行判断返回的是否为 Zero Value。
func main() {
v := reflect.ValueOf(struct {name string}{})
println(v.FieldByName("name").IsValid())
println(v.FieldByName("xxx").IsValid())
}
输出:
true
false
三、方法
动态调用方法,谈不上有多麻烦。只须按 In 列表准备好所需参数即可。
type X struct {}
func (X) Test(x, y int) (int, error) {
return x + y, fmt.Errorf("err: %d", x + y)
}
func main() {
var a X
v := reflect.ValueOf(&a)
m := v.MethodByName("Test")
in := []reflect.Value{
reflect.ValueOf(1),
reflect.ValueOf(2),
}
out := m.Call(in)
for _, v := range out {
fmt.Println(v)
}
}
输出:
3
err: 3
对于变参来说,用 CallSlice() 要更方便一些。









