ch13_反射reflection

本文深入探讨了Go语言中的反射机制,包括基本结构、匿名或嵌入字段的反射、通过反射修改元素值以及调用结构体方法的具体示例。通过实践代码展示了如何使用reflect包进行类型检查和操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射reflection

反射的基本结构

  • 要导入reflect
import (
    "fmt"
    "reflect"
)

type User struct {
    Id   int
    Name string
    Age  int
}

func (u User) Hello() {
    fmt.Println("Hello world.")
}
func Info(o interface{}) {
    t := reflect.TypeOf(o)
    //判断o是否为结构体
    if k := t.Kind(); k != reflect.Struct {
        fmt.Println("这不是个结构体")
        return
    }
    fmt.Println("Type:", t.Name())
    v := reflect.ValueOf(o)
    fmt.Println("Fields:")
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        val := v.Field(i).Interface()
        fmt.Printf("%6s: %v %v\n", f.Name, f.Type, val) //对于interface{}, %v会打印实际类型的值
    }
    for i := 0; i < t.NumMethod(); i++ {
        m := t.Method(i)
        fmt.Printf("%6s: %v\n", m.Name, m.Type)
    }
}
func main() {
    u := User{1, "OK", 12}
    Info(u)
}

%v the value in a default format
when printing structs, the plus flag (%+v) adds field names
%#v a Go-syntax representation of the value
%T a Go-syntax representation of the type of the value

反射匿名或嵌入字段

  • 通过查看其类型中Anonymous的真假判断是否为匿名字段
type User struct {
    Id   int
    Name string
    Age  int
}
type Manager struct {
    User
    title string
}

func (u User) Hello() {
    fmt.Println("Hello world.")
}

func main() {
    m := Manager{User: User{1, "OK", 13}, title: "233"}
    t := reflect.TypeOf(m)
    //通过Anonymous字段判断是否为匿名字段
    fmt.Printf("%#v\n", t.Field(0))
    fmt.Printf("%#v\n", t.Field(1))
    //取第0号元素里的第0号元素,即User字段里的Id
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0}))
}

输出结果

reflect.StructField{Name:“User”, PkgPath:"", Type:(*reflect.rtype)(0x4c9a00), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}
reflect.StructField{Name:“title”, PkgPath:“main”, Type:(*reflect.rtype)(0x4b6380), Tag:"", Offset:0x20, Index:[]int{1}, Anonymous:false}
reflect.StructField{Name:“Id”, PkgPath:"", Type:(*reflect.rtype)(0x4b5bc0), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}

通过反射修改元素的值

  • 要使用元素的指针
    x := 123
    v := reflect.ValueOf(&x)
    v.Elem().SetInt(999)
    fmt.Println(x)
  • 修改结构体元素示例
type User struct {
    Id   int
    Name string
    Age  int
}

func Set(o interface{}) {
    v := reflect.ValueOf(o)
    //判断v是否为指针
    if v.Kind() != reflect.Ptr {
        fmt.Println("不是指针,无法修改")
        return
    }
    //判断v所指向的值是否可以被修改
    if v.Elem().CanSet() == false {
        fmt.Println("属性为不可修改")
        return
    }
    //取出v的值
    v = v.Elem()
    f := v.FieldByName("Name")
    if f.IsValid() == false {
        fmt.Println("没有找到")
        return
    }
    switch f.Kind() {
    case reflect.Int:
        f.SetInt(1)
    case reflect.String:
        f.SetString("ByeBye")
    }
}
func main() {
    u := User{Id: 55, Name: "Hello", Age: 13}
    Set(&u)
    fmt.Println(u)
}
  • 调用结构体方法示例
type User struct {
    Id   int
    Name string
    Age  int
}

func (u User) Hello(name string) {
    fmt.Println("Hello", name, ", my name is", u.Name)
}
func main() {
    u := User{Id: 55, Name: "Alice", Age: 13}
    v := reflect.ValueOf(u)
    mv := v.MethodByName("Hello")
    args := []reflect.Value{reflect.ValueOf("Bob")}
    mv.Call(args)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值