import (
"fmt"
"reflect"
)
type Foo struct {
X string
Y int
}
func main() {
var i int = 123
var f float32 = 1.23
var l []string = []string{"a", "b", "c"}
fmt.Println(reflect.TypeOf(i)) //int
fmt.Println(reflect.TypeOf(f)) //float32
fmt.Println(reflect.TypeOf(l)) //[]string
var foo Foo
fmt.Println(reflect.TypeOf(foo)) //main.Foo
}
查看reflect包的源代码可以看到,reflect.Type的定义如下:
1234567891011121314
type Type interface {
Align() int
FieldAlign() int
Method(int) Method
MethodByName(string) (Method, bool)
NumMethod() int
Name() string
String() string
Elem() Type
Field(i int) StructField
FieldByName(name string) (StructField, bool)
Len() int
.....
}
type Foo struct {
X string
Y int
}
func (f Foo) do() {
fmt.Printf("X is: %s, Y is: %d", f.X, f.Y)
}
func main() {
var s string = "abc"
fmt.Println(reflect.TypeOf(s).String()) //string
fmt.Println(reflect.TypeOf(s).Name()) //string
var f Foo
typ := reflect.TypeOf(f)
fmt.Println(typ.String()) //main.Foo
fmt.Println(typ.Name()) //Foo ,返回结构体的名字
}
var f Foo
typ := reflect.TypeOf(f)
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fmt.Printf("%s type is :%s\n", field.Name, field.Type)
}
//x type is :string
//y type is :int
field2, _ := typ.FieldByName("x") //等价于typ.Field(0),返回的也是StructField对象
fmt.Println(field2.Name) // x
Type的Field是一个StructFiled对象:
12345678910
type StructField struct {
Name string
PkgPath string
Type Type // field type
Tag StructTag // field tag string
Offset uintptr // offset within struct, in bytes
Index []int // index sequence for Type.FieldByIndex
Anonymous bool // is an embedded field
}
Method相关的方法
12345678
var f Foo
typ := reflect.TypeOf(f)
fmt.Println(typ.NumMethod()) //1, Foo 方法的个数
m := typ.Method(0)
fmt.Println(m.Name) //do
fmt.Println(m.Type) //func(main.Foo)
fmt.Println(m.Func) //<func(main.Foo) Value>, 这个返回的是reflect.Value对象,后面再讲
type Foo struct {
X string
Y int
}
func (f Foo) do() {
fmt.Printf("X is: %s, Y is: %d", f.X, f.Y)
}
func main() {
var i int = 123
var f = Foo{"abc", 123}
var s = "abc"
fmt.Println(reflect.ValueOf(i)) //<int Value>
fmt.Println(reflect.ValueOf(f)) //<main.Foo Value>
fmt.Println(reflect.ValueOf(s)) //abc
//Value.String()方法对string类型的数据做了特殊处理,会直接返回字符串的值。
//其它类型对象返回的格式都是"<Type% Value>"
}
var foo = Foo{"abc", 123}
val := reflect.ValueOf(foo)
fmt.Println(val.FieldByName("y")) //<int Value> interface.Value对象
typ := reflect.Typeof(foo)
fmt.Println(typ.FieldByName("y")) //{ <nil> 0 [] false} false StructField对象
12345678910111213
func main() {
var f = Foo{"abc", 123}
rv := reflect.ValueOf(f)
rt := reflect.TypeOf(f)
for i := 0; i < rv.NumField(); i++ {
fv := rv.Field(i)
ft := rt.Field(i)
fmt.Printf("%s type is :%s ,value is %v\n", ft.Name, fv.Type(), fv.Interface())
}
}
//X type is :string ,value is abc
//Y type is :int ,value is 123
设置Value的值
要设置reflect.Value的值还颇费周折,不能直接对Value进行赋值操作
12345678
var s = "abc"
fv := reflect.ValueOf(s)
fmt.Println(fv.CanSet()) //false
// fv.SetString("edf") //panic
fv2 := reflect.ValueOf(&s)
fmt.Println(fv2.CanSet()) //false
// fv2.SetString("edf") //panic
func main() {
var i int = 123
fv := reflect.ValueOf(i)
fe := reflect.ValueOf(&i).Elem() //必须是指针的Value才能调用Elem
fmt.Println(fe) //<int Value>
fmt.Println(fv) //<int Value>
fmt.Println(fv == fe) //false
fmt.Println(fe.CanSet()) //true
fe.SetInt(456)
fmt.Println(i) //456
}
Method
这个是reflect一个比较经典的使用场景,在知道对象方法名的情况下,调用对象的方法。
1234567891011121314151617
type Foo struct {
X string
Y int
}
func (f Foo) Do() {
fmt.Printf("X is: %s, Y is: %d\n", f.X, f.Y)
}
func main() {
var foo = &Foo{"abc", 123}
reflect.ValueOf(foo).MethodByName("Do").Call([]reflect.Value{})
}
//方法名Do必须是大写的,否则会抛异常