龙空技术网

Go的结构体和结构体指针有什么区别?

壞尛孓Michael 83

前言:

此刻你们对“结构体指针指向哪里”大体比较注重,你们都想要知道一些“结构体指针指向哪里”的相关内容。那么小编也在网上收集了一些有关“结构体指针指向哪里””的相关资讯,希望小伙伴们能喜欢,咱们快快来学习一下吧!

大家好,这里是qsharing。

很多初学go语言的同学(当然也包括我自己)在学习到go结构体和方法的时候通常会遇到一个问题,结构体和结构体指针调用方法的时候到底应该用哪一个?根据官方的FAQ[1]并结合实际代码整理出这篇文章,希望能带给大家一些认识和思考

什么是结构体?

结构体struct是Go语言中常见的其中一个复合类型,举个例子:

type Student struct {  Name string}

这样就定义了一个结构体。

那么在实际开发中,我们会基于这个结构体构建一个实例:

package mainimport "fmt"type Student struct { Name string}func main() { s1 := Student{  Name: "qsharing",  Age: 18, } fmt.Println(s1.Name)}

程序运行的结果:

qsharing
结构体和结构体指针

接下来就是本文的主题,在实际开发中,我们通常会对结构体赋予一些方法,例如Setter,如下例子:

type Student struct { Name string}func (s Student) SetNameMethod1(name string) { s.Name = name}func (s *Student) SetNameMethod2(name string) { s.Name = name}

这段程序里面包含了两个结构体的方法,两个方法唯一的区别是一个是结构体,一个是结构体指针,那么两者在实际运行中有什么区别呢?

package mainimport "fmt"type Student struct { Name string}func (s Student) SetNameMethod1(name string) { s.Name = name}func (s *Student) SetNameMethod2(name string) { s.Name = name}func main() { // 构造结构体对象 s1 := Student{  Name: "student1", } s1.SetNameMethod1("qsharing") fmt.Println("调用结构体方法SetNameMethod1:", s1.Name) // 构造结构体指针 s2 := &Student{  Name: "student2", } s2.SetNameMethod2("qsharing") fmt.Println("调用结构体指针方法SetNameMethod2:", s2.Name)}

程序运行结果:

调用结构体方法SetNameMethod1: student1调用结构体指针方法SetNameMethod2: qsharing
区别

可以看出,虽然两个方法的程序逻辑是一致的,但是调用结构体指针的方法才能正确的设置Name,这是为什么呢?

因为作用于SetNameMethod1的结构体实际上是一个结构体的拷贝对象,修改这个拷贝对象的值不会影响原始对象的值。而作用于SetNameMethod2的结构体实际是指向结构体的同一块内存地址,因此修改结构体指针的值会正确反应到原始对象。

另外,使用结构体指针传递给方法,go语言会复制该变量的指针地址作为方法的地址(指向同一块内存地址)。而使用结构体传递给方法,go语言会先完整拷贝这个结构体,再传递给结构体的方法,从效率上来说,传递一个指针地址会比传递一个结构体拷贝要高效很多。

总结

简单来说,我们在使用结构体方法的时候需要注意:

该方法是否需要修改接收器?当需要改变结构体的内部元素值,那么就必须使用结构体指针的方法进行调用效率。如果结构体的值很大,那么传递一个结构体地址通常会比传递一个结构体效率更高一致性。如果该结构体的某些方法必须有指针接收器,其余的也应该如此,这样无论如何使用该结构体,方法集都是一致的

最后希望今天的文章能解答到同学们的疑惑。

参考资料

[1]

官方的FAQ:

标签: #结构体指针指向哪里