reflect,反射。
利用reflect,可以得到一個struct的相關資訊。
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (u User) Hello(name string) {
fmt.Printf("hello %s, my name is %s\n", name, u.Name)
}
type Manager struct {
User
title string
}
func main() {
// modify variable through reflect
//x := 123
//v := reflect.ValueOf(&x)
//v.Elem().SetInt(234)
//fmt.Println(x)
u := User{1, "xiaoming", 12}
u.Hello("atom")
// call method through reflect
v := reflect.ValueOf(u)
mv := v.MethodByName("Hello")
args := []reflect.Value{reflect.ValueOf("jack")}
mv.Call(args)
Info(u)
Set(&u)
Info(u)
m := Manager{User{1, "xiaoming", 12}, "rd"}
// get nested struct field
t := reflect.TypeOf(m)
fmt.Printf("%#v\n", t.Field(0))
fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0}))
}
func Info(i interface{}) {
t := reflect.TypeOf(i)
if t.Kind() != reflect.Struct {
fmt.Println("Type Error")
return
}
fmt.Println("Type:", t.Name())
v := reflect.ValueOf(i)
// get fields
fmt.Println("Fields:")
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
val := v.Field(i).Interface()
fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, val)
}
// get methods
fmt.Println("Methods:")
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Printf("%6s: %v\n", m.Name, m.Type)
}
}
func Set(i interface{}) {
v := reflect.ValueOf(i)
if v.Kind() != reflect.Ptr || !v.Elem().CanSet() {
fmt.Println("Error")
return
} else {
v = v.Elem()
}
f := v.FieldByName("Name")
if !f.IsValid() {
fmt.Println("Bad Field")
}
if f.Kind() == reflect.String {
f.SetString("byebye")
}
}
輸出如下:
hello atom, my name is xiaoming
hello jack, my name is xiaoming
Type: User
Fields:
Id: int = 1
Name: string = xiaoming
Age: int = 12
Methods:
Hello: func(main.User, string)
Name: string = byebye
reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x10d9e00), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}
reflect.StructField{Name:"Id", PkgPath:"", Type:(*reflect.rtype)(0x10c4e60), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}
需要注意的一個地方是:
結構體的field首字母需要大寫,否則會報錯"panic: reflect.Value.Interface: cannot return value obtained from unexported field or method"
參考資料
Go程式設計基礎