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)}