【问题标题】:GO - method redeclared errorGO - 方法重新声明错误
【发布时间】:2017-06-15 01:53:18
【问题描述】:

规则是,方法只能在命名类型和指向命名类型的指针上定义。


对于下面的code

package main

type Cat struct {
}

func (c Cat) foo() {
   // do stuff_
}

func (c *Cat) foo() {
  // do stuff_
}

func main() {

}

编译器报错:

main.go:10: method redeclared: Cat.foo
    method(Cat) func()
    method(*Cat) func()

以上代码定义,

方法foo() 用于命名类型(Cat)和

方法 foo() 用于指向命名类型的指针 (*Cat)。

问题:

对于 GO 编译器,为什么要考虑为不同类型定义的方法 一样吗?

【问题讨论】:

  • 出现这个错误,我怎么知道,要为允许的类型定义什么方法?
  • @dev.bmax 你怎么认为它是重复的?如果此查询得到答案 Ed 那么请分享它
  • 你启动的三个线程都是一样的。您采用一种语言功能,这对您来说毫无意义,并且您试图发现语言方法中的不一致之处。但是,社区每次都证明你错了。最后,您不接受得到文档和示例充分支持的答案,仅仅是因为它们不符合您的直觉。
  • @dev.bmax 看到你的回答后,我觉得这应该是我的第一个问题。我不是来接受你的答案,而是来学习。

标签: go methods types


【解决方案1】:

例如,您可以对一些猫科动物的行为进行建模,如下所示:

package main

import (
    "fmt"
)

type Growler interface{
    Growl() bool
}

type Cat struct{
    Name string
    Age int
} 

// *Cat is good for both objects and "object references" (pointers to objects)
func (c *Cat) Speak() bool{
    fmt.Println("Meow!")
    return true
}

func (c *Cat) Growl() bool{
    fmt.Println("Grrr!")
    return true
}


func main() {
    var felix Cat // is not a pointer
    felix.Speak() // works :-)
    felix.Growl() // works :-)

    var ginger *Cat = new(Cat) 
    ginger.Speak() // works :-)
    ginger.Growl() // works :-)
}

【讨论】:

    【解决方案2】:

    在 Go 中,接收者是一种语法糖。函数(c Cat) foo() 的实际运行时签名是foo(c Cat)。接收器被移动到第一个参数。

    Go 不支持名称重载。一个包中只能有一个名为foo的函数。

    说了上面的陈述,你会看到有两个名为foo 的函数具有不同的签名。该语言不支持。

    你不能在 Go 中做到这一点。经验法则是为指针接收器编写一个方法,只要你有一个指针或值,Go 就会使用它。

    如果您仍然需要两个变体,则需要以不同的方式命名方法。

    【讨论】:

    • 函数foo() 具有相同的签名。在(Cat)foo() & (*Cat)foo()方法中,第一个参数是receiver类型参数,签名不同。那么,签名如何相同?编译器不会抱怨函数(foo)具有相同的签名
    • @overexchange 如果您有var c Cat 并调用c.foo(),您如何区分要调用的方法?
    • @JonathonReinhart 1) 你是在问,如果 GO 编译器允许这两种方法,那么在说var c Cat;c.foo() 时,要调用哪个方法?接收器类型(c Cat) 应该是消除歧义的。 2) 当我说func (c*Cat)foo(){..} 定义方法时 for 接收器类型(*Cat) 但不是接收器类型(Cat) 和反之亦然 3) 出现这个错误,我为什么要知道,我需要定义哪个方法 func (c *Cat)foo(){..}func (c Cat)foo(){..} 因为方法 foo 具有不同的签名,第一个参数为具有命名类型的参数第二个作为指向命名类型的指针
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2023-04-02
    • 2013-02-25
    • 1970-01-01
    相关资源
    最近更新 更多