Go 语言-->指针
Go 语言–>指针
它允许你操作内存中的实际数据,而不仅仅是数据的副本。指针存储的是另一个变量的内存地址,而不是变量的实际值。
1. 什么是指针
指针是存储变量内存地址的变量,它指向另一个变量。通过指针,你可以间接地访问和修改那个变量的值。
- 指针变量:指针存储一个内存地址,这个内存地址指向一个具体的值。
- 解引用:通过指针访问指向的变量的值。
2. 声明指针
在 Go 中,指针通过在类型前加上 *
来声明。例如,*int
表示一个指向 int
类型的指针。
示例:声明指针
var ptr *int // ptr 是一个指向 int 类型的指针
3. 获取指针(取地址)
使用 &
操作符可以获得一个变量的内存地址,这叫做取地址。
示例:获取指针
package mainimport "fmt"func main() {var a int = 58var ptr *int = &a // ptr 保存 a 的地址fmt.Println("a 的值:", a) // 输出:a 的值: 58fmt.Println("ptr 的值:", ptr) // 输出:ptr 的值: &afmt.Println("ptr 指向的值:", *ptr) // 输出:ptr 指向的值: 58
}
&a
:返回变量a
的内存地址。*ptr
:返回指针ptr
所指向的变量的值。
4. 通过指针修改变量值
通过指针可以间接修改变量的值。通过解引用(*ptr
)可以修改指针所指向的变量的值。
示例:通过指针修改值
package mainimport "fmt"func main() {var a int = 58var ptr *int = &a // ptr 指向 a 的地址fmt.Println("修改前 a 的值:", a) // 输出:修改前 a 的值: 58*ptr = 100 // 通过指针修改 a 的值fmt.Println("修改后 a 的值:", a) // 输出:修改后 a 的值: 100
}
5. 指针与函数传参
Go 中的函数传参是按值
传递的,这意味着函数内部的参数是传入值的副本。如果你想要在函数内修改参数的值,必须通过指针传递。
示例:通过指针修改函数参数的值
package mainimport "fmt"func modifyValue(ptr *int) {*ptr = 500 // 修改 ptr 指向的变量的值
}func main() {a := 100fmt.Println("修改前 a 的值:", a) // 输出:修改前 a 的值: 100modifyValue(&a) // 将 a 的地址传递给函数fmt.Println("修改后 a 的值:", a) // 输出:修改后 a 的值: 500
}
6. 零值指针
Go 中的指针默认值是 nil
,即如果一个指针没有指向任何地址,它的默认值是 nil
。你可以检查指针是否为 nil
来判断它是否已经被初始化。
示例:零值指针
package mainimport "fmt"func main() {var ptr *int // 默认为 nilfmt.Println("ptr 的值:", ptr) // 输出:ptr 的值: <nil>if ptr == nil {fmt.Println("指针是 nil")}
}
7. 指针和数组、切片
Go 中的数组和切片也可以通过指针来传递,指针可以用来操作数组或切片的数据。
示例:指针与数组
package mainimport "fmt"func modifyArray(arr *[3]int) {arr[0] = 100 // 通过指针修改数组
}func main() {arr := [3]int{1, 2, 3}fmt.Println("修改前数组:", arr) // 输出:修改前数组: [1 2 3]modifyArray(&arr) // 将数组的地址传递给函数fmt.Println("修改后数组:", arr) // 输出:修改后数组: [100 2 3]
}
8. 指针与结构体
指针也可以指向结构体,结构体指针可以通过 ->
语法来访问结构体的字段,或者通过 *
解引用来访问结构体字段。
示例:指针与结构体
package mainimport "fmt"type Person struct {Name stringAge int
}func modifyPerson(p *Person) {p.Name = "Alice"p.Age = 30
}func main() {person := Person{Name: "Bob", Age: 25}fmt.Println("修改前:", person) // 输出:修改前: {Bob 25}modifyPerson(&person) // 将结构体的地址传递给函数fmt.Println("修改后:", person) // 输出:修改后: {Alice 30}
}
9. 指针的高级应用:指针的指针
Go 支持指针的指针,即你可以有一个指向指针的指针。这通常用于函数传递多个级别的地址或动态创建多级引用。
示例:指针的指针
package mainimport "fmt"func main() {var a int = 58var ptr *int = &avar ptr2 **int = &ptr // ptr2 是指向 ptr 的指针fmt.Println("a 的值:", a) // 输出:a 的值: 58fmt.Println("ptr 的值:", *ptr) // 输出:ptr 的值: 58fmt.Println("ptr2 指向的值:", **ptr2) // 输出:ptr2 指向的值: 58
}
10. 总结
- 指针允许你通过内存地址间接访问和修改变量的值。
- 取地址操作符 (
&
) 用于获取变量的内存地址。 - 解引用操作符 (
*
) 用于访问指针指向的变量的值。 - Go 中的 指针默认值为
nil
,检查指针是否为nil
是一个好的编程习惯。 - Go 中的 指针可以与数组、切片、结构体 等一起使用,可以高效地传递大数据结构而无需复制数据。
指针在 Go 中的使用使得函数能直接修改外部变量,而不需要返回修改后的副本,这在处理大数据结构或需要高效内存管理时非常有用。