默认指针类型
类型 |
名称 |
长度 |
默认值 |
pointer |
指针 |
|
nil |
array |
数组 |
|
0 |
slice |
切片 |
|
nil |
map |
字典 |
|
nil |
struct |
结构体 |
|
|
1. 变量和内存地址
- go 语言中指针是很容易学习的,比 C 中容易的多,它可以更简单地执行一些任务
- 每个变量都有内存地址,可以理解为变量来操作对应的内存
- go 语言的
取地址符是&
,放到一个变量前使用就会返回相应变量的内存地址
package main
import "fmt"
func main() {
var a int
a = 0
// 使用 & 符号获取变量地址
fmt.Println(&a)
fmt.Printf("变量a的地址是: %x\n", &a)
}
2. 值类型和指针类型
- 普通变量存储的是对应类型的值,这些类型叫值类型
(var a int = 10)
- 指针也是一个变量,用于存储另一个变量的内存地址,变量存的是值,指针存的是一个地址,这个地址指向的空间存的才是值,所以指针又叫引用类型
- 与变量类似,使用前需要声明
- 声明指针的格式:
var 指针变量名 *指针类型
- 指针的使用
package main
import "fmt"
func main() {
var a int
a = 10
var p *int
// 指针类型存变量地址
p = &a
fmt.Printf("变量a的地址: %x\n", &a)
fmt.Printf("指针类型p指向a地址的值: %x\n", p)
fmt.Printf("指针类型p获取指针变量的值: %d\n", *p)
}
3. 空指针
- 当一个指针被定义后没有分配到任何变量时,它的值为
nil
- 空指针的判断
package main
import "fmt"
func main() {
var p *int
fmt.Println(p)
fmt.Printf("p的值%x\n", p)
// 判断类型是否为空
if p != nil {
fmt.Println("非空")
} else {
fmt.Println("空")
}
}
4. 值传递和引用传递
package main
import "fmt"
func swap(a, b *int) {
// 交换语法,必须交换值
//a, b = b, a
*a, *b = *b, *a
}
func main() {
a, b := 10, 20
fmt.Println(a, b)
swap(&a, &b)
fmt.Println(a, b)
}
package main
import "fmt"
func swap(a, b *int) (*int, *int) {
a, b = b, a
return a, b
}
func main() {
a, b := 10, 20
fmt.Println(a, b)
c, d := swap(&a, &b)
fmt.Println(*c, *d)
fmt.Println(&a, &b)
// 这里可以打断点,导致连锁反应
a = *c
b = *d
fmt.Println(a, b)
}
5. new()和 make()
- make()用来分配引用类型的内存,例如 slice、map、channel,并且初始化内存
- new()用来分配各种类型的内存,但它不会初始化内存
- make()的用途不同于 new(),它只能创建 slice、map、channel,并返回类型为 T(非指针)的已初始化(非零值)的值
package main
import "fmt"
func main() {
a := new([]int)
fmt.Println(a)
b := make([]int, 10, 20)
fmt.Println(b)
}
// 输出结果
// &[]
// [0 0 0 0 0 0 0 0 0 0]