文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何使用反射获取私有类型?

2024-04-04 23:49

关注

编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天编程网就整理分享《如何使用反射获取私有类型?》,文章讲解的知识点主要包括,如果你对Golang方面的知识点感兴趣,就不要错过编程网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。

问题内容

假设有人使用 client, _ := rpc.dial('tcp', 'example.com:port') 初始化了一个 rpc 客户端,并且只为您提供 rpc 客户端实例。出于某种原因,您希望从客户端实例获取地址 example.com。但是,由于客户端类型是高度抽象的,因此您无法直接获取提供 remoteaddr() 方法的 net.conn 实例。在这种情况下,reflect 包可能会有所帮助。

让我们从以下尝试开始:

func getremoteaddr(client *rpc.client) net.addr {
  codec := reflect.indirect(rpclient).fieldbyname("codec")
  connv := codec.fieldbyname("rwc")
  conn := connv.interface().(net.conn)
  return conn.remoteaddr()
}

但是,第二行立即跳出错误:

panic: reflect: call of reflect.value.fieldbyname on interface value

这是合理的,因为 codec 被声明为 clientcodec 类型,它只是一个具有四个方法签名的接口。但是,从代码中我们知道codec的详细类型可能是未导出的结构体gobclientcodec。不幸的是,go 编译器不够智能,无法深入追踪并找出实际类型。因此,有没有一种方法可以使用反射包告诉编译器我确信 codec 的类型是未导出的 gobclientcodec ?如果这是不可能的,我可能必须计算地址偏移量并使用不安全的指针,这是最后的选择。

附注reflect 方法中的默认 type() 方法将不起作用,因为 codec 被声明为 clientcodec 并通过在 gobclientcodec 方法中传递 gobclientcodec 结构的地址进行初始化,如下所示:

func NewClient(conn io.ReadWriteCloser) *Client {
    encBuf := bufio.NewWriter(conn)
    client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
    return NewClientWithCodec(client)
}

此外,reflect.typeof(rpc.gobclientcodec) 将无法正常工作,因为编译器会拒绝未导出的类型使用。


正确答案


使用.Elem()获取接口中包含的值。

elem 返回接口 v 包含的值或者 指针 v 指向。如果 v 的 kind 不是 interface 或 ptr,它会发生恐慌。它 如果 v 为零,则返回零值。

对于您的特定用例,您还需要使用 unsafe 包来访问未导出的字段。使用之前请务必阅读 unsafe 的文档。

func getRemoteAddr(client *rpc.Client) net.Addr {
  rv := reflect.ValueOf(client)
  rv = rv.Elem()               // deref *rpc.Client
  rv = rv.FieldByName("codec") // get "codec" field from rpc.Client
  rv = rv.Elem()               // get the value that ClientCodec contains
  rv = rv.Elem()               // deref *gobClientCodec
  rv = rv.FieldByName("rwc")   // get "rwc" field from gobClientCodec

  conn := *(*net.Conn)(unsafe.Pointer(rv.UnsafeAddr()))
  return conn.RemoteAddr()
}

https://go.dev/play/p/cHHdwQJ7DE7

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《如何使用反射获取私有类型?》文章吧,也可关注编程网公众号了解相关技术文章。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯