
在go语言中,指针是一个核心概念,它允许程序直接操作内存地址,从而实现更灵活的数据管理和高效的程序设计。理解*(星号)和&(取地址符)这两个操作符是掌握go语言指针的关键。
& 操作符用于获取一个变量的内存地址。当应用于一个变量时,它会返回该变量在内存中的地址,这个地址就是一个指向该变量类型的新指针。
语法: &variable
示例:
package main
import "fmt"
func main() {
value := 100
ptr := &value // ptr 现在是一个指向 value 变量的指针
fmt.Printf("变量 value 的值:%d\n", value)
fmt.Printf("变量 value 的内存地址:%p\n", ptr) // %p 用于打印指针地址
}在上述示例中,ptr 变量存储的不是 100 这个值,而是 value 变量在内存中的具体位置。
立即学习“go语言免费学习笔记(深入)”;
* 操作符在Go语言中扮演了多重角色,其具体含义取决于它出现的位置。
当 * 紧跟在一个类型前面时(例如 *int, *string),它表示声明一个指向该类型数据的指针。这意味着这个变量将存储一个内存地址,而这个地址指向的是指定类型的数据。
语法: var variableName *Type
示例:
package main
import "fmt"
func main() {
var p *int // 声明 p 是一个指向 int 类型数据的指针
fmt.Printf("p 的零值(未初始化):%v\n", p) // 指针的零值是 nil
}当 * 放置在一个已声明的指针变量前面时,它被称为解引用操作符。解引用操作用于访问或获取指针所指向的内存地址中存储的实际值。
语法: *pointerVariable
示例:
package main
import "fmt"
func main() {
value := 200
ptr := &value // ptr 指向 value 的地址
fmt.Printf("通过 ptr 解引用获取 value 的值:%d\n", *ptr) // *ptr 获取 ptr 指向的值
}通过解引用操作符,我们不仅可以读取指针指向的值,还可以修改该值。当 *pointerVariable 出现在赋值语句的左侧时,它表示修改指针所指向内存地址中的值。
语法: *pointerVariable = newValue
示例:
package main
import "fmt"
func main() {
num := 300
ptr := &num // ptr 指向 num 的地址
fmt.Printf("修改前 num 的值:%d\n", num)
*ptr = 400 // 通过 ptr 间接修改 num 的值
fmt.Printf("修改后 num 的值:%d\n", num)
}为了更深入地理解 & 和 * 的协同工作,我们来分析一个典型的代码片段:
package main
import (
"fmt"
"os"
)
func main() {
s := "hello" // 声明并初始化字符串变量 s
if s[1] != 'e' { // 检查字符串 s 的第二个字符是否为 'e'
os.Exit(1) // 如果不是,则退出程序
}
fmt.Printf("s 初始值: %s, 地址: %p\n", s, &s)
s = "good bye" // 重新赋值 s
fmt.Printf("s 重新赋值后: %s, 地址: %p\n", s, &s)
var p *string = &s // 声明一个字符串指针 p,并用 s 的地址初始化它
fmt.Printf("指针 p 的值 (s 的地址): %p\n", p)
fmt.Printf("通过指针 p 解引用得到的值: %s\n", *p)
*p = "ciao" // 通过指针 p 间接修改 s 的值
fmt.Printf("通过指针 p 修改后 s 的值: %s\n", s)
fmt.Printf("通过指针 p 修改后,通过 p 解引用得到的值: %s\n", *p)
}分析过程:
运行此代码,您会观察到 s 的值最终变为 "ciao",这证明了通过指针可以实现对原始变量的间接修改。
Go语言中所有函数参数的传递都是值传递(pass by value)。这意味着当您将一个变量作为参数传递给函数时,函数会接收到该变量的一个副本。对副本的任何修改都不会影响原始变量。
然而,当您传递一个指针的值时,函数接收到的是原始变量的内存地址的副本。虽然这个地址本身是一个副本,但它指向的仍然是原始变量在内存中的位置。因此,通过这个指针副本解引用并修改其指向的值,就能够影响到原始变量。这在效果上类似于其他语言中的“引用传递”,但本质上仍是值传递——只是传递的是一个地址值。
package main
import "fmt"
func modifyValue(x int) { // 值传递,x 是 num 的副本
x = 20
}
func modifyValueByPointer(ptr *int) { // 值传递,ptr 是 &num 的副本
*ptr = 20 // 通过指针修改 num
}
func main() {
num := 10
fmt.Println("初始值:", num) // 10
modifyValue(num)
fmt.Println("值传递后:", num) // 10 (未改变)
modifyValueByPointer(&num)
fmt.Println("指针传递后:", num) // 20 (已改变)
}& 和 * 是Go语言中操作指针的两个基本且强大的操作符。& 用于获取变量的内存地址,生成一个指针;而 * 则用于声明指针类型、解引用指针以访问其指向的值,以及通过指针间接修改变量的值。理解并熟练运用它们,是编写高效、安全Go程序的基础。掌握指针不仅能让您更深入地理解Go的内存模型,也能帮助您在特定场景下优化程序性能和实现复杂的数据结构。
以上就是Go语言中指针操作符*与取地址符&的全面解析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号