go語言reflect實驗

//反射的本質就是根據傳入的結構體的類型不一樣從而生成不一樣的結構體對象,而後經過查找原結構體的方法,來動態調用其方法。json

package main指針

import (
"fmt"
"reflect"
)對象

var log = fmt.Println接口

func main() {ci

reflect1()
// reflect2()
//reflect3()
//reflect4()
//reflect5()
}element

type T5 struct {
Name string
}字符串

func reflect5() {
var i int = 1
v5 := reflect.ValueOf(&i)
v5 = reflect.Indirect(v5) //等同於Elem()
//v5 = v5.Elem()
v5v := v5.Interface()
if v5.Kind() == reflect.Int {
log(v5.Kind(), "kind")
v5.SetInt(2) //傳地址才能夠設置
}
v5i := v5.Interface()
log(v5v, v5i, "v5v")
s := T5{"x"}
value5 := reflect.ValueOf(&s).Elem()
log(value5.Interface())
f0 := value5.FieldByName("Name")
log(f0, "f0")
if f0.Kind() == reflect.String {
if f0.CanSet() {
f0.SetString("y")
log(f0, s, value5, "fsv")
}
}
}string

type User struct {
Name string
Age int
}it

func (u User) showUser() {
log("showuser")
}
func (u User) showAge() {
log("showAge")
}
func reflect4() {
u := &User{"maliu", 20}
t := reflect.TypeOf(u)
v := reflect.ValueOf(u)
vt := v.Type() //根據reflect.value還原類型
tk := t.Kind() //還原其底層基礎類型
isCan := v.CanSet()
log(t, v, vt, tk, isCan, "tv")
u2 := v.Interface()
u1 := v.Interface().(*User) //將reflect.Value類型還原爲原始類型
log(u, u1, u2, "u1")
u3 := (*User)(nil) //將nil強轉爲User的指針類型
log(u3, "u3")
t4 := reflect.TypeOf(u3).Elem()
log(t4.Name(), t4, "t4")
m4 := map[string]reflect.Type{}
m4[t4.Name()] = t4
log(m4, "m4")
elem4, ok4 := m4["User"]
log(elem4, ok4)
r4 := reflect.New(elem4).Elem() //New出來的是指針類型
r5 := r4.Interface() // 該方法會返回一個value的值,不過類型是interface
r6 := r5.(User) //建立一個原始類型的空值io

r6.Name = "hi,I am r6"
log(r4, r5, r6, "r4")
t2 := t.Elem()
for i := 0; i < t2.NumField(); i++ {
log(t2.Field(i).Name, "field")
}
for i := 0; i < t2.NumMethod(); i++ {
log(t2.Method(i).Name, "Method")
}

}

//-------------------------
type test3 struct {
Name string
}

func reflect3() {
var temp3 interface{} = test3{Name: "wangwu"}
t3 := reflect.TypeOf(temp3).Elem()
log(t3, "t3") //會報錯
}

//--------------
type test2 struct {
Name string
Sex int
}

type tmpStruct struct {
Name string
}
type tink interface {
ShowName()
ShowName2()
}

func (c tmpStruct) ShowName() {
log(c.Name, "c.Name")
}
func (c *tmpStruct) ShowName2() {
log(c.Name, "c.Name2")
}
func reflect2() {
m := map[string]int{"a": 1, "b": 2}
elem, ok := m["a"] //存在就是true
log(m, "m")
log(elem, ok, "elementok")
var emp tink = &tmpStruct{Name: "lisi"} //若是接口有任意一個方法的調用者是指針,那麼接口只能被指針賦值
c := reflect.TypeOf(emp).Elem()

temp := reflect.New(c).Elem().Interface() //new的參數必須是結構體typeof實例返回的內容也就是reflect.type類型,直接傳結構體沒用
log(c, temp, "temp")
}

//------------------------
type ControllerInterface interface {
Init(action string, method string)
}
type Controller struct {
Action string
Method string
Tag string `json:"tag"`
}

func (c *Controller) Init(action string, method string) {
c.Action = action
c.Method = method
log("I am in init")
}
func (c *Controller) Test() {
log("I am Test func")
}
func reflect1() {
runController := &Controller{
Action: "Run1",
Method: "Get",
}

var i ControllerInterface
i = runController
v := reflect.ValueOf(i) //i接口的值
log("value", v)
t := reflect.TypeOf(i) //i接口類型
log("Type", t)
controllerValue := v.Elem() //解掉指針以後的值
log(controllerValue, "cv")
log(controllerValue.Field(0).String()) //第一個值的字符串形式
controllerType := t.Elem()
log(controllerType, "controllerType")
log(controllerType.Name(), "typeName()")
log(controllerType.Field(0), "Field0")
log(controllerType.Field(1), "Field1")
log(controllerType.Field(2), "Field2")
fb, _ := controllerType.FieldByName("Method") //經過字段獲取值信息
log(fb, "FieldByName")
tag := controllerType.Field(2).Tag //Field(第幾個字段,index從0開始)
log("tag", tag, tag.Get("json")) //獲取別名
method, _ := t.MethodByName("Init")
log(method, "method")
vMethod := v.MethodByName("Init")
log(vMethod, "vMethod")
arg1 := []reflect.Value{reflect.ValueOf("Run2"), reflect.ValueOf("POST")}
vMethod.Call(arg1)
log(i, "I am I")
arg2 := make([]reflect.Value, 0)
log(arg2, "arg2")
v.MethodByName("Test").Call(arg2)
}

//v := reflect.ValueOf(i) //i接口的值 這個類型是reflect.Type
// t := reflect.TypeOf(i) //i接口類型
// controllerValue := v.Elem() //解掉指針以後的值,這個類型是reflect.Value,非指針類型沒有Elem這個方法
// controllerValue.Field(0).String() //第一個字段的字符串形式
// controllerType := t.Elem()//解掉指針以後的類型 這個類型是reflect.Type,非指針類型沒有Elem這個方法
//controllerType.Name()//去掉包名以後的類型名
//controllerType.Field(1)//返回一個結構體包含字段名,類型,第幾個字節,第幾個元素,bool值
// tag := controllerType.Field(2).Tag //Field(第幾個字段,index從0開始)
//vMethod := v.MethodByName("Init") //地址值,能夠經過Call並傳入切片調用,能夠改變原值
//reflect.Value //是一種反射值類型
//method, _ := t.MethodByName("Init")

//go 語言沒有提供根據類型名稱返回類型變量的功能,可是你能夠經過設置一個:
// var typemap = make(map[string]reflect.Type)
// 而後把你的結構體註冊到這個表中,以後你能夠經過這個表經過類型名獲取類型,以後用反射建立對象就好了。
//感受應該是用reflect來解決, 可是reflect動態生成,得知道類型,reflect.Type. reflect.New(type)能夠動態生成一個reflect.Value。 獲得value了就能夠用接口來轉換了

// func New(typ Type) Value New returns a Value representing a pointer to a new zero value for the specified type. That is, the returned Value's Type is PtrTo(typ).

相關文章
相關標籤/搜索