golang结构体指针
引言:在go语言中,我们如何修改一个的结构体的属性呢?
type Student struct {
Name string
}
修改失败案例
package main
import "fmt"
//定义一个结构体 属性Name
type Student struct {
Name string
}
//方法接收者 :即我们附加在函数名前面的参数
//类型为Student
//方法没有返回类型
func (s Student) FixNameMethod1(name string) {
s.Name = name
}
func main() {
s := Student{"xiaozhu"}
fmt.Println("原有名字:", s.Name)
fmt.Println("使用方法1修改名字")
s.FixNameMethod1("xiaolan")
fmt.Println("修改后的名字:", s.Name)
}
运行程序后我们发现案例1并没有修改成功
分析
我们创建的s想要调用FixNameMethod1
,实参是按照值传递的,所以FixNameMethod1
接收到的是实参的副本,也就是s的复制品。既然是副本,那么我们在FixNameMethod1
修改形参接收者的属性并不会影响到实参本身的属性
修改成功案例
package main
import "fmt"
//定义一个结构体 属性Name
type Student struct {
Name string
}
//方法接收者参数类型为*Student
func (s *Student) FixNameMethod2(name string) {
s.Name = name
}
func main() {
s := Student{"xiaozhu"}
fmt.Println("原有名字:", s.Name)
fmt.Println("使用方法1修改名字")
s.FixNameMethod1("xiaolan")
fmt.Println("修改后的名字:", s.Name)
fmt.Println("使用方法2修改名字")
FixNameMethod2("lanlan")
fmt.Println("修改后的名字:", s.Name)
}
运行程序后发现这次修改成功
分析
我们本次方法接收者使用的参数类型是一个指向Student类型的指针,这样我们就间接的修改了实参变量
后续
但是在学习过程中 又遇到了一个新的问题
//方法接收者参数类型为*Student
func (s *Student) FixNameMethod2(name string) {
s.Name = name
}
上述方法的方法接收者的类型是一个指向Student指针类型(*Student),而我传递给它的是一个s := Student{"xiaozhu"}
, 这并不是一个指针。
那我们为什么可以修改成功呢?我又修改了一下代码加以验证
//s.FixNameMethod2("lanlan") 修改为以下代码
(&s).FixNameMethod2("lanlan")
发现名称果然可以修改成功
分析
s.FixNameMethod2("lanlan") //相当于隐式的转化为(&s).FixNameMethod2("lanlan")
我们使用未修改前的语句时,实参接收者是Student类型的变量,形参接收者是*Student类型的变量,go的编译器会隐式的获取变量的地址, 因此我们可以修改成功
补充一点,我们上面的方法修改值的过程中,直接使用了 (s.Name = name)指针 . 属性的方式。
//方法接收者参数类型为*Student
func (s *Student) FixNameMethod2(name string) {
s.Name = name
}
我们在c/c++当中使用的是->
操作符来访问成员
举个例子
如果 him == &barney
, 那么 him->income
,即是barney.income
但是在go语言中,编译器是帮我们隐式的解引用获取实际的值,因此我们完整的写下来是:
(*s).Name = name
指针Or结构体
那么我们的方法接收者的参数类型何时使用指针类型 何时使用结构体类型呢?
go语言中所有的函数参数都是值拷贝。如果结构体较大,一般使用指针参数,这样可以避免复制整个实参,并且如果要在函数修改结构体的属性,则必须使用指针参数。
再总结一下
使用指针的优点
- 执行快,效率高
- 可以修改数据
使用指针的缺点
- 无法保护数据,原始数据容易修改
使用结构体的优点
- 处理的是原始数据的副本,这样保护了原始数据
- 代码风格非常清晰明了(更贴近于java语言)
使用结构体的缺点
- 不能修改属性
- 传递结构体浪费时间和空间,尤其是较大的结构体
参考书籍:《Go程序设计语言》、《C Primer Plus》
如有错误和冒犯,欢迎指出