【问题标题】:Calling methods from derived type in Go在 Go 中从派生类型调用方法
【发布时间】:2016-09-06 11:58:18
【问题描述】:

我有两个文件 generic_handler.go,基本上看起来像这样:

type Handler struct{
    fields map[string]interface{}
}

func (handler *Handler) addField(key string, value interface{}){ some code }

还有 stat_handler.go:

type StatHandler Handler

当我尝试(从 stat_handler.go 文件中)调用这样的方法时,出现错误:

//inside some function
stathandler.addField("some field", "some value")

type StatHandler has no field or method addField 出错。即使我通过将addField 设置为AddField 来导出它也是一样的。这两个文件位于同一个包中。

我有什么遗漏吗?

【问题讨论】:

标签: go types


【解决方案1】:

声明的方法属于特定类型。 type 关键字创建一个 new 类型,它不会“继承”您在类型规范中使用的类型的方法。

你声明的方法addField()属于Handler,类型StatHandler没有任何方法,因为你没有指定任何方法作为接收者类型。

如果你有一个StatHandler 类型的变量并且你想调用addField() 方法,你需要有一个*Handler 类型的值。您可以使用type conversion 获得这样的值,例如:

s := StatHandler{}
(*Handler)(&s).addField("somekey", "someval")

注意,由于addField()有指针接收器,所以需要一个指针(因此使用了&地址运算符),但是*StatHandler只能转换为*Handler

如果您首先要有一个*StatHandler 指针:

sp := &StatHandler{}
(*Handler)(sp).addField("somekey", "someval")

由于新类型不会“继承”底层类型的方法,您应该考虑使用embedding 来实现您想要的,因为嵌入类型的方法和字段提升为嵌入类型:

type StatHandler struct {
    Handler // Embed Handler, so addField() method will be promoted
}

s2 := StatHandler2{}
s2.addField("somekey", "someval")

尝试Go Playground 上的示例。

规范中涵盖了类型具有哪些方法的确切定义:Method sets

【讨论】:

    【解决方案2】:

    在 Go 中,您通常会通过组合来做到这一点:

    type StatHandler struct {
        Handler  // Anonymous member of type Handler
    }
    
    // ...Later on
    var stathandler StatHandler
    stathandler.addField("some field", "some value")
    

    【讨论】:

    • 啊!我知道这很明显......我记得在 Go 文档中读到过这个,但我一定没有完全理解它。感谢您的帮助。
    【解决方案3】:

    请注意,在 Go 中,为了访问另一个包中的方法,您需要导出它,这意味着您必须将方法的第一个字母大写。

    type Handler struct{
        fields map[string]interface{}
    }
    
    func (handler *Handler) AddField(key string, value interface{}){ some code }
    

    如果你的包被命名为stathandler,你可以访问AddField方法:

    stathandler.AddField("some field", "some value")
    

    【讨论】:

    • 不要粗鲁,但您没有阅读问题。我已经尝试导出它,并且发生了同样的错误。它们在同一个包中。
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 2014-03-17
    • 2014-09-05
    • 2023-04-09
    • 1970-01-01
    • 2019-11-16
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多