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 中的使用使得函數能直接修改外部變量,而不需要返回修改后的副本,這在處理大數據結構或需要高效內存管理時非常有用。