Golang教程中的第55和第57节讲解了接口和指针的使用。

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

Interfaces and Pointers in Golang tour #55 and #57

问题

在这两个教程示例中,为什么一个带有指针接收器的方法在一个案例中满足接口,而在另一个案例中却不满足接口?

示例#55中,类Vertex不满足Abser接口,因为方法Abs仅针对*Vertex定义,而不是Vertex

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

错误消息是:

prog.go:22: cannot use v (type Vertex) as type Abser in assignment:
    Vertex does not implement Abser (Abs method has pointer receiver)

但是在示例#57中,类MyError满足error接口,尽管Error()是为*MyError定义的,而不是MyError

type error interface {
    Error() string
}

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

根据这个答案中的描述,似乎两者都应该正常工作,但教程演示了第一个示例失败。有什么区别?

英文:

In these two tutorial examples, why does a method with a pointer receiver satisfy an interface in one case but not the other?

In example #55 the class Vertex doesn't satisfy the Abser interface because method Abs is only defined for *Vertex and not Vertex:

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

The error message is:

prog.go:22: cannot use v (type Vertex) as type Abser in assignment:
    Vertex does not implement Abser (Abs method has pointer receiver)

But in example #57, the class MyError satisfies the error interface ok even though Error() is defined for *MyError and not MyError:

type error interface {
    Error() string
}

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

From the description in this answer, it seems like both should work ok, but the tutorial demonstrates the first one failing. What's the difference?

答案1

得分: 6

在示例57中,错误被返回如下:

<!-- language-all: go -->

return &amp;MyError{
    time.Now(),
    "it didn't work",
}

这将返回一个指向MyError结构体的指针。而*MyError满足接口要求。

在示例55中也指出了这一点:

a = &amp;v // a *Vertex implements Abser

// 在下一行中,v是一个Vertex(而不是*Vertex)
// 并且不满足Abser接口。
a = v

正如你所引用的答案中所说,当情况相反时(*MyStruct类型将具有MyStruct的所有方法)。

英文:

in example57, the error is returned as such:

<!-- language-all: go -->

return &amp;MyError{
    time.Now(),
    &quot;it didn&#39;t work&quot;,
}

this returns a pointer to the MyError struct. And *MyError satisfies the interface.

In example55 this is also pointed out:

a = &amp;v // a *Vertex implements Abser

// In the following line, v is a Vertex (not *Vertex)
// and does NOT implement Abser.
a = v

As it says in the answer you are referring to, the generation occurs when it's the other way around (*MyStruct type will have all the methods MyStruct has)

答案2

得分: 3

在第57行中,只有*MyError满足error。正如你所看到的,从run()返回的值是*MyError,而不是MyError

func run() error {
    return &MyError{ // <<< 注意 '&'
        time.Now(),
        "it didn't work",
    }
}
英文:

In #57 only *MyError satisfies the error. As you can see, the value returned from run() is *MyError, not MyError:

func run() error {
    return &amp;MyError{ // &lt;&lt;&lt; Notice the &#39;&amp;&#39;.
        time.Now(),
        &quot;it didn&#39;t work&quot;,
    }
}

答案3

得分: 3

#57中,它返回了指向我的错误的指针:

return &MyError{ //注意"&"符号,表示返回该结构体的地址/指针。
    time.Now(),
    "它没有工作",
}
英文:

In #57 it is returning a pointer to my Error:

return &amp;MyError{ //notice the &quot;&amp;&quot;, that means return the address / pointer to that struct.
    time.Now(),
    &quot;it didn&#39;t work&quot;,
}

huangapple
  • 本文由 发表于 2014年7月14日 23:08:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/24739725.html
匿名

发表评论

匿名网友

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

确定