Go 反射示例项目,由于该部分比较复杂,仅从网上摘抄了一部分。
示例
package main
import (
"fmt"
"math/rand"
"reflect"
"strconv"
)
// Person 定义结构体和属性标签
type Person struct {
FirstName string `json:"first_name"`
IsBoy bool `json:"is_boy"`
Height float32 `json:"height"`
}
func NewPersion(firstName string, isBoy bool, height float32) *Person {
return &Person{FirstName: firstName, IsBoy: isBoy, Height: height}
}
// 定义String方法
func (p Person) String() string {
return fmt.Sprintf("Person{FirstName: %s, IsBoy: %v, Height: %v}", p.FirstName, p.IsBoy, p.Height)
}
func (p Person) GetFirstName() string {
return p.FirstName
}
func (p *Person) SetFirstName(firstName string) {
p.FirstName = firstName
}
func (p Person) GetHeight() float32 {
return p.Height
}
func (p *Person) SetHeight(height float32) {
p.Height = height
}
// 接口
type Close interface {
Close() error
}
type Addr struct {
ip string `json:"ip"`
port int `json:"port"`
}
func (addr Addr) GetIp() string {
return addr.ip
}
func (addr Addr) GetPort() int {
return addr.port
}
type Connection struct {
Addr
status int
}
func NewConnection(ip string, port int) *Connection {
return &Connection{
Addr{
ip: ip,
port: port,
},
1,
}
}
func (c *Connection) Send(msg string) error {
fmt.Println("send", msg)
return nil
}
func (c *Connection) Close() error {
fmt.Printf("close %v:%v\n", c.ip, c.port)
return nil
}
// 打印方法
func displayMethod(method reflect.Method, tab string) {
// 获取方法接收者
t := method.Type
// 显示方法名
fmt.Printf("%sfunc %s(", tab, method.Name)
// 打印参数信息
// 获取参数数量并遍历
for i := 0; i < t.NumIn(); i++ {
// 根据索引获取第i个参数的Type对象
fmt.Printf("%s", t.In(i))
if i != t.NumIn()-1 {
fmt.Printf(", ")
}
}
// 打印可变参数信息
if t.IsVariadic() {
fmt.Printf("...")
}
// 打印返回值信息
fmt.Printf(") ")
if t.NumOut() > 0 {
fmt.Printf("(")
// 获取返回值数量并遍历
for i := 0; i < t.NumOut(); i++ {
// 根据索引获取第i个返回值的Type
fmt.Printf("%s", t.Out(i))
if i != t.NumOut()-1 {
fmt.Printf(", ")
}
}
fmt.Printf(") ")
}
fmt.Printf("{}")
}
// 获取 reflect.Type 变量 t 的信息
func displayType(t reflect.Type, tab string) {
// 判断 nil
if t == nil {
fmt.Println("nil")
return
}
// 枚举判断每种类型
switch t.Kind() {
case reflect.Int, reflect.Float32, reflect.String, reflect.Bool:
// 基本数据类型显示名称
fmt.Printf("%s %s\n", tab, t.Name())
case reflect.Array, reflect.Slice:
// 针对数组和切片,打印类型
fmt.Printf("%s %s\n", tab, t)
case reflect.Map:
// 对于映射类型,打印键和值
fmt.Printf("%smap{\n", tab)
fmt.Printf("%s\tKey: ", tab)
// 获取键的Type对象
fmt.Printf("%s %s", tab, t.Key())
fmt.Println()
fmt.Printf("%s\tValue: ", tab)
// 获取键的Type对象
fmt.Printf("%s %s", tab, t.Elem())
fmt.Println()
fmt.Printf("%s}", tab)
case reflect.Func:
// 对于函数类型,打印名字
fmt.Printf("%sfunc (", tab)
// 打印参数
for i := 0; i < t.NumIn(); i++ {
// 根据索引获取第i个参数的Type对象
fmt.Printf("%s", t.In(i))
if i != t.NumIn()-1 {
fmt.Printf(", ")
}
}
if t.IsVariadic() {
fmt.Printf("...")
}
fmt.Printf(") ")
// 打印返回值信息
if t.NumOut() > 0 {
fmt.Printf("(")
// 变量返回值类型
for i := 0; i < t.NumOut(); i++ {
// 根据索引获取第i个返回值的Type对象
fmt.Printf("%s", t.Out(i))
if i != t.NumOut()-1 {
fmt.Printf(", ")
}
}
fmt.Printf(") ")
}
fmt.Printf("{}")
case reflect.Struct:
// 结构体,打印属性和方法
fmt.Printf("%stype %s struct {", tab, t.Name())
// 获取属性数量并遍历
fmt.Printf("%s\tFields(%d):\n", tab, t.NumField())
for i := 0; i < t.NumField(); i++ {
// 获取第i个StructTag对象
filed := t.Field(i)
// 打印属性的Type对象和标签
fmt.Printf("%s\t\t%s\t%s\t`%s`", tab, filed.Name, filed.Type, filed.Tag)
fmt.Printf(",\n")
}
// 获取方法数量并遍历
fmt.Printf("\n%s\tMethods(%d):\n", tab, t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
displayMethod(t.Method(i), tab+"\t\t")
fmt.Printf(",\n")
}
fmt.Printf("%s}", tab)
case reflect.Ptr:
// 指针,遍历分析引用值
fmt.Printf("%s*{\n", tab)
// 获取指针的引用值,并递归调用 displayType 函数
displayType(t.Elem(), tab+"\t")
// 打印指针变量的方法
if t.NumMethod() > 0 {
fmt.Printf("\n%s\tMethods(%d):\n", tab, t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
// 打印方法信息
displayMethod(t.Method(i), tab+"\t\t")
if i != t.NumMethod()-1 {
fmt.Printf(",\n")
}
}
}
fmt.Printf("}")
default:
fmt.Println("unknown", tab, t)
}
}
// 获取 reflect.Type 变量 t 的Value信息
func displayValue(value reflect.Value, tab string) {
// 获取值对应的枚举类型
switch value.Kind() {
case reflect.Int:
fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatInt(value.Int(), 10))
case reflect.Float32:
fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatFloat(value.Float(), 'e', -1, 64))
case reflect.String:
fmt.Printf("%s[%s] %s", tab, value.Type(), value)
case reflect.Bool:
fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatBool(value.Bool()))
case reflect.Array:
fmt.Printf("%s[%s] {\n", tab, value.Type())
// 获取数组的长度
for i := 0; i < value.Len(); i++ {
displayValue(value.Index(i), tab+"\t")
fmt.Printf(",\n")
}
fmt.Printf("%s\n", tab)
case reflect.Slice:
// 针对切片,获取值对应的Type对象、长度和容量
fmt.Printf("%s[%s](%d:%d) {\n", tab, value.Type(), value.Len(), value.Cap())
// 获取切片长度
for i := 0; i < value.Len(); i++ {
displayValue(value.Index(i), tab+"\t")
fmt.Printf("\n")
}
fmt.Printf("%s\n", tab)
case reflect.Map:
// 对于映射类型,获取值对应的Type对象
fmt.Printf("%s[%s] {\n", tab, value.Type())
it := value.MapRange()
for it.Next() {
displayValue(it.Key(), tab+"\t")
fmt.Printf(" : ")
displayValue(it.Value(), "")
fmt.Printf(",\n")
}
fmt.Printf("%s}", tab)
case reflect.Struct:
// 结构体,获取值对应的type对象
structType := value.Type()
fmt.Printf("%s[%s] {\n", tab, structType)
// 获取属性数量并遍历
for i := 0; i < value.NumField(); i++ {
structField := structType.Field(i)
field := value.Field(i)
fmt.Printf("%s\t%s:", tab, structField.Name)
displayValue(field, tab+"\t")
fmt.Printf(",\n")
}
fmt.Printf("%s}", tab)
case reflect.Ptr:
// 指针
fmt.Printf("%s[%s] {\n", tab, value.Type())
displayValue(value.Elem(), tab+"\t")
fmt.Printf("}")
default:
fmt.Println("unknown", tab, value)
}
}
func changeValue(value reflect.Value, path string) {
switch value.Kind() {
case reflect.Int:
if value.CanSet() {
fmt.Printf("int CanSet: %s.%s\n", path, value.Type())
value.SetInt(value.Int() + rand.Int63n(100))
}
case reflect.Float32:
if value.CanSet() {
fmt.Printf("float32 CanSet: %s.%s\n", path, value.Type())
value.SetFloat(value.Float() + rand.Float64())
}
case reflect.Bool:
if value.CanSet() {
fmt.Printf("bool CanSet: %s.%s\n", path, value.Type())
value.SetBool(!value.Bool())
}
case reflect.String:
if value.CanSet() {
fmt.Printf("string CanSet: %s.%s\n", path, value.Type())
value.SetString("chage:" + value.String())
}
case reflect.Array:
if value.CanSet() {
fmt.Printf("array CanSet: %s.%s\n", path, value.Type())
}
for i := 0; i < value.Len(); i++ {
changeValue(value.Index(i), path+".array")
}
case reflect.Slice:
for i := 0; i < value.Len(); i++ {
changeValue(value.Index(i), path+".slice")
}
case reflect.Map:
keys := value.MapKeys()
for _, key := range keys {
value.SetMapIndex(key, reflect.ValueOf("change:"+value.MapIndex(key).String()))
}
case reflect.Struct:
if value.CanSet() {
fmt.Printf("struct CanSet: %s.%s\n", path, value.Type())
}
for i := 0; i < value.NumField(); i++ {
changeValue(value.Field(i), path+".struct")
}
case reflect.Ptr:
if value.CanSet() {
fmt.Printf("ptr CanSet: %s.%s\n", path, value.Type())
}
changeValue(value.Elem(), path+".point")
default:
fmt.Printf("unknown CanSet: %s.%s\n", path, value.Type())
}
}
func callFunc(f reflect.Value) {
ftype := f.Type()
fmt.Printf("%s\n", ftype.String())
parameters := make([]reflect.Value, 0)
for i := 0; i < ftype.NumIn(); i++ {
parameters = append(parameters, reflect.Zero(ftype.In(i)))
}
if ftype.IsVariadic() {
fmt.Printf("%#v", f.CallSlice(parameters))
} else {
fmt.Println(f.Call(parameters))
}
}
func callMethod(f reflect.Value, t reflect.Type, m reflect.Method) {
ftype := f.Type()
fmt.Printf("method: %s.%s => %s\n", t.Name(), m.Name, ftype.String())
parameters := make([]reflect.Value, 0)
for i := 0; i < ftype.NumIn(); i++ {
parameters = append(parameters, reflect.New(ftype.In(i)).Elem())
}
if ftype.IsVariadic() {
fmt.Printf("%#v", f.CallSlice(parameters))
} else {
fmt.Println(f.Call(parameters))
}
}
func callValue(value reflect.Value) {
fmt.Println("----------", value.Type())
switch value.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < value.Len(); i++ {
callValue(value.Index(i))
}
case reflect.Map:
it := value.MapRange()
for it.Next() {
callValue(it.Value())
}
case reflect.Struct:
for i := 0; i < value.NumMethod(); i++ {
callMethod(value.Method(i), value.Type(), value.Type().Method(i))
}
case reflect.Ptr:
for i := 0; i < value.NumMethod(); i++ {
callMethod(value.Method(i), value.Elem().Type(), value.Type().Method(i))
}
case reflect.Func:
callFunc(value)
default:
fmt.Printf("unknown[%#v]\n", value)
}
}
func main() {
vars := make([]interface{}, 0, 20)
var intV int = 1
var floatV float32 = 3.14
var boolV bool = true
var stringV string = "hello world!"
var arrayV [5]int = [...]int{1, 2, 3, 4, 5}
var sliceV []string = []string{"i", "am", "string"}
var mapV map[string]string = map[string]string{"name": "xianbin"}
var funcV1 func(...interface{}) error = func(x ...interface{}) error {
fmt.Println(x)
return nil
}
var funcV2 func(string, int) *Connection = NewConnection
var persionV *Person = NewPersion("xianbin", true, 1.8)
var closeV Close
vars = make([]interface{}, 0, 20)
vars = append(vars, intV, &intV, floatV, boolV, stringV, arrayV, sliceV, mapV, funcV1, funcV2, persionV, *persionV, closeV)
for _, v := range vars {
displayType(reflect.TypeOf(v), "")
displayValue(reflect.ValueOf(v), "")
fmt.Println()
}
// 变量可修改条件
// 对于基本数据类型变量可获取地址
// 对于结构体属性必须是可获取地址且为公开的属性
vars = append(vars, sliceV, mapV, *persionV, persionV, closeV)
for _, v := range vars {
changeValue(reflect.ValueOf(v), "")
fmt.Println()
}
vars = make([]interface{}, 0, 20)
var funcs []func() = make([]func(), 0)
funcs = append(funcs,
func() {
fmt.Println("hello 1")
},
func() {
fmt.Println("hello 2")
})
var funcV11 func(...interface{}) error = func(i ...interface{}) error {
fmt.Println(i)
return nil
}
var funcV12 func(string) error = func(i string) error {
fmt.Println(i)
return nil
}
vars = append(vars, funcs, funcV11, funcV12)
for _, v := range vars {
callValue(reflect.ValueOf(v))
fmt.Println()
}
}