在Go语言中访问嵌入方法的方式

huangapple go评论142阅读模式
英文:

Accessing embedded methods in GoLang

问题

我正在尝试在Go语言中创建一些通用函数,用于处理许多不同的对象类型,其中一些类型嵌入了一个我创建的方便的子类型BaseObject。

我似乎无法弄清楚如何测试'Value interface{}'是否包含BaseObject,或者如何调用它的方法之一,例如ToString()...它应该返回[TestObject]而不是[BaseObject]

  1. package Test
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. func main() {
  7. Value := TestObject{}
  8. TestFunction(Value)
  9. }
  10. //通用函数
  11. func TestFunction(Value interface{}) {
  12. // 值是否包含BaseObject?reflect.TypeOf(Value).Contains...Implements??
  13. // 转换为BaseObject?BO := Value.(BaseObject)
  14. // 如果是,调用BO.ToString()
  15. // fmt.println(BO.ToString())
  16. }
  17. //基础对象
  18. type BaseObject struct {
  19. }
  20. func (this *HCObject) ToString() string {
  21. return "[BaseObject]"
  22. }
  23. //测试对象
  24. type TestObject struct {
  25. BaseObject
  26. }
  27. func (this *TestObject) ToString() string {
  28. return "[TestObject]"
  29. }
英文:

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]

  1. package Test
  2. import(
  3. "fmt"
  4. "reflect"
  5. )
  6. func main() {
  7. Value:=TestObject{}
  8. TestFunction(Value)
  9. }
  10. //Generic function
  11. func TestFunction(Value interface{}){
  12. // Does value contain BaseObject? reflect.TypeOf(Value).Containes...Implements??
  13. //Convert to BaseObject? BO:=Value.(BaseObject)
  14. // If it does, call BO.ToString()
  15. //fmt.println(BO.ToString())
  16. }
  17. //Base Object
  18. type BaseObject struct {
  19. }
  20. func (this *HCObject) ToString() string {
  21. return "[BaseObject]"
  22. }
  23. //Test Object
  24. type TestObject struct{
  25. BaseObject
  26. }
  27. func (this *TestObject) ToString() string {
  28. return "[TestObject]"
  29. }

答案1

得分: 3

首先,有几点需要注意:

  • 在play.golang.org上提供可运行的代码示例是一个很好的做法。
  • 始终使用fmt对代码进行格式化。
  • ToString 应该是 String。参考 fmt.Stringer 接口。
  • 正如其他人指出的,试图在Go中编写Java或C++代码会导致很多困难。

说完这些,这里 是一个可运行的代码示例,它可以实现你想要的功能,但有一些限制。

  1. func TestFunction(v interface{}) {
  2. fmt.Println(reflect.ValueOf(v).FieldByName("BaseObject").MethodByName("String").Call(nil)[0].String())
  3. }

这段代码使用了 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 be String. See fmt.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.

  1. func TestFunction(v interface{}) {
  2. fmt.Println(reflect.ValueOf(v).FieldByName("BaseObject").MethodByName("String").Call(nil)[0].String())
  3. }

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{}中。接口本身具有方法集,并包含某个值及其类型信息。

你可以使用类型断言从接口中提取值。

你的测试函数可以包含以下内容:

  1. bo, ok := value.(BaseObject)
  2. if ok {
  3. fmt.Println(bo)
  4. }

如果你想检查多个类型,可以使用类型开关。在你的情况下,TestObjectBaseObject是完全不同的类型;TestObject不是BaseObject

  1. switch bo := value.(type) {
  2. case TestObject:
  3. fmt.Println("TestObject", bo)
  4. case BaseObject:
  5. fmt.Println("BaseObject", bo)
  6. }

如果你需要区分这两种类型,其中嵌入类型具有嵌入类型方法的超集,可以定义与你需要的方法匹配的接口。

  1. type Base interface {
  2. MethodA()
  3. }
  4. type Sub interface {
  5. MethodA()
  6. MethodB()
  7. }

在这种情况下,SubBase,因为满足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:

  1. bo, ok := value.(BaseObject)
  2. if ok {
  3. fmt.Println(bo)
  4. }

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.

  1. switch bo := value.(type) {
  2. case TestObject:
  3. fmt.Println("TestObject", bo)
  4. case BaseObject:
  5. fmt.Println("BaseObject", bo)
  6. }

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.

  1. type Base interface {
  2. MethodA()
  3. }
  4. type Sub interface {
  5. MethodA()
  6. MethodB()
  7. }

In this case Sub is a Base, in that anything that fulfills the Sub interface, also fulfills the Base interface.

huangapple
  • 本文由 发表于 2014年9月2日 22:23:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/25625757.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定