【golang指针笔记1】结构体变量存的不是结构体地址,而是结构体数据本身

90 阅读2分钟

先说结论

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对应的字符串也变了。

图解:

image.png