您好,登錄后才能下訂單哦!
本文以Golang中的指針為例,為大家分析Golang中的指針地址和指針類型以及取值的使用方法。閱讀完整文希望大家對Golang中的指針有一定的認識。
任何數據載入內存后,在內存中都有對應的地址,這就是指針。
為了保存一個數據在內存中的地址,需要指針變量。
比如"好好學習,天天向上"這個字符串寫入程序中,程序一啟動這句話就加載到內存(假設內存地址為0x123456),在程序中,把該字符串賦值給變量A,把該字符串的內存地址賦值給變量B。
這時變量B就是一個指針變量。通過變量A和變量B都能找到該字符串。
Go語言中的指針不能進行偏移和運算,因此Go語言中的指針操作非常簡單,只需要記住兩個符號:&(取地址)和*(根據地址取值)。
也需要記得:
值類型有:int、float、bool、string、array、struct
引用類型有:指針,map,切片,chan
每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。
Go語言中使用&字符放在變量前面對變量進行“取地址”操作。
Go語言中的值類型(int,float,bool,string,array,struct)都有對應的指針類型,如*int,*in64,*string等。
取變量指針的語法如下:
ptr := &v // v的類型為T
其中:
v:代表被取地址的變量,類型為T
ptr:用于接收地址的變量,ptr的類型就是*T,稱作T的指針類型。*代表指針。
package main
import "fmt"
func main() {
a:=10
b:=&a
fmt.Printf("a:%d ptr:%p\n",a,&a)
fmt.Printf("b:%p type:%T\n",b,b)
fmt.Println(&b)
}
結果:
a:10 ptr:0xc000054080
b:0xc000054080 type:*int
0xc000080018
Process finished with exit code 0
在對普通變量使用&操作符取地址后,會獲得這個變量的指針,然后可以對指針使用*操作,即指針取值。
package main
import "fmt"
func main() {
a:=10
b:=&a
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
Process finished with exit code 0
總結:
取地址操作符&和取值操作符*是一對互補操作符,&取出地址,*根據地址取出地址指向的值。
變量、指針地址、指針變量、取地址、取值的相互關系和特性如下:
1.對變量進行取地址(&)操作,可以獲取這個變量的指針變量。
2.指針變量的值是指針地址。
3.對指針變量進行取值(*)操作,可以獲得指針變量指向的原變量的值。
package main
import "fmt"
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
}
先看一個例子:
func main() {
var a *int
*a = 100
fmt.Println(*a)
var b map[string]int
b["沙河娜扎"] = 100
fmt.Println(b)
}
結果:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x494aaa]
goroutine 1 [running]:
main.main()
C:/Users/Administrator/Desktop/go/src/myproject1/test.go:7 +0x2a
Process finished with exit code 2
上面的代碼引發了panic,在Go語言中,對于引用類型的變量,我們在使用的時候不僅要聲明它,還要為它分配內存空間,否則我們值就沒辦法存儲。
對于值類型的聲明,不需要分配內存空間,因為在聲明的時候,已經默認分配好了內存空間。
要分配內存,就引出了new和make,Go語言中使用new和make來分配內存。
new是一個內置函數,它的函數簽名如下:
func new(Type) *Type
其中,
Type表示類型,new函數只接收一個參數,這個參數是一個類型。
*Type表示指針類型,new函數返回一個指向該類型內存地址的指針。
new函數不太常用,使用new函數得到的是一個類型的指針,并且該指針對應的值為該類型的零值。
package main
import "fmt"
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
}
本節開始的示例代碼中,var a *int只是聲明了一個指針變量a,但是沒有初始化,指針作為引用類型,需要初始化后才能擁有內存空間,才能給它賦值。
應該按照如下方式,使用內置的new函數對a進行初始化后才可以正常進行賦值。
func main() {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)
}
make也是用于內存分配的,與new相比,make只用于slice、map及chan的內存創建,而且它的返回類型就是三個類型本身,不是他們的指針類型,
因為這三種類型就是引用類型,所以沒必要返回指針了。
make函數的函數簽名如下: func make(t Type, size ...IntegerType) Typ make函數是無可替代的,我們在使用slice、map、及channel的時候,都要使用make進行初始化,然后才可以對它們進行操作。channel我們稍后講解。 本節開始的實例中var b map[string]int只是聲明變量b是一個map類型的變量,需要像下面的示例代碼一樣使用make函數進行初始化操作后,才能對其進行鍵值對賦值。 func main() { var b map[string]int b = make(map[string]int, 10) b["沙河娜扎"] = 100 fmt.Println(b) }
new與make的區別
1.兩者都是用來做內存分配的。
2.make只用于slice、map及channel的初始化,返回的還是三中類型本身。
3.new用于類型的內存分配,并且內存對應的值為類型零值,返回的是指向類型的指針。
看完上述內容,你們對Golang中的指針有進一步的了解嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。