总结
- 指针对象是用来存储内存地址的数据类型
- &符号获取对象的内存地址
- *符号根据内存地址获取值, 只有指针对象可以使用该符号
指针
仔细看代码注释, 应该描述得足够明细了
package main
import "fmt"
func main() {
// 重点句子1: 指针对象是用来存储内存地址的数据类型
// 重点句子2: &符号获取对象的内存地址
// 重点句子3: *符号根据内存地址获取值, 只有指针对象可以使用*符号
var p *int // 创建了一个int类型的指针对象
// fmt.Println(p) //此时 p 是 <nil>
// 创建一个int变量
var v = 20
fmt.Println(v) // 50 v得到了新值:50
fmt.Println(&v) // 0xc4200160a8 v的内存地址没有变化
// fmt.Println(*v) // 错误, v是一个int对象,不是一个指针对象
p = &v // &符号得到了v的内存地址, 赋值给指针p
// 此时 p指针已经有了一个内存地址了
fmt.Println(p) // 0xc4200160a8 这个是v的内存地址
fmt.Println(&p) // 0xc420016028 这个是p指针的内存地址, 一般用不到
fmt.Println(*p) // *符号会根据p所保存的内存地址,获取到该内存地址指向的值,即v的值
// 修改对象的值
v = 50
fmt.Println(v) // 50 v得到了新值:50
fmt.Println(&v) // 0xc4200160a8 v的内存地址没有变化
fmt.Println(p) // 0xc4200160a8 p还是这个v的地址,没有修改
fmt.Println(*p) // 50 *符号得到内存地址的值, v已经修改了,
// 通过指针修改对象的值
*p = 100
fmt.Println(v) // 100 v得到了新值:100
fmt.Println(&v) // 0xc4200160a8 v的内存地址没有变化
fmt.Println(p) // 0xc4200160a8 p还是这个v的地址,没有修改
fmt.Println(*p) // 100 *符号得到内存地址的值, v已经修改了,
}
结构体和指针
package main
import "fmt"
// Vertex 声明一个结构体
type Vertex struct {
X int
Y int
}
func main() {
// 实例化一个结构体
var v = Vertex{1, 2}
// 实例化一个结构体指针
var p *Vertex
// 把结构体的内存地址复制给指针
p = &v
// 以上三行一般情况下省略为:
// 实例化一个结构体指针
// var p = &Vertex{1, 2}
// 对比上一段普通指针的几种情况
fmt.Println(v) // {1, 2} 这是结构体值
fmt.Println(p) // &{1, 2} 这是结构体指针和普通指针的区别 直接显示对象地址 而不是0x123456的内存地址
fmt.Println(*p) // {1, 2} 结构体对象的值
fmt.Println(&p) // 和普通指针一样, *p是指针对象的内存地址, 和结构体无关系
fmt.Println(p) // &{1, 2} 这是结构体指针和普通指针的区别 直接显示对象地址 而不是0x123456的内存地址
// 根据上面这行的特性
fmt.Println(p.X) //1 可以直接访问结构体指针里的对象
fmt.Println(&v.X) //0xc420096010 v.X的内存地址
fmt.Println(&p.X) //0xc4200160b0 &p.X的内存地址和 v.X是一样的,因为它们是同一个对象
}