猿问

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

我知道,已经有人问过类似的问题,但我没有找到该案例的答案:


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 object

resourceField := 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,但只要不使用底层资源我就不能运行。


由于我可以访问私有字段(如此处所述),我有点希望我也可以以某种方式访问该字段的公共方法。也许我只是反映错误?


达令说
浏览 133回答 3
3回答

呼如林

未导出的字段仅用于声明包。别再惹他们了。他们不适合你。链接的答案只能通过使用 package 来访问它unsafe,这不适合日常使用。包装unsafe中应附有“请勿触摸”手册。如果您确实需要访问unexportedResource,请将其导出。要么是字段,要么向调用 的类型添加一个方法unexportedResource.Close()。或者向包中添加执行此操作的实用程序函数(同一包中的函数可以访问未导出的字段和标识符)。

至尊宝的传说

但这里有一种使用reflectand来做到这一点的方法unsafe:var t pkg.Tv := 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

慕码人2483693

恐怕你想要做的事情通过反思是不可能的。下面是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()}
随时随地看视频慕课网APP

相关分类

Go
我要回答