猿问

结构的方法签名之间的区别

作为一名来自 C++ 等其他语言的程序员,我觉得很奇怪,go 允许为允许指针或实例作为参数的结构指定方法。根据go by example,如果我们不想修改原点,once 可以使用它们中的任何一个:

Go 自动处理方法调用的值和指针之间的转换。您可能希望使用指针接收器类型来避免在方法调用上进行复制或允许该方法改变接收结构。

考虑以下代码:

package main


import (

    "fmt"

)


type Foo struct {}


type Bar struct {}


func (this Foo) String() string {

  return "Foo"

}


func (this *Bar) String() string {

  return "Bar"

}


func main() {

  fmt.Println(Foo{}) // "Foo"

  fmt.Println(Bar{}) // "{}"

}

为什么我不能同时使用两个签名版本来修改结构的stringify(我不知道它在 go 中实际上是如何调用的)行为?


明确一点:我并不真正关心字符串化,但想了解语言的行为方式。


有只小跳蛙
浏览 134回答 2
2回答

汪汪一只猫

只需添加&到Bar{}并使其成为指针接收器,如下所示:fmt.Println(&Bar{}) // "Bar"这里对输出的代码进行了一些调整:Foo Bar看:package mainimport "fmt"type Foo struct{}func (Foo) String() string {    return "Foo"}type Bar struct{}func (*Bar) String() string {    return "Bar"}func main() {    fmt.Println(Foo{}) // "Foo"    pb := &Bar{}    fmt.Println(pb) // "Bar"}笔记:收件人姓名应反映其身份;不要使用通用名称,例如“this”或“self”你的例子不需要名字。很高兴阅读Golang 方法接收器:值接收者对原始类型值的副本进行操作。这意味着涉及成本,尤其是在结构非常大的情况下,接收到的指针效率更高。

幕布斯7119047

因为 Bar 没有实现stringer*Bar 。如果您从 Foo 中删除的实现stringer,您将获得“{}”。同样,当你写fmt.Println(Bar{})它意味着它会寻找类似func (Bar) String()而不是func (*Bar) String()另外,当你写的时候故事是不同的fmt.Println(&Foo{}),你可能认为它会打印“{}”因为没有func (*Foo) String()但它会打印“Foo”。为此,您将必须了解接口。这些是我的经验,所以请也做你自己的研究。该fmt.Print函数对传递的参数调用 String()。所以实际上 String() 不是在你的结构上调用的,而是一个类型为 stringer 的变量。接口类型可以包含一个类型(实现它的)或指向它的指针,如果它是用值接收器实现的。这就是为什么Foo{}两者 &Foo{}都有效。接口类型只能保存一个类型的指针(实现它的指针),前提是它是用指针接收器实现的。为什么?因为当你实现一个带有指针接收器的接口时,它需要一个只能用指针提供的地址。这就是为什么只&Bar{} 起作用而不起作用的原因Bar{}
随时随地看视频慕课网APP

相关分类

Go
我要回答