不積跬步,無以至千里;不積小流,無以成江海。
Go語言中的指針
任何程序數據載入內存後,在內存都有他們的 地址,這就是 指針。而為了保存一個數據在內存中的地址,我們就需要 指針變量。換句話說,指針變量的值是 指針,也就是 內存地址。
Go語言中的指針不能進行偏移和運算,因此Go語言中的指針操作非常簡單,我們只需要記住兩個符號:&(取地址)和 *(根據地址取值)。
指針地址和指針類型
每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。Go語言中使用 & 字符放在變量前面對變量進行“取地址”操作。 Go語言中的值類型(int、float、bool、string、array、struct)都有對應的指針類型,如:*int、*int64、*string等。
取變量指針的語法如下:
ptr := &v // v的類型為T
其中:
- v:代表被取地址的變量,類型為T
- ptr:用於接收地址的變量,ptr的類型就為*T,稱做T的指針類型。*代表指針。
舉例:
<code>func main() { a := 10 b := &a fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078 fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int fmt.Println(&b) // 0xc00000e018 } /<code>
指針取值
在對普通變量使用&操作符取地址後會獲得這個變量的指針,然後可以對指針使用*操作,也就是指針取值,代碼如下。
<code>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) } /<code>
輸出
<code>type of b:*int type of c:int value of c:10 /<code>
總結: 取地址操作符&和取值操作符*是一對互補操作符,&取出地址,*根據地址取出地址指向的值。
變量、指針地址、指針變量、取地址、取值的相互關係和特性如下:
對變量進行取地址(&)操作,可以獲得這個變量的指針變量。 指針變量的值是指針地址。 對指針變量進行取值(*)操作,可以獲得指針變量指向的原變量的值。
指針傳值示例:
<code>func modify1(x int) { x = 100 } func modify2(x *int) { *x = 100 } func main() { a := 10 modify1(a) fmt.Println(a) // 10 modify2(&a) fmt.Println(a) // 100 } /<code>
new和make
Go語言中new和make是內建的兩個函數,主要用來分配內存。
new
new是一個內置的函數,它的函數簽名如下:
func new(Type) *Type
其中,
- Type表示類型,new函數只接受一個參數,這個參數是一個類型
- *Type表示類型指針,new函數返回一個指向該類型內存地址的指針。
使用new函數得到的是一個類型的指針,並且該指針對應的值為該類型的零值。舉個例子:
<code>func main() { a := new(int) b := new(bool) fmt.Printf("%T\n", a) // *int fmt.Printf("%T\n", b) // *bool fmt.Println(*a) // 0 fmt.Println(*b) // false } /<code>
指針作為 引用類型 需要 初始化 後才會擁有內存空間,才可以給它賦值。應該按照如下方式使用內置的new函數進行初始化之後就可以正常對其賦值了:
<code>func main() { var a *int // 創建指針 a = new(int) //分配內存空間 *a = 10 //給指針賦值 fmt.Println(*a) } /<code>
make
make也是用於內存分配的,區別於new,它只用於slice、map以及 chan 的內存創建,而且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型,所以就沒有必要返回他們的指針了。make函數的函數簽名如下:
func make(t Type, size ...IntegerType) Type
make函數是無可替代的,我們在使用 slice、map 以及 channel 的時候,都需要使用make進行初始化,然後才可以對它們進行操作。
new與make的區別
- 二者都是用來做內存分配的。
- make只用於slice、map以及channel的初始化,返回的還是這三個引用類型本身;
- 而new用於類型的內存分配,並且內存對應的值為類型零值,返回的是指向類型的指針。
點關注 不迷路
如果你從本篇內容有收穫,求 點贊,求 關注,求 轉發 ,讓更多的人學習到。
如果本文有任何錯誤,請批評指教,不勝感激