您好,登錄后才能下訂單哦!
這篇文章主要介紹“Go語言的指針Map如何使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Go語言的指針Map如何使用”文章能幫助大家解決問題。
區別于C/C++
中的指針,Go
語言中的指針不能進行偏移和運算,是安全指針。
要搞明白Go
語言中的指針需要先知道3個概念:指針地址、指針類型和指針取值。
Go
語言中的函數傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創建一個指向該變量地址的指針變量。
傳遞數據使用指針,而無須拷貝數據。類型指針不能進行偏移和運算。
Go
語言中的指針操作非常簡單,只需要記住兩個符號:&(取地址)和*(根據地址取值)。
每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。Go
語言中使用&
字符放在變量前面對變量進行“取地址”操作。
Go
語言中的值類型(int
、float
、bool
、string
、array
、struct
)都有對應的指針類型,如:*int
、*int64
、*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) // a:10 ptr:0xc00001a078 fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int fmt.Println(&b) // 0xc00000e018 }
在對普通變量使用&
操作符取地址后會獲得這個變量的指針,然后可以對指針使用*
操作,也就是指針取值。
package main import "fmt" 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
取地址操作符&
和取值操作符*
是一對互補操作符,&
取出地址,*
根據地址取出地址指向的值。
變量、指針地址、指針變量、取地址、取值的相互關系和特性如下:
對變量進行取地址(&
)操作,可以獲得這個變量的指針變量。
指針變量的值是指針地址。
對指針變量進行取值(*
)操作,可以獲得指針變量指向的原變量的值。
package main import "fmt" func p1(n int) { n = 100 } func p2(n *int) { *n = 100 } func main() { a := 10 p1(a) fmt.Println(a) // 10 p2(&a) fmt.Println(a) // 100 }
當一個指針被定義后沒有分配到任何變量時,它的值為 nil
空指針的判斷
package main import "fmt" func main() { var p *string fmt.Printf("p的值是%v \n", p) if p != nil { fmt.Println("非空指針") } else { fmt.Println("空指針") } }
new
是一個內置的函數,它的函數簽名如下:
func new(Type) *Type
其中:
Type
表示類型,new
函數只接受一個參數,這個參數是一個類型
*Type
表示類型指針,new
函數返回一個指向該類型內存地址的指針。
new
函數不太常用,使用new
函數得到的是一個類型的指針,并且該指針對應的值為該類型的零值。
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
,它只用于slice
、map
以及chan
的內存創建,而且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型,所以就沒有必要返回他們的指針了。
二者都是用來做內存分配的。
make
只用于slice
、map
以及channel
的初始化,返回的還是這三個引用類型本身;
而new
用于類型的內存分配,并且內存對應的值為類型零值,返回的是指向類型的指針。
map
是一種無序的基于key-value的數據結構,Go語言中的map是引用類型,必須初始化才能使用。
最通俗的話說:Map
是一種通過key
來獲取value
的一個數據結構,其底層存儲方式為數組,在存儲時key
不能重復,當key
重復時,value
進行覆蓋,我們通過key
進行hash
運算(可以簡單理解為把key
轉化為一個整形數字)然后對數組的長度取余,得到key
存儲在數組的哪個下標位置,最后將key
和value
組裝為一個結構體,放入數組下標處。
數組一個下標處只能存儲一個元素,也就是說一個數組下標只能存儲一對key
,value
, hashkey(xiaoming)=4
占用了下標0的位置,假設我們遇到另一個key
,hashkey(xiaowang)
也是4
,這就是hash
沖突(不同的key
經過hash
之后得到的值一樣),那么key=xiaowang
的怎么存儲?
開放定址法: 也就是說當我們存儲一個key
,value
時,發現hashkey(key)
的下標已經被別key
占用,那我們在這個數組中空間中重新找一個沒被占用的存儲這個沖突的key
,那么沒被占用的有很多,找哪個好呢?常見的有:線性探測法,線性補償探測法,隨機探測法,這里以線性探測為對比。
拉鏈法: 何為拉鏈,簡單理解為鏈表,當key
的hash
沖突時,我們在沖突位置的元素上形成一個鏈表,通過指針互連接,當查找時,發現key
沖突,順著鏈表一直往下找,直到鏈表的尾節點,找不到則返回空。
拉鏈法比線性探測處理簡單
線性探測查找是會被拉鏈法會更消耗時間
線性探測會更加容易導致擴容,而拉鏈不會
拉鏈存儲了指針,所以空間上會比線性探測占用多一點
拉鏈是動態申請存儲空間的,所以更適合鏈長不確定的
Go
語言中 Map
的定義語法如下:
map[KeyType]ValueType
其中:
KeyType
: 表示鍵的類型。
ValueType
: 表示鍵對應的值的類型。
map
類型的變量默認初始值為nil
,需要使用make()
函數來分配內存。語法為:
make(map[KeyType]ValueType, [cap])
其中cap
表示map
的容量,該參數雖然不是必須的,但是我們應該在初始化map
的時候就為其指定一個合適的容量。
map
中的數據都是成對出現的,map
的基本使用如下:
func main() { scoreMap := make(map[string]int, 8) scoreMap["張三"] = 90 scoreMap["李四"] = 100 fmt.Println(scoreMap) fmt.Println(scoreMap["李四"]) fmt.Printf("type of a: %T\n", scoreMap) }
輸出結果:
map[李四:100 張三:90]
100
type of a: map[string]int
map
也支持在聲明的時候填充元素:
func main() { userInfo := map[string]string{ "username": "admin", "password": "123456", } fmt.Println(userInfo) }
Go
語言中使用for range
遍歷map
:
func main() { scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["李四"] = 100 scoreMap["王五"] = 60 for k, v := range scoreMap { fmt.Println(k, v) } }
如果只想遍歷key
的時候,可以按下面的寫法:
func main() { scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["李四"] = 100 scoreMap["王五"] = 60 for k := range scoreMap { fmt.Println(k) } }
注意: 遍歷map
時的元素順序與添加鍵值對的順序無關。
Go
語言中有個判斷map
中鍵是否存在的特殊寫法,格式如下:
value, ok := map[key]
如果key
存在ok
為true
,value
為對應的值;不存在ok
為false
,value
為值類型的零值
func main() { scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["李四"] = 100 // 如果key存在ok為true,value為對應的值;不存在ok為false,value為值類型的零值 value, ok := scoreMap["張三"] if ok { fmt.Println(v) } else { fmt.Println("查無此人") } }
使用delete()
內建函數從map
中刪除一組鍵值對, delete()
函數的格式如下:
delete(map, key)
其中:
map
: 表示要刪除鍵值對的map
key
: 表示要刪除的鍵值對的鍵
func main(){ scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["李四"] = 100 scoreMap["王五"] = 60 delete(scoreMap, "李四")//將李四: 100從 map 中刪除 for k,v := range scoreMap{ fmt.Println(k, v) } }
關于“Go語言的指針Map如何使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。