指针操作
# 数组指针
package main
import "fmt"
func main() {
//数组指针,指向数组的指针
var n = [3]int{1, 2, 3}
var p *[3]int = &n
//指针数组,数组成员的类型是指针
var q = [3]*int{&n[0], &n[1], &n[2]}
fmt.Println("指针数组...")
for i, v := range q {
fmt.Println(i, v, *v)
}
fmt.Println("数组指针...")
for i, v := range p {
fmt.Println(i, &v, v)
}
}
指针数组...
0 0xc0000aa060 1
1 0xc0000aa068 2
2 0xc0000aa070 3
数组指针...
0 0xc0000a6058 1
1 0xc0000a6058 2
2 0xc0000a6058 3
数组指针中的地址是相同的,因为它们指向同一个数组的起始位置。而指针数组中的每个元素是独立的指针,它们存储了不同的地址。
package main
import "fmt"
func main() {
// 1.定义一个切片
var sce []int = []int{1, 3, 5}
// 2.打印切片的地址
// 切片变量中保存的地址, 也就是指向的那个数组的地址 sce = 0xc0420620a0
fmt.Printf("sce = %p\n", sce)
fmt.Println(sce) // [1 3 5]
// 切片变量自己的地址, &sce = 0xc04205e3e0
fmt.Printf("&sce = %p\n", &sce)
fmt.Println(&sce) // &[1 3 5]
// 3.定义一个指向切片的指针
var p *[]int
// 因为必须类型一致才能赋值, 所以将切片变量自己的地址给了指针
p = &sce
// 4.打印指针保存的地址
// 直接打印p打印出来的是保存的切片变量的地址 p = 0xc04205e3e0
fmt.Printf("p = %p\n", p)
fmt.Println(p) // &[1 3 5]
// 打印*p打印出来的是切片变量保存的地址, 也就是数组的地址 *p = 0xc0420620a0
fmt.Printf("*p = %p\n", *p)
fmt.Println(*p) // [1 3 5]
// 5.修改切片的值
// 通过*p找到切片变量指向的存储空间(数组), 然后修改数组中保存的数据
(*p)[1] = 666
fmt.Println(sce[1])
}
在 Golang 中,指向字典和结构体的指针使用方式略有不同。下面分别介绍一下:
# 指向字典的指针
在 Golang 中,字典(map
)本身就是一个引用类型,所以通常情况下我们不会直接使用指向字典的指针。字典本身就是一个引用,使用起来非常方便,不需要额外的指针操作。
示例代码如下:
package main
import "fmt"
func main() {
// 创建一个字典
dict := make(map[string]int)
// 添加键值对
dict["apple"] = 5
dict["banana"] = 3
// 直接使用字典
fmt.Println(dict)
// 指向字典的指针
var dictPtr *map[string]int // 这种声明通常不常用
// 直接操作字典
dict["apple"] = 7
fmt.Println(dict)
}
# 指向结构体的指针
结构体(struct
)是 Golang 中的一种复合数据类型,与字典不同,结构体通常需要通过指针来进行操作,特别是在函数传递和修改结构体字段时。
示例代码如下:
package main
import "fmt"
// 定义一个结构体
type Person struct {
Name string
Age int
}
func main() {
// 创建一个结构体变量
var p1 Person
p1.Name = "Alice"
p1.Age = 30
// 使用结构体变量
fmt.Println(p1)
// 指向结构体的指针
var p2 *Person
p2 = &p1 // p2 指向 p1
// 使用指针操作结构体字段
p2.Age = 31
// 打印修改后的结构体变量
fmt.Println(p1)
}
在上面的例子中,p2
是指向 Person
结构体的指针,通过 p2
可以修改 p1
的字段值。
- 字典:字典本身就是引用类型,不常见直接使用指向字典的指针。
- 结构体:结构体通常需要通过指针来进行操作,特别是在函数间传递和修改结构体的字段时,使用指针可以避免值拷贝的开销。
# 结构体指针表示指向结构体实例的指针
它是指向结构体在内存中分配的位置的引用。可以使用 new 关键字或 &运算符创建结构体指针。
type Person struct {
Name string
Age int
}
var p Person = new(Person) // 使用 new 关键字创建结构体指针
p.Name = "John Doe"
p.Age = 30
指针结构体是指包含指向其他类型的指针的结构体。
也就是说,指针结构体的字段是指向其他类型的指针。指针结构体自身不是指针类型,而是一个结构体类型。
type Person struct {
Name *string
Age *int
}
name := "John Doe"
age := 30
p := Person{
Name: &name,
Age: &age,
}
注意上述示
例中,Name 和 Age 字段都是指向字符串和整数的指针。
因此,结构体指针和指针结构体在概念上有所区别。结构体指针指向结构体实例本身,而指针结构体的字段是指向其他类型的指针。 当使用结构体指针时,可以直接通过指针访问和修改结构体的字段。而在指针结构体中,需要通过解引用指针来访问和修改字段值。
总结起来:结构体指针指向结构体对象,而指针结构体包含指向其他类型的指针。它们在用途和操作上有所不同,尽管有时可以使用类似的语法。