英文:
Accessing embedded methods in GoLang
问题
我正在尝试在Go语言中创建一些通用函数,用于处理许多不同的对象类型,其中一些类型嵌入了一个我创建的方便的子类型BaseObject。
我似乎无法弄清楚如何测试'Value interface{}'是否包含BaseObject,或者如何调用它的方法之一,例如ToString()...它应该返回[TestObject]而不是[BaseObject]
package Test
import (
"fmt"
"reflect"
)
func main() {
Value := TestObject{}
TestFunction(Value)
}
//通用函数
func TestFunction(Value interface{}) {
// 值是否包含BaseObject?reflect.TypeOf(Value).Contains...Implements??
// 转换为BaseObject?BO := Value.(BaseObject)
// 如果是,调用BO.ToString()
// fmt.println(BO.ToString())
}
//基础对象
type BaseObject struct {
}
func (this *HCObject) ToString() string {
return "[BaseObject]"
}
//测试对象
type TestObject struct {
BaseObject
}
func (this *TestObject) ToString() string {
return "[TestObject]"
}
英文:
I'm trying to create some generic functions in go that handle lots of different object types, some of the types embed a handy sub type I've created call BaseObject.
I can't seem to figure out how to test if 'Value interface{}' contains a BaseObject, or how to then call one of it's methods e.g. ToString()... which should return [TestObject] not [BaseObject]
package Test
import(
"fmt"
"reflect"
)
func main() {
Value:=TestObject{}
TestFunction(Value)
}
//Generic function
func TestFunction(Value interface{}){
// Does value contain BaseObject? reflect.TypeOf(Value).Containes...Implements??
//Convert to BaseObject? BO:=Value.(BaseObject)
// If it does, call BO.ToString()
//fmt.println(BO.ToString())
}
//Base Object
type BaseObject struct {
}
func (this *HCObject) ToString() string {
return "[BaseObject]"
}
//Test Object
type TestObject struct{
BaseObject
}
func (this *TestObject) ToString() string {
return "[TestObject]"
}
答案1
得分: 3
首先,有几点需要注意:
- 在play.golang.org上提供可运行的代码示例是一个很好的做法。
- 始终使用fmt对代码进行格式化。
ToString
应该是String
。参考fmt.Stringer
接口。- 正如其他人指出的,试图在Go中编写Java或C++代码会导致很多困难。
说完这些,这里 是一个可运行的代码示例,它可以实现你想要的功能,但有一些限制。
func TestFunction(v interface{}) {
fmt.Println(reflect.ValueOf(v).FieldByName("BaseObject").MethodByName("String").Call(nil)[0].String())
}
这段代码使用了 reflect
包(只有在真正需要时才应该使用)。我建议你尝试运行这个示例,并深入了解 reflect
,看看是否值得继续使用Go进行开发。
英文:
First of all, a couple of points:
- It is a good practice to give links to working code examples at play.golang.org.
- Always fmt your code.
ToString
should beString
. Seefmt.Stringer
interface.- As others have pointed out, trying to write Java of C++ in Go will end with a log of pain below the back.
With that said, this is a runnable example of the code that does what you want with many buts.
func TestFunction(v interface{}) {
fmt.Println(reflect.ValueOf(v).FieldByName("BaseObject").MethodByName("String").Call(nil)[0].String())
}
This code uses the reflect
package (which is something you should do only when you really need it). I suggest you play with that example and dig into reflect
to see, whether it's worth it to continue the way you go with Go.
答案2
得分: 2
你不会“嵌入”到interface{}
中。接口本身具有方法集,并包含某个值及其类型信息。
你可以使用类型断言从接口中提取值。
你的测试函数可以包含以下内容:
bo, ok := value.(BaseObject)
if ok {
fmt.Println(bo)
}
如果你想检查多个类型,可以使用类型开关。在你的情况下,TestObject
和BaseObject
是完全不同的类型;TestObject
不是BaseObject
。
switch bo := value.(type) {
case TestObject:
fmt.Println("TestObject", bo)
case BaseObject:
fmt.Println("BaseObject", bo)
}
如果你需要区分这两种类型,其中嵌入类型具有嵌入类型方法的超集,可以定义与你需要的方法匹配的接口。
type Base interface {
MethodA()
}
type Sub interface {
MethodA()
MethodB()
}
在这种情况下,Sub
是Base
,因为满足Sub
接口的任何内容也满足Base
接口。
英文:
You don't "embed" into an interface{}
. Interfaces themselves have a method set, and contain some value and it's type information.
You extract a value from an interface using a Type Assertion.
Your test function could contain something like:
bo, ok := value.(BaseObject)
if ok {
fmt.Println(bo)
}
If you want to check for more than one type, you use a type switch. In your case, TestObject and BaseObject are completely different types; TestObject is not a BaseObject.
switch bo := value.(type) {
case TestObject:
fmt.Println("TestObject", bo)
case BaseObject:
fmt.Println("BaseObject", bo)
}
If you need to distinguish between the two types, with the embedding type having a superset of the embedded type's methods, define interfaces that match the methods you need.
type Base interface {
MethodA()
}
type Sub interface {
MethodA()
MethodB()
}
In this case Sub
is a Base
, in that anything that fulfills the Sub
interface, also fulfills the Base
interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论