package main
import("fmt""reflect")// Person 测试结构体type Person struct{
Name string`json:"name"`
Age int}// Stu 测试结构体type Stu struct{
Score int
Person
}funcmain(){// 实例化
stu1 := Stu{
Score:100,
Person: Person{
Name:"Tim",
Age:30,},}// 拿到 Type
t := reflect.TypeOf(stu1)// 根据索引取属性信息
sf1 := t.Field(1)
fmt.Println(sf1)// {Person main.Person 8 [1] true}, 这个 true 说明 stu 结构体中的 person 结构体是匿名引用// 根据字符串取属性信息
sf2, ok := t.FieldByName("Score")if ok {
fmt.Println(sf2)}// 根据索引去嵌套的属性
sf3 := t.FieldByIndex([]int{1,0})// 实际上是找到了 t[1][0], 也就是 stu1 的 Name 属性
fmt.Println(sf3)// 上边三个返回值是 StructField 结构体// 取详细的信息
fmt.Println(sf3.Name)
fmt.Println(sf3.Type)
fmt.Println(sf3.Index)
fmt.Println(sf3.Tag)// 如果结构体定义的时候, 声明了 Tag, 就会返回, 反之则为空}
Method() – 方法相关
package main
import("fmt""reflect")type stu struct{
name string
age int
score int}func(s stu)Study()string{return"study"}func(s *stu)ChangeScore(newScore int){
s.score = newScore
}funcmain(){
stu1 := stu{
name:"Tim",
age:18,
score:100,}
t := reflect.TypeOf(stu1)// 获取方法数量, 这个方法只统计暴露给外部,并且是值接收者的方法
numMethod := t.NumMethod()for i :=0; i < numMethod; i++{// 根据索引
fmt.Println(t.Method(i).Name)}// 根据字符串取方法
m, ok := t.MethodByName("Study")if ok {
fmt.Println(m.Name)}}
源码
Type接口
type Type interface{String()string// 直接打印就是这个Kind() Kind // 返回种类Name()string// 返回类型Elem() Type // 获取指针对应的值NumField()int// 获取属性数量Field(i int) StructField // 根据索引获取属性FieldByIndex(index []int) StructField // 根据索引获取多个属性FieldByName(name string)(StructField,bool)// 根据字符串获取属性NumMethod()int// 获取方法数量Method(int) Method // 根据索引获取方法MethodByName(string)(Method,bool)// 根据字符串获取方法FieldByNameFunc(match func(string)bool)(StructField,bool)Align()intFieldAlign()intPkgPath()stringSize()uintptrImplements(u Type)boolAssignableTo(u Type)boolConvertibleTo(u Type)boolComparable()boolBits()intChanDir() ChanDir
IsVariadic()boolIn(i int) Type
Key() Type
Len()intNumIn()intNumOut()intOut(i int) Type
common()*rtype
uncommon()*uncommonType
}
// Field, FieldByIndex, FieldByName 返回值都是StructFieldtype StructField struct{// Name is the field name.
Name string// PkgPath is the package path that qualifies a lower case (unexported)// field name. It is empty for upper case (exported) field names.// See https://golang.org/ref/spec#Uniqueness_of_identifiers
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结构体源码
type Method struct{// Name is the method name.// PkgPath is the package path that qualifies a lower case (unexported)// method name. It is empty for upper case (exported) method names.// The combination of PkgPath and Name uniquely identifies a method// in a method set.// See https://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
PkgPath string
Type Type // method type
Func Value // func with receiver as first argument
Index int// index for Type.Method}
ValueOf - 拿到 Value
package main
import("fmt""reflect")funcmain(){
a :=10// 拿到 Value
v := reflect.ValueOf(a)// 这里输出的就是值
fmt.Println(v)}
Value 实现的方法
Kind() - 值的类型
package main
import("fmt""reflect")funcmain(){var a int8
a =18// 拿到 Value
v := reflect.ValueOf(a)// 拿到值对应的类型
t := v.Kind()switch t {// 可以写到一起case reflect.String:
fmt.Println("这是 string")case reflect.Int:// 注意, 这个 int 是区分 int8, int16, int32 的
fmt.Println("这是 int")default:
fmt.Println("不支持的类型")}}
Elem() - 修改值
package main
import("fmt""reflect")funcmain(){var a int
a =18// 拿到 Value
e := reflect.ValueOf(&a).Elem()// 修改值的情况下, ValueOf 的参数必须是指针// 拿到值对应的类型
t := e.Kind()switch t {// 可以写到一起case reflect.String:
e.SetString("经过修改")case reflect.Int:// 注意, 这个 int 是区分 int8, int16, int32 的
e.SetInt(123)default:
fmt.Println("不支持的类型")}
fmt.Println(a)}