go-utils/common/reflect/main.go

128 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `json:"name"`
Age int `json:"age" default:"18"`
addr string `json:"addr"`
}
func (u User) Do(in string) (string, int) {
fmt.Printf("%s Name is %s, Age is %d \n", in, u.Name, u.Age)
return u.Name, u.Age
}
func main() {
u := User{"tom", 27, "beijing"}
// 获取对象的 Value
v := reflect.ValueOf(u)
fmt.Println("Value:", v)
// fmt.Printf("%v\n", u)
// 获取对象的 Type
t := reflect.TypeOf(u)
fmt.Println("Type:", t)
// fmt.Printf("%T\n", u)
t1 := v.Type()
fmt.Println(t == t1)
v1 := reflect.New(t)
fmt.Println(v1)
fmt.Println()
// 获取 Kind 类型
k := t.Kind()
fmt.Println("Kind:", k)
k1 := v.Kind()
fmt.Println(k == k1)
fmt.Println()
// 修改反射对象的值
i := 20
fmt.Println("before i =", i)
e := reflect.Indirect(reflect.ValueOf(&i))
// e := reflect.ValueOf(&i).Elem()
if e.CanSet() {
e.SetInt(22)
}
fmt.Println("after i =", i)
fmt.Println()
// 反射字段操作
// elem := reflect.Indirect(reflect.ValueOf(&u))
elem := reflect.ValueOf(&u).Elem()
for i := 0; i < t.NumField(); i++ {
// 反射获取字段的元信息例如名称、Tag 等
ft := t.Field(i)
fmt.Println("field name:", ft.Name)
tag := ft.Tag
fmt.Println("Tag:", tag)
fmt.Println("Tag json:", tag.Get("json"))
// 反射修改字段的值
fv := elem.Field(i)
if fv.CanSet() {
if fv.Kind() == reflect.Int {
fmt.Println("change age to 30")
fv.SetInt(30)
}
if fv.Kind() == reflect.String {
fmt.Println("change name to jerry")
fv.SetString("jerry")
}
}
fmt.Println()
}
fmt.Println("after user:", u)
fmt.Println()
// 反射方法操作
for i := 0; i < v.NumMethod(); i++ {
method := t.Method(i) // 获取方法信息对象,方法 1
mt := method.Type // 获取方法信息 Type 对象,方法 1
// m := v.Method(i) // 获取方法信息对象,方法 2
// mt := m.Type() // 获取方法信息 Type 对象,方法 2
fmt.Println("method name:", method.Name)
in := []reflect.Value{}
// 获取方法入参类型
for j := 0; j < mt.NumIn(); j++ {
fmt.Println("method in type:", mt.In(j))
if mt.In(j).Kind() == reflect.String {
in = append(in, reflect.ValueOf("welcome"))
}
// 方法 1 获取的方法信息对象会把方法的接受者也当着入参之一
if mt.In(j).Name() == t.Name() {
in = append(in, v)
}
}
// 获取方法返回类型
for j := 0; j < mt.NumOut(); j++ {
fmt.Println("method out type:", mt.Out(j))
}
// 反射方法调用
// out := m.Call(in) // 方法 1 获取的 Method 对象反射调用方式
out := method.Func.Call(in) // 方法 1 获取的 Method 对象反射调用方式
for _, o := range out {
fmt.Println("out:", o)
}
}
fmt.Println()
// Value 转原始类型
if u1, ok := v.Interface().(User); ok {
fmt.Println("after:", u1.Name, u1.Age)
}
}