& 括号星号原则:由于编辑器的抵触,( * ) 仅仅是代表一个星号而已
& 不指向地址的指针为空原则:声明指针却没有指向地址,那么这个指针的地址将为 nil(空)
& 指针首先分配地址空间原则:声明指针之后首先得分配一段内存空间,才能对指针的值进行读写操作
& 指针不喜欢变量地址原则:声明指针之后使用语句 p = new(int) 用来分配一段 int 内存空间,而不是指向变量的地址 p = &a
指针的定义和初始化
语法:var 指针名 (*)指针类型
package main
import "fmt"
func main() {
// 1. 定义指针变量和 int 类型的变量
var p_int *int
num1 := 100
// 2. 使指针 p_int 指向变量 num1 的地址
p_int = &num1
// 3. 修改指针的值在本质上也就修改了它指向的值
*p_int = 200
fmt.Println(num1) // 200
}
重点(即不指向地址的指针为空原则):没有指向变量地址的指针是空的(nil)
package main
import "fmt"
func main() {
var p_int *int
fmt.Println(p_int) // <nil>
num1 := 100
p_int = &num1
fmt.Println(p_int) // 0xc0000160d0
}
野指针:指针指向未知的空间(即指针首先分配地址空间原则)
package main
func main() {
// 野指针 -- 指向未知的空间
var p_int *int
//*p_int = 100 // invalid memory address or nil pointer dereference
}
创建内存空间(即指针不喜欢变量原则)
package main
import "fmt"
func main() {
var p_int *int
p_int = new(int)
*p_int = 100
fmt.Println(*p_int) // 100
}
自动推导类型
package main
import "fmt"
func main() {
// 自动推导类型
// 1. 分配变量的地址
num := 100
p := &num
fmt.Println(*p) // 100
// 2. 创建地址空间
p1 := new(int)
*p1 = 200
fmt.Println(*p1) // 200
}
指针作为函数形参
重点:地址传递
package main
import "fmt"
// 交换 a 和 b 的值
func Swap(a *int, b *int) {
*a, *b = *b, *a
}
func main() {
num1, num2 := 1, 2
fmt.Println(num1, num2) // 1 2
Swap(&num1, &num2)
fmt.Println(num1, num2) // 2 1
}
数组指针
数组指针声明及赋值过程
步骤:首先初始化数组,然后声明数组指针,最后将指针指向数组
package main
import "fmt"
func main() {
// 1. 定义长度为 3 的数组
arr := [3]int{1, 2, 3}
// 2. 定义数组指针
var p *[3]int
// 3. 指针指向数组
p = &arr
// 4. 打印指针的值
fmt.Println(*p) // [1 2 3]
}
数组指针初始化过程(即自动推导)
package main
import "fmt"
func main() {
// 1. 定义长度为 3 的数组
arr := [3]int{1, 2, 3}
// 2. 指针指向数组
p := &arr
// 3. 打印指针的值
fmt.Println(*p) // [1 2 3]
}
数组指针的使用
语法:(*)数组指针名[索引项] = 值 OR 数组指针名[索引项] = 值
package main
import "fmt"
func main() {
// 1. 定义长度为 3 的数组
arr := [3]int{1, 2, 3}
// 2. 指针指向数组
p := &arr
// 3. 使用数组指针
(*p)[0] = 100
p[1] = 200
// 4. 打印数组指针
fmt.Println(*p) // [100 200 3]
}
数组指针作为函数形参
重点:地址传递
package main
import "fmt"
func Test(p *[3]int) {
p[1] = 100
}
func main() {
arr := [3]int{1, 2, 3}
fmt.Println(arr) // [1 2 3]
Test(&arr)
fmt.Println(arr) // [1 100 3]
}
指针数组
简单形式
package main
import "fmt"
func main() {
num1, num2, num3 := 1, 2, 3
var p [3]*int = [3]*int{&num1, &num2, &num3}
fmt.Println(p) // [0xc0000ac058 0xc0000ac070 0xc0000ac078]
fmt.Println(*p[0]) // 1
fmt.Println(*p[1]) // 2
fmt.Println(*p[2]) // 3
}
复杂形式
package main
import "fmt"
func main() {
arr1, arr2, arr3 := [3]int{1, 2, 3}, [3]int{4, 5, 6}, [3]int{7, 8, 9}
var p [3]*[3]int = [3]*[3]int{&arr1, &arr2, &arr3}
fmt.Println(p) // [0xc0000141c8 0xc0000141e0 0xc0000141f8]
fmt.Println(*p[0]) // [1 2 3]
fmt.Println(*p[1]) // [4 5 6]
fmt.Println(*p[2]) // [7 8 9]
}
切片指针
切片指针初始化过程(即自动推导)
package main
import "fmt"
func main() {
slice_p := &[]int{1, 2, 3}
fmt.Println(*slice_p) // [1 2 3]
*slice_p = append(*slice_p, 4, 5, 6)
fmt.Println(*slice_p) // [1 2 3 4 5 6]
}
切片指针作为函数形参
重点:地址传递
package main
import "fmt"
func Test(p *[]int) {
*p = append(*p, 4, 5, 6)
}
func main() {
slice_p := &[]int{1, 2, 3}
Test(slice_p)
fmt.Println(*slice_p) // [1 2 3 4 5 6]
}
结构体指针
package main
import "fmt"
type Student struct {
id int
score int
}
func main() {
// 自动推导
struct_p := &Student{1, 100}
fmt.Println(*struct_p) // {1 100}
// 声明及赋值
var struct_p1 *Student = &Student{2, 90}
fmt.Println(*struct_p1) // {2 90}
}
结构体指针的使用
package main
import "fmt"
type Student struct {
id int
score int
}
func main() {
// 声明及赋值
var struct_p1 *Student = &Student{2, 90}
fmt.Println(*struct_p1) // {2 90}
// 通过指针间接改变结构体内的属性
(*struct_p1).score = 1000
// 通过指针直接改变结构体内的属性
struct_p1.id = 10
fmt.Println(*struct_p1) // {10 1000}
}
结构体指针作为函数形参
重点:地址传递
package main
import "fmt"
type Student struct {
id int
score int
}
func Test(struct_p *Student) {
struct_p.score = 72
}
func main() {
// 声明及赋值
var struct_p1 *Student = &Student{2, 90}
fmt.Println(*struct_p1) // {2 90}
Test(struct_p1)
fmt.Println(*struct_p1) // {2 72}
}
结构体数组指针
package main
import "fmt"
type Student struct {
id int
score int
}
func main() {
struct_p := &[3]Student{
{1, 100},
{1, 100},
{1, 100},
}
fmt.Println(*struct_p) // [{1 100} {1 100} {1 100}]
struct_p[0].score = 1000
fmt.Println(*struct_p) // [{1 1000} {1 100} {1 100}]
}
map 类型的结构体指针
package main
import "fmt"
type Student struct {
id int
score int
}
func main() {
// 字典的键为整数
// 字典的值为 结构体类型的数组指针
m := make(map[int]*[3]Student)
m[1] = &[3]Student{
{1, 100},
{2, 200},
{3, 300},
}
fmt.Println(*(m[1])) // [{1 100} {2 200} {3 300}]
}
多级指针
package main
import "fmt"
func main() {
// 一级指针 -- 指向变量的地址
num1 := 1
p := &num1
fmt.Println(*p) // 1
// 二级指针 -- 指向一级指针的地址
pp := &p
fmt.Println(pp) // 0xc0000d8028 -- 二级指针的地址
fmt.Println(*pp) // 0xc000016098 -- 一级指针的地址
fmt.Println(**pp) // 1 -- 一级指针指向的值
}