本文主要是介绍经过99次失败后, 我总结了几点 Golang 反射的经验(附源码),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
// kind_type_test.go
// 打印 kind 和 type 的值
func kind_type_value(v interface{}) {
rv := reflect.ValueOf(v)
fmt.Println(rv.Kind(), rv.Type())
}
// kind 和 type 相同字面值
func Test_Kind_Type_Same(t *testing.T) {
name := "tangxin"
age := 18
kind_type_value(name) // string string
kind_type_value(age) // int int
kind_type_value(&name) // ptr *string
kind_type_value(&age) // ptr *int
}
// 根据内置类型 string 的自定义类型
type MyString string
// kind 和 type 不同
func Test_KindType_Different(t *testing.T) {
p := Person{
Name: "tagnxin",
Age: 18,
}
kind_type_value(p) // struct main.Person
kind_type_value(&p) // ptr *main.Person
s1 := MyString("tangxin")
kind_type_value(s1) // string main.MyString
kind_type_value(&s1) // ptr *main.MyString
}
// 第一定律: 对象类型转指针类型
func Test_Rule1(t *testing.T) {
p := &Person{
Name: "zhangsan",
Age: 18,
Addr: struct {
City string
}{
City: "chengdu",
},
}
rule1(p) // ptr *main.Person
rule1(&p) // ptr **main.Person
}
func rule1(v interface{}) {
rv := reflect.ValueOf(v)
fmt.Println(rv.Kind(), rv.Type())
}
func rule2(rv reflect.Value) {
// check
if !rv.CanInterface() {
fmt.Println("rv is not settable: ", rv.Type())
return
}
// convert
rv = DerefValue(rv)
irv := rv.Interface()
fmt.Println(irv)
// type assert
v, ok := irv.(Person)
fmt.Println(v, ok) // {zhangsan 18 {chengdu}} true
}
func rule3(rv reflect.Value) {
if !rv.CanSet() {
fmt.Println("rv is not settable", rv.Type())
return
}
switch rv.Kind() {
case reflect.String:
rv.SetString("tangxin")
case reflect.Int:
rv.SetInt(333)
default:
fmt.Println("not support kind: ", rv.Kind())
}
}
const ( Invalid Kind = iota Bool Int // ... String // ... Interface Map Ptr // 这里是重点, 指针可以只想任何容器类型,包括指针本身。 )
func Indirect(v Value) Value {
if v.Kind() != Ptr {
return v
}
return v.Elem()
}
// rule1_test.go
// 指向指针的指针对象
func Test_Rule1(t *testing.T) {
p := &Person{
Name: "zhangsan",
Age: 18,
Addr: struct {
City string
}{
City: "chengdu",
},
}
rv := reflect.ValueOf(&p)
fmt.Println(rv.Kind(), rv.Type()) // ptr **main.Person
}
// value.go
// DerefValue 返回最底层的反射容器对象
func DerefValue(rv reflect.Value) reflect.Value {
for rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
return rv
}
type student struct {
Name string
Age int
}
func (stu *student) SetDefaults() {
stu.Name = "tangxin"
if stu.Age == 0 {
stu.Age = 100
}
}
// 没有传参数的方法
func (stu *student) Greeting() {
fmt.Printf("hello %s, %d years old\n", stu.Name, stu.Age)
}
// 具有传参数的方法
func (stu *student) Aloha(name string) {
fmt.Println("aloha,", name)
}
func Test_MethodCall(t *testing.T) {
stu := student{
Name: "wangwu",
}
// 注意
// 方法对象的方法接收者, 可以是 **指针对象** 也可以是 **结构体对象**
// 如果是指针对象的方法, **结构体对象** 是不能调用起方法的
rv := reflect.ValueOf(stu)
prv := reflect.ValueOf(&stu)
stu.Greeting()
methodCall(prv, "SetDefaults")
methodCall(rv, "Greeting") // 结构体接收者, 找不到方法
methodCall(prv, "Aloha", reflect.ValueOf("boss"))
}
// 对象方法调用
// rv 目标对象, method 方法名称, in 参数
func methodCall(rv reflect.Value, method string, in ...reflect.Value) {
// 通过方法名称获取 反射的方法对象
mv := rv.MethodByName(method)
// check mv 是否存在
if !mv.IsValid() {
fmt.Printf("mv is zero value, method %s not found\n", method)
return
}
// 调用
// nil 这里代表参数
mv.Call(in)
}
这篇关于经过99次失败后, 我总结了几点 Golang 反射的经验(附源码)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!