先说结论
Golang中的结构体和Java中的对象很相似,都可以有多个属性和方法。但,Golang中的结构体类型变量和Java中的对象类型变量(也叫引用类型变量)不同:
Java中,对象类型变量的值是对象的地址,而Golang中,结构体类型变量的值却不是结构体的地址,而是结构体数据本身。
Java中,只有值传递,只能传递变量的值,变量的值要么是基础类型值,要么是引用值(即对象的地址)。
Golang中,既有值传递,也有引用传递,既可以传递变量的值,也能取变量的地址、传递变量的地址。
再看现象
看看如下的程序:
type ASD struct {
Name string
}
func main() {
test1()
}
func test1() {
// 这里并不是说asd变量指向一个对象,而是这个变量的值是对象
asd := ASD{
"1111",
}
var s *string
s = &asd.Name
fmt.Println("*s:", *s)
asd.Name = "2222"
fmt.Println("*s:", *s)
// 这里是【值传递】,所以asd变量的Name属性值被更新了
asd = ASD{
"aaa",
}
fmt.Println("*s:", *s)
}
输出:
*s: 1111
*s: 2222
*s: aaa
分析现象
和Java不一样,Java里给一个变量赋值对象(类似Golang的结构体),变量存的是对象的地址,然后修改对象类型变量的值实则是变量指向了另一个对象
Golang中,一个结构体变量存的就是结构体数据本身(而不是结构体的地址),结构体变量声明时就分配好了内存(字段默认存对应数据类型的零值),后续修改结构体变量的值,就是修改内存中结构体数据本身。
所以,上面的程序里指针变量s一直指向asd结构体的Name属性的地址。后续修改asd变量值,就改变了Name属性的值,所以指针变量s对应的字符串也变了。
图解: