目錄
2、變量、interface{},reflect.Value相互轉化
反射可以在運行時動態獲取變量的各種信息,比如變量的類型、類別。如果是結構體變量,還可以獲取到結構體本身的信息(包括結構體字段、方法)。通過反射,可以修改變量的值,可以調用關聯的方法
1、通過反射獲取到傳入變量的type,值、kind
Type是類型,Kind是類別【最原始的數據類型】,Type和Kind可能相同,也可能不同
- Eg: var num int = 10,num的Type是int,Kind也是int
- Eg: var stu Student,stu 的Type是model.Student,Kind是struct
- reflect.TypeOf(變量名):獲取變量的類型,返回reflect.Type類型
- reflect.ValueOf(變量名):獲取變量的值,返回reflect.Value類型reflect.Value,是一個結構體類型
兩種方式可以獲取到Kind
- reflect.TypeOf(變量名).Kind()
- reflect.ValueOf(變量名).Kind()
注意:如果傳入的interface是10,那麼它的值類型是reflect.Value,不等同於int,如果進行運算,需要先
2、變量、interface{},reflect.Value相互轉化
上述將interface{}轉化成需要類型的方式除了斷言(加入對返回值的判斷)外還可以採用switch方式
- interface{} -> reflect.Value:rValue := reflect.ValueOf(b)
- reflect.Value -> interface{}:iV := rValue.Interface()
- interface{} -> 變量:num3 := iV.(int)
3、反射獲取結構體內容
獲取結構體字段
獲取方法並調用:
修改值:
4、反射最佳實踐
type Monster struct {
Name string `json:"name"`
Age int `json:"monster_age"`
Score float32 `json:"成績"`
Sex string
}
//返回兩個數的和
func (s Monster) GetSum(n1, n2 int) int {
return n1 + n2
}
//接收四個值,給s賦值
func (s Monster) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
}
//顯示s的值
func (s Monster) Print() {
fmt.Println("----start----")
fmt.Println(s)
fmt.Println("----end----")
}
//使用反射獲取結構體內容
func TestStruct(a interface{}) {
typ := reflect.TypeOf(a)
val := reflect.ValueOf(a)
kd := val.Kind()
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
//獲取到該結構體有幾個字段
num := val.NumField()
fmt.Printf("struct has %d fields\n", num)
//變量結構體的所有字段
for i := 0; i < num; i++ {
fmt.Printf("Filed %d:值爲=%v\n", i, val.Field(i))
//獲取到struct標籤:注意需要通過reflect.Type來獲取tag
tagVal := typ.Field(i).Tag.Get("json")
//如果該字段屬於tag標籤就顯示,否則就不顯示
if tagVal != "" {
fmt.Printf("Filed %d:tag 爲=%v\n", i, tagVal)
}
}
//獲取到該結構體有多少個方法
numOfMethod := val.NumMethod()
fmt.Printf("struct has %d methods\n", numOfMethod)
//var params []reflect.Value
//方法的默認順序是按照函數名的排序
val.Method(1).Call(nil) //獲取到第二個方法,調用它
//調用結構體的第一個方法
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := val.Method(0).Call(params) //Call方法的參數是 []reflect.Value,返回 []reflect.Value
fmt.Println("res=", res[0].Int()) //返回的結果是[]reflect.Value
}
//修改值
func UpdateStruct(a interface{}) {
val := reflect.ValueOf(a)
val.Elem().Field(0).SetString("白象精")
}
func main() {
var a Monster = Monster{
Name: "黃鼠狼精",
Age: 400,
Score: 30.8,
}
TestStruct(a)
UpdateStruct(&a)
fmt.Println(a)
}