iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
0
自我挑戰組

golang初探系列 第 26

day26-Reflect(反射) Package 介紹

  • 分享至 

  • xImage
  •  

在 php、java 語言反射機制在框架當中常常運用,用於提供實體化物件
在 golang 可以在運行時動態獲取變數的各種信息,比如說變數的類型、類別

  • 如果是 struct 的變數,還可以獲取 feild 及 strcut func method
  • 通過 reflect 可以修改變數的 value,可以調用關聯的方法

Reflect

Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types. The typical use is to take a value with static type interface{} and extract its dynamic type information by calling TypeOf, which returns a Type.
A call to ValueOf returns a Value representing the run-time data. Zero takes a Type and returns a Value representing a zero value for that type.

TypeOf

使用 reflect.TypeOf() 可以獲得任意值得類型對象

package main

import (
	"fmt"
	"reflect"
)

func reflectType(x interface{}) {
	v := reflect.TypeOf(x)
	fmt.Printf("type:%v\n", v)
	//如果 array、slice、map、pointer name 為空
	fmt.Printf("name:%v\n", v.Name())
	fmt.Printf("kind:%v\n", v.Kind())

}
func main() {
	var a float32 = 3.14
	reflectType(a)

	var b int64 = 100
	reflectType(b)
	var c = make([]int, 10, 10)
	reflectType(c)

}

ValueOf

使用 reflect.ValueOf() 可以獲得任意值得 value 對象

package main

import (
	"fmt"
	"reflect"
)

func reflectValue(x interface{}) {
	fmt.Println("x :", x)
	v := reflect.ValueOf(x)
	fmt.Printf("value :%v\n", v)
	fmt.Printf("kind:%v\n", v.Kind())

}
func main() {
	var a float32 = 3.14
	reflectValue(a)

	var b int64 = 100
	reflectValue(b)
	var c = make([]int, 10, 10)
	reflectValue(c)

}

通過反射設置變數的值

想要在 func 中透過反射修改變數值,需注意函數參數傳遞是 call by value ,必須傳遞變數的 address 才能修改變數值,而反射中使用 Elem() 方法來獲取 pointer 對應的值

package main

import (
	"fmt"
	"reflect"
)

func reflectSetValue(x interface{}) {
	v := reflect.ValueOf(x)
	fmt.Println(v.Elem())
	if v.Elem().Kind() == reflect.Int64 {
		v.Elem().SetInt(200)
	}
}
func main() {

	var b int64 = 100
	//需傳 adress 否則會panic
	reflectSetValue(&b)
	fmt.Println(b)

}

isNil()isValid()

  • isNil() 判斷 value 值使否為 nil,value 的 type 必須為 chan、func、interface、map、pointer、slice之一,否則會panic
  • isValid 判斷是否有一個值,也可判斷 struct 中是否含有 filed 或 method
package main

import (
	"fmt"
	"reflect"
)

type Test struct {
}

func (t Test) String() {

}

func main() {

	var a *int
	fmt.Println("var a *int isNil", reflect.ValueOf(a).IsNil())
	fmt.Println("nil isValid:", reflect.ValueOf(nil).IsValid())
	b := Test{}
	fmt.Println("struct 是否存在 'abc' feild ", reflect.ValueOf(b).FieldByName("abc").IsValid())
	fmt.Println("struct 是否存在 'abc' method", reflect.ValueOf(b).MethodByName("Abc").IsValid())
	fmt.Println("struct 是否存在 'String' method", reflect.ValueOf(b).MethodByName("String").IsValid())

	c := map[string]int{}
	c["測試2"] = 5
	fmt.Println("map key是否存在 '測試'  ", reflect.ValueOf(c).MapIndex(reflect.ValueOf("測試")).IsValid())
	fmt.Println("map key是否存在 '測試2' ", reflect.ValueOf(c).MapIndex(reflect.ValueOf("測試2")).IsValid())

}

Struct 反射

package main

import (
	"fmt"
	"reflect"
)

type student struct {
	Name  string `json:"name"`
	Score int    `json:"score "`
}

func main() {
	stu1 := student{
		Name:  "小王子",
		Score: 90,
	}
	t := reflect.TypeOf(stu1)
	fmt.Println("struct Name:", t.Name(), "type 為", t.Kind())
	fmt.Println("student struct filed count:", t.NumField())
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		fmt.Printf("student field name:%s index:%d type:%v json tag :%v\n", field.Name, field.Index, field.Type, field.Tag.Get("json"))
	}
	if scoreField, ok := t.FieldByName("Score"); ok {
		fmt.Println("獲取 student struct Score feild 成功")
		fmt.Printf("field name 為 %s \n", scoreField.Name)
		fmt.Printf("field index 為 %d \n", scoreField.Index)
		fmt.Printf("field type 為 %v \n", scoreField.Type)
		fmt.Printf("field json tag 為 %s \n", scoreField.Tag.Get("json"))
	}

}

將 Struct 轉成 json 字串

使用 json package 中 Marshal func 可以將 struct 當中的 filed 轉成 json 字串

package main

import (
	"encoding/json"
	"fmt"
)

type student struct {
	Name  string `json:"name"`
	Score int    `json:"score "`
}

func main() {
	stu1 := student{
		Name:  "小王子",
		Score: 90,
	}
	if s, err := json.Marshal(stu1); err == nil {
		fmt.Println(string(s))
	}

}


上一篇
day25-Select 介紹
下一篇
day27-Data Race
系列文
golang初探30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言