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

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

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

Go
达令说 2023-08-07 19:05:20
我知道,已经有人问过类似的问题,但我没有找到该案例的答案: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贡献1798条经验 获得超3个赞

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

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

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


查看完整回答
反对 回复 2023-08-07
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

但这里有一种使用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


查看完整回答
反对 回复 2023-08-07
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

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


下面是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()

}


查看完整回答
反对 回复 2023-08-07
  • 3 回答
  • 0 关注
  • 126 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信