1. 需要修改传入函数的参数值
如果需要在函数内修改传入参数的值并希望这些修改在函数外生效,可以使用指针。
func updateValue(val *int) {
*val = 42
}
func main() {
num := 10
updateValue(&num)
fmt.Println(num) // 输出 42
}
2. 避免值拷贝,提升性能
对于大型结构体,将其作为参数传递时,如果不使用指针,会创建整个结构体的副本,这样会消耗更多内存和 CPU 时间。通过使用指针,可以只传递一个引用,避免拷贝。
type BigStruct struct {
Data [100000]int
}
func processBigStruct(bs *BigStruct) {
bs.Data[0] = 1
}
func main() {
var bigData BigStruct
processBigStruct(&bigData)
}
3. 动态分配内存
使用指针可以直接创建动态分配的变量,而不是固定的局部变量。
func createPointer() *int {
p := new(int) // 动态分配一个 int 类型的指针
*p = 100
return p
}
func main() {
ptr := createPointer()
fmt.Println(*ptr) // 输出 100
}
4. 需要与 nil 值作比较
当某些值可能不存在时,可以使用指针将其设置为 nil,这通常用于树、链表等数据结构中。
type Node struct {
Value int
Next *Node
}
func main() {
var head *Node = nil // 空链表
if head == nil {
fmt.Println("链表为空")
}
}
5. 需要共享或引用数据
当多个函数或 goroutine 需要共享同一份数据时,可以使用指针,确保修改同步。
func addOne(val *int) {
*val += 1
}
func main() {
shared := 5
addOne(&shared)
fmt.Println(shared) // 输出 6
}
6. 需要实现某些特定接口
有些接口方法的接收者必须是指针类型,尤其是当方法需要修改接收者的字段时。
type Counter struct {
Count int
}
func (c *Counter) Increment() {
c.Count++
}
func main() {
c := Counter{}
c.Increment()
fmt.Println(c.Count) // 输出 1
}
总结
- 修改数据:当函数需要直接修改变量值时。
- 避免拷贝:对于大型结构体或数组,避免性能损耗。
- 动态内存分配:需要在堆上分配内存时。
- 引用共享数据:多个地方需要共享同一个变量。
- nil 表示状态:需要表示值的缺失状态。
- 实现接口:需要为方法绑定指针接收者。
但也要注意,指针的滥用可能导致代码复杂度增加和潜在的空指针错误(nil 引用问题),因此需要在合理场景下使用指针。



