go 基礎之指針
要搞明白 Go 語言中的指針需要先知道 3 個概念:指針地址、指針類型和指針取值。
go-func-pointer
Go 語言中的指針
Go 語言中的函數傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創建一個指向該變量地址的指針變量。傳遞數據使用指針,而無須拷貝數據。類型指針不能進行偏移和運算。Go 語言中的指針操作非常簡單,只需要記住兩個符號:&
(取地址)和*
(根據地址取值)。
比如下面的代碼:
var a = 3
fmt.Printf("num is : %d, it's location in memory: %p\n", a, &a)
輸出:
num is : 3, it's location in memory: 0xc000062080
可以看到 & a 輸出了 a 的內存地址。
你可以將 & a 賦值給一個變量, 然後觀察這個變量的類型,使用reflect.TypeOf()
方法:
var a = 3
b := &a
fmt.Println(reflect.TypeOf(b))
輸出:
*int
可以看到 & a 的返回類型是 *int。
我們可以將一個變量的內存地址放在一個叫做指針的特殊數據類型中,聲明一個指針的方式如下:
var p *int
然後我們可以使用 p 去指向一個內存地址:
p = &a
那麼我們如何通過指針來獲取對應內存地址的值呢,這也是有辦法的。你可以在指針類型前面加上 * 號(前綴)來獲取指針所指向的內容,這裏的 * 號是一個類型更改器。使用一個指針引用一個值被稱爲間接引用。
func main() {
//指針取值
a := 10
b := &a // 取變量a的地址,將指針保存到b中
fmt.Printf("type of b:%T\n", b)
c := *b // 指針取值(根據指針去內存取值)
fmt.Printf("type of c:%T\n", c)
fmt.Printf("value of c:%v\n", c)
}
輸出如下:
type of b:*int
type of c:int
value of c:10
當一個指針被定義沒有分配任何變量的時候,它的值爲 nil。
指針傳值示例
// 值傳遞x
func modify1(x int) {
x = 100
}
// 指針類型x
func modify2(x *int) {
*x = 100
}
func main() {
a := 10
modify1(a) // 此時的修改不會改變a的值,因爲傳遞的是a的一個副本
fmt.Println(a) // 10
modify2(&a) // 傳遞了a的指針地址,並且接收參數是指針類型,所以會被修改
fmt.Println(a) // 100
}
對於任何一個變量 val,如下表達式都是正確的:
var == *(&var)
有如下你需要注意的是,你不能獲取到一個常量或者一個沒有賦值操作的文字的內存地址:
const PI = 3.14
piP := &PI Cannot take the address of 'PI'
p2 := &3 Cannot take the address of '3'
空指針
-
當一個指針被定義後沒有分配到任何變量時,它的值爲 nil
-
空指針的判斷
package main
import"fmt"
func main() {
var p *string
fmt.Println(p)
fmt.Printf("p的值是%v\n", p)
if p != nil {
fmt.Println("非空")
} else {
fmt.Println("空值")
}
}
總結
-
Go 默認使用按值傳遞來傳遞參數,也就是傳遞參數的副本。當我們想要修改某個變量的時候,我們可以創建一個指向該變量地址的指針變量。傳遞數據使用指針,而無須拷貝數據。類型指針不能進行偏移和運算。Go 語言中的指針操作非常簡單,只需要記住兩個符號:(
&
)(取地址)和(*
)(根據地址取值) -
在對普通變量使用(
&
)操作符取地址後會獲得這個變量的指針,然後可以對指針使用(*
)操作,也就是指針取值。取地址操作符 & 和取值操作符*
是一對互補操作符,&
取出地址,*
根據地址取出地址指向的值。 -
對變量進行取地址(
&
)操作,可以獲得這個變量的指針變量。 -
指針變量的值是指針地址。
-
對指針變量進行取值(
*
)操作,可以獲得指針變量指向的原變量的值。
references
- https://www.topgoer.com/go%E5%9F%BA%E7%A1%80/%E6%8C%87%E9%92%88.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/GjoQySRwN64rMAmLH2RRzg