为了账号安全,请及时绑定邮箱和手机立即绑定

在未导出的字段上调用导出的方法

在未导出的字段上调用导出的方法

Go
牛魔王的故事 2022-04-20 20:55:06
我知道,有人问过类似的问题,但我没有找到该案例的答案:type ExportedStruct struct{ //comes from a dependency, so I can't change it  unexportedResource ExportedType}我想在. _Close()unexportedResource我所做的是:rs := reflect.ValueOf(myExportedStructPtr).Elem() //myExportedStructPtr is a pointer to an ExportedStruct objectresourceField := rs.FieldByName("unexportedResource")closeMethod := resourceField.MethodByName("Close")closeMethod.Call([]reflect.Value{reflect.ValueOf(context.Background())}),这导致reflect.flag.mustBeExported using value obtained using unexported field。这很烦人,因为我想运行多个使用 的测试ExportedStruct,但只要不使用底层资源,我就不能。由于我可以访问私有字段(如此处所述),我有点希望我也被允许以某种方式访问该字段的公共方法。也许我只是反映错了?
查看完整描述

3 回答

?
子衿沉夜

TA贡献1828条经验 获得超3个赞

未导出的字段仅用于声明包。别再惹他们了。它们不适合你。

链接的答案只能通过使用 package 来访问它unsafe,这不是日常使用的。包装unsafe应随附“请勿触摸”手册。

如果确实需要访问unexportedResource,请将其导出。无论是字段,还是向调用的类型添加方法unexportedResource.Close()。或者将实用程序函数添加到执行此操作的包中(同一包中的函数可以访问未导出的字段和标识符)。


查看完整回答
反对 回复 2022-04-20
?
RISEBY

TA贡献1856条经验 获得超5个赞

虽然@icza 的回答为您提供了不应该这样做的理由,但这里有一种方法可以使用reflectand unsafe:


var t pkg.T

v := reflect.ValueOf(&t).Elem()

f := v.FieldByName("t")

rf := reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem()

rf.MethodByName("Print").Call(nil)

游乐场: https: //play.golang.org/p/CmG9e4Bl9gg


查看完整回答
反对 回复 2022-04-20
?
largeQ

TA贡献2039条经验 获得超8个赞

恐怕你试图做的事情通过反思是不可能的。


下面是 reflect.Call 的实现:


func (v Value) Call(in []Value) []Value {

    v.mustBe(Func)

    v.mustBeExported()

    return v.call("Call", in)

}

如您所见,是否从导出的字段中获得了明确的检查(即mustBeExported()) 。Value


通常没有导出字段是有原因的。如果要操作该字段,则必须使用ExportedStruct结构实现的方法。


如果您可以修改ExportedStruct定义的代码,则可以轻松地Close在其上实现包装器方法。例如:


type ExportedStruct struct{

  unexportedResource ExportedType

}


func (e ExportedStruct) Close(){

  e.unexportedResource.Close()

}


查看完整回答
反对 回复 2022-04-20
  • 3 回答
  • 0 关注
  • 226 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号