接收者的用法
package main
import "fmt"
type Person struct {
name string
age int
}
func (p *Person) greeting1() {
fmt.Println(p) //&{0}
fmt.Println(&p) //0xc000086018
fmt.Println("Hello~")
}
func (p Person) greeting2() {
fmt.Println(p) //{0}
fmt.Println(&p) //&{0}
fmt.Println("Hello~")
}
type Student struct {
//p Persion -> has a
Person // -> is a
school string
grade int
}
func test1(p Student) {
fmt.Println(p)
}
func test2(p *Student){
fmt.Println(p)
}
func main() {
var s Student
//s.p.greeting()
s.greeting1()
s.greeting2()
test1(s)
//test2(s) -> error
}
当我在golang中使用函数时,如果我声明了值变量,那么当我使用自己制作的函数时,我只需要将值变量放在参数上。喜欢,
a int= 10;
func func1(param int){
fmt.Println(fmt)
}
尽管我在“学生”结构中将“人”声明为值结构, 如您所见,我的代码 接收器函数(greeting1,greeting2)正在获取两个类型参数,分别是* Person和Person。 尽管我将value变量作为参数,但我无法理解为什么greeting1函数正常运行。 谢谢大家的帮助。
答案 0 :(得分:1)
简化示例代码,重点关注当前的问题:
package main
import "fmt"
type Person struct {
name string
age int
}
func (p *Person) greeting1() {
fmt.Println(p)
fmt.Println(&p)
}
func main() {
var p Person
p.name = "joe"
p.age = 41
p.greeting1()
}
打印:
&{joe 41}
0xc00000c028
简而言之,调用p.greeting1()
之所以有效,是因为Go看到Person
(p
的类型)在指针接收器上定义了一个greeting1
方法。因此,它将呼叫p.greeting1()
等同于(&p).greeting1()
。正如mkopriva在评论中所说,这在Go spec中明确列出:
如果x的方法集(的类型)有效,则x.m()方法调用有效 包含m并且参数列表可以分配给参数列表 的米如果x是可寻址的并且&x的方法集包含m,则x.m()为 (&x).m()
的简写
这样做是为了方便。由于指针接收器在Go中非常必要且很流行-当方法改变基础对象时,您就需要它们-它有助于编写更简洁的代码。您不应被迫在(&p).greeting1()
会写的地方写p.greeting1()
-这种替换是明确的,因为编译器知道Person
上定义了哪些方法,以及接收者。
Effective Go在pointer vs. value receivers上有一个部分,您应阅读。这是一个相关的报价:
当值是可寻址的时,该语言将照顾通用 通过插入地址在值上调用指针方法的情况 自动操作。在我们的示例中,变量b是可寻址的, 因此我们可以仅使用b.Write调用其Write方法。编译器将 将其重写为(&b)。为我们写信。
答案 1 :(得分:0)
实际上Go本身就是一种面向对象的语言。它使用结构而不是类。如果您想拥有一个类,则必须创建一个结构,并通过该结构的指针将一些函数与该函数相关联,以便稍后可以从该结构中创建许多独立的对象。您可以使用new函数,该函数将返回结构的指针。喜欢:
p:=new(person)
p.name = "joe"
p.age = 41
p.greeting1()