go語言指針常見操作方法
什么是指針?
指針是存儲一個變量的內(nèi)存地址的,聲明一個指針變量的格式如下:
// ptr是指針變量名,*表示是指針類型,*int表示存儲的是一個int類型變量的內(nèi)存地址 var ptr *int
1、關(guān)鍵操作符
| 符號 | 名稱 | 作用 | 示例 |
| & | 取址符 | 獲取變量在內(nèi)存中的地址,返回指針類型 | ptr := &num (獲取 num 的地址) |
| * | 解引用符 | 1. 聲明時:表示指針類型(如 *int) 2. 使用時:獲取或修改指針指向的具體值 | val := *ptr (讀取ptr指向的int變量值) *ptr = 100 (修改ptr指向的int變量值為100) |
2、常見操作
package main
import "fmt"
func main() {
// 1.定義普通變量
num := 100
fmt.Printf("普通變量值: %d, 地址: %p\n", num, &num)
// 2. 聲明并初始化指針
var ptr *int = &num // ptr 存儲的是 num 的內(nèi)存地址
// 3. 解引用:讀取和修改
fmt.Printf("指針指向的值: %d\n", *ptr) // 輸出 100
*ptr = 200 // 通過指針修改原始變量的值
fmt.Printf("修改后原始變量值: %d\n", num) // 輸出 200,證明原值被改變
}3、空指針
當指針變量未初始化時,默認為空指針,nil。
go語言底層將nil視為地址為0的特殊變量。
所以,空指針 ptr == nil 為true,但是在打印ptr指向的內(nèi)存地址時,打印出的是 0x0【就是0】
危險操作:對 nil 指針進行解引用(如 *ptr)會導(dǎo)致程序運行時崩潰(panic: invalid memory address or nil pointer dereference)。
package main
import "fmt"
func main() {
var ptr *int
if ptr == nil {
fmt.Printf("%p", ptr)
}
}4、指針的使用場景
4.1、在函數(shù)間共享數(shù)據(jù)并修改原值
Go 語言默認參數(shù)傳遞是值傳遞(拷貝副本)。如果希望在函數(shù)內(nèi)部修改外部變量的值,必須傳遞指針。
func increment(ptr *int) {
*ptr++ // 修改指針指向的原始值
}
func main() {
count := 10
increment(&count) // 傳入地址
fmt.Println(count) // 輸出 11
}4.2、避免大型數(shù)據(jù)結(jié)構(gòu)的拷貝開銷
對于大型結(jié)構(gòu)體(Struct)或數(shù)組,值傳遞會復(fù)制整個數(shù)據(jù)結(jié)構(gòu),消耗內(nèi)存和 CPU。傳遞指針僅復(fù)制一個地址(64位系統(tǒng)占8字節(jié)),效率極高。
type BigData struct {
Items int
}
// 使用指針接收,避免拷貝 10000 個 int
func process(data *BigData) {
// 處理邏輯
}5、注意事項
1. 不可取地址的情況
你不能對以下對象使用 & 取地址,否則編譯報錯 cannot take the address of ...:
- 字面量/常量:
&42、&"hello"是錯誤的。 - Map 的值:
&m["key"]是錯誤的。因為 Map 的值可能隨時移動或不存在,Go 禁止直接取 Map 值的地址。如果需要,先將值賦給臨時變量再取址。 - 函數(shù)返回值:通常情況下,不能直接對函數(shù)返回值取地址(除非返回的是指針或可尋址變量)。
2. 切片、Map 和 Channel 的特殊性
- 切片(Slice)、Map 和 Channel 在 Go 中本身就是引用類型(底層實現(xiàn)包含指針)。
- 無需傳指針:在函數(shù)間傳遞切片或 Map 時,通常直接傳遞值即可。函數(shù)內(nèi)部對元素內(nèi)容的修改會反映到原變量上。
- 例外:如果你需要在函數(shù)內(nèi)改變切片的長度或容量(例如 append 導(dǎo)致底層數(shù)組重新分配),或者替換整個 Map 對象,則需要傳遞指向切片或 Map 的指針(如
*[]int),但這在日常開發(fā)中較少見。
3. 內(nèi)存逃逸與性能
- 棧與堆:Go 編譯器會自動進行“逃逸分析”。如果局部變量的地址被返回或傳遞給其他 goroutine,該變量會分配到堆上,增加垃圾回收(GC)壓力。
- 適度使用:不要濫用指針。對于小的基本類型(int, bool, small struct),值傳遞往往比指針傳遞更快,因為指針涉及間接尋址和可能的堆分配。
4. 原子指針與 unsafe
sync/atomic.Pointer提供了無鎖的原子指針操作,適用于高并發(fā)場景下的狀態(tài)切換。unsafe.Pointer允許繞過類型系統(tǒng)進行指針轉(zhuǎn)換,極其危險,不參與 GC 生命周期檢查,容易導(dǎo)致懸垂指針或內(nèi)存破壞。除非編寫底層庫或驅(qū)動,否則嚴禁在業(yè)務(wù)代碼中使用。
到此這篇關(guān)于go語言指針常見操作方法的文章就介紹到這了,更多相關(guān)go語言指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

