Go:反射

1、经过反射获取类型信息

在 Go 程序中,使用 reflect.TypeOf() 函数能够得到任意值的类型对象(reflect.Type),程序经过类型对象能够访问任意值的类型信息。json

package main import ( "fmt"
    "reflect" ) func test1() { var a int t := reflect.TypeOf(a) fmt.Printf("name:%v kind:%v\n", t.Name(), t.Kind()) // name:int kind:int
} func test2() { type User struct {} user := User{} t := reflect.TypeOf(user) fmt.Printf("name:%v kind:%v\n", t.Name(), t.Kind()) // name:User kind:struct
} func main() { test1() test2() }
View Code

2、经过反射获取指针指向的元素类型

package main import ( "fmt"
    "reflect" ) func main() { // 声明一个空结构体
 type User struct {} // 建立User的实例
    user := &User{} // 获取结构体实例的反射类型对象
    t := reflect.TypeOf(user) // 显示反射类型对象的名称和种类
    fmt.Printf("name:'%v' kind:'%v'\n", t.Name(), t.Kind()) // name:'' kind:'ptr'
    // 获取指针类型的元素类型
    e := t.Elem() // 显示指针变量指向元素的类型名称和种类
    fmt.Printf("name:'%v' kind:'%v'\n", e.Name(), e.Kind()) // name:'User' kind:'struct'
}
View Code

3、经过反射获取结构体的成员类型

任意值经过 reflect.TypeOf() 得到反射对象信息后,若是它的类型是结构体,能够经过反射值对象(reflect.Type)的 NumField() 和 Field() 方法得到结构体成员的详细信息。app

package main import ( "fmt"
    "reflect" ) type User struct { Name string `json:"username"` Age int Salary float64 } func main() { user := User{"pd", 18, 9999.99} tf := reflect.TypeOf(user) // 遍历结构体全部成员
    for i := 0; i < tf.NumField(); i++ { // 获取每一个成员的结构体字段类型
        fieldType := tf.Field(i) fmt.Printf("name:'%v' tag:'%v'\n", fieldType.Name, fieldType.Tag) // name:'Name' tag:'json:"username"'
        // name:'Age' tag:''
        // name:'Salary' tag:''
 } // 经过字段名, 找到字段类型信息
    userType, ok := tf.FieldByName("Name") if ok { // 从tag中取出须要的tag
        fmt.Println(userType.Tag.Get("json")) // username
 } }
View Code

4、经过反射获取值信息

package main import ( "fmt"
    "reflect" ) func main() { // 声明整型变量a并赋初值
    var a int a = 666
    // 获取变量a的反射值对象
    vf := reflect.ValueOf(a) // 将vf反射值对象以Interface{}类型取出, 经过类型断言转换为int类型
    r1 := vf.Interface().(int) // 将vf反射值对象以int64类型取出
    r2 := vf.Int() // 强制类型转换为int类型
    r3 := int(r2) fmt.Printf("r1值:%v r1类型:%T\n", r1, r1) // r1值:666 r1类型:int
    fmt.Printf("r2值:%v r2类型:%T\n", r2, r2) // r2值:666 r2类型:int64
    fmt.Printf("r3值:%v r3类型:%T\n", r3, r3) // r3值:666 r3类型:int
}
View Code

5、经过反射访问结构体成员的值

package main import ( "fmt"
    "reflect" ) type User struct { Name string Age int Salary float64 } func main() { user := User{"pd", 18, 9999.99} vf := reflect.ValueOf(user) // 获取字段数量
    fmt.Printf("NumField:%v\n", vf.NumField()) // NumField:3
    // 获取索引为2的字段
    field := vf.Field(2) fmt.Println(field.Type()) // float64
    // 根据名字查找字段
    fbn := vf.FieldByName("Name") fmt.Println(fbn.Type()) // string
    // 根据索引查找字段
    fbi := vf.FieldByIndex([]int{1}) fmt.Println(fbi.Type()) // int
}
View Code

6、判断反射值的空和有效性

package main import ( "fmt"
    "reflect" ) func main() { // *int的空指针
    var a *int fmt.Println(reflect.ValueOf(a).IsNil()) // true

    // nil值
    fmt.Println(reflect.ValueOf(nil).IsValid()) // false

    // 实例化一个结构体
    s := struct{}{} // 尝试从结构体中查找一个不存在的字段
    fmt.Println(reflect.ValueOf(s).FieldByName("").IsValid()) // false

    // 尝试从结构体中查找一个不存在的方法
    fmt.Println(reflect.ValueOf(s).MethodByName("").IsValid()) // false
}
View Code

7、经过反射修改变量的值

package main import ( "fmt"
    "reflect" ) func main() { // 声明整型变量a并赋初值
    var a int
    var b string a = 100 b = "哈哈哈"
    // 获取变量a、b的反射值对象(a、b的地址)
    vfa := reflect.ValueOf(&a) vfb := reflect.ValueOf(&b) // 取出a、b地址的元素(值)
    vfae := vfa.Elem() vfbe := vfb.Elem() // 修改a、b的值
    vfae.SetInt(200) vfbe.SetString("嘻嘻嘻") // 打印a、b的值
    fmt.Println(a, b) // 200 嘻嘻嘻
}
View Code
package main import ( "fmt"
    "reflect" ) type User struct { Name string Age int } func main() { user := User{"pd", 18} vf := reflect.ValueOf(&user) // 取出User实例地址的元素
    vfe := vf.Elem() // 获取Name字段的值
    name := vfe.FieldByName("Name") // 修改此实例(对象)对应字段的值
    name.SetString("佩奇") fmt.Println(user) // {佩奇 18}
}
View Code

8、经过类型信息建立实例

package main import ( "fmt"
    "reflect" ) func main() { var a int
    // 取变量a的反射类型对象
    tf := reflect.TypeOf(a) // 根据反射类型对象建立这个类型的实例值,值以 reflect.Value 类型返回
    obj := reflect.New(tf) // 输出类型和种类
    fmt.Printf("type:%v kind:%v\n", obj.Type(), obj.Kind()) // type:*int kind:ptr
}
View Code

9、经过反射调用函数、方法

package main import ( "fmt"
    "reflect" ) // add函数
func add(a, b int) int { return a + b } func main() { // 将函数包装为反射值对象
    vf := reflect.ValueOf(add) // 构造函数参数, 传入两个整型值
    paramList := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)} // 反射调用函数
    retList := vf.Call(paramList) // 获取第一个返回值, 取整数值
    fmt.Println(retList[0].Int()) // 30
}
View Code
package main import ( "fmt"
    "reflect" ) type User struct { Name string } func (u *User) Hello(name string) { fmt.Printf("%s对%s打了一个招呼...\n", u.Name, name) // pd对佩奇打了一个招呼...
} func main() { user := User{"pd"} vf := reflect.ValueOf(&user) method := vf.MethodByName("Hello") // 方式1
    // args := []reflect.Value{reflect.ValueOf("佩奇")}
    // 方式2
    var args []reflect.Value args = append(args, reflect.ValueOf("佩奇")) // 调用方法
 method.Call(args) }
View Code
相关文章
相关标签/搜索