網(wǎng)站首頁 編程語言 正文
1. 指針
區(qū)別于C/C++
中的指針,Go
語言中的指針不能進行偏移和運算,是安全指針。
要搞明白Go
語言中的指針需要先知道3個概念:指針地址、指針類型和指針取值。
Go
語言中的函數(shù)傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創(chuàng)建一個指向該變量地址的指針變量。
傳遞數(shù)據(jù)使用指針,而無須拷貝數(shù)據(jù)。類型指針不能進行偏移和運算。
Go
語言中的指針操作非常簡單,只需要記住兩個符號:&(取地址)和*(根據(jù)地址取值)。
1.1 指針地址和指針類型
每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。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 }
1.2 指針取值
在對普通變量使用&
操作符取地址后會獲得這個變量的指針,然后可以對指針使用*
操作,也就是指針取值。
package?main import?"fmt" func?main()?{ ????//指針取值 ????a?:=?10 ????b?:=?&a?//?取變量a的地址,將指針保存到b中 ????fmt.Printf("type?of?b:?%T\n",?b) ????c?:=?*b?//?指針取值(根據(jù)指針去內存取值) ????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
取地址操作符&
和取值操作符*
是一對互補操作符,&
取出地址,*
根據(jù)地址取出地址指向的值。
變量、指針地址、指針變量、取地址、取值的相互關系和特性如下:
- 對變量進行取地址(
&
)操作,可以獲得這個變量的指針變量。 - 指針變量的值是指針地址。
- 對指針變量進行取值(
*
)操作,可以獲得指針變量指向的原變量的值。
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 }
1.3 空指針
- 當一個指針被定義后沒有分配到任何變量時,它的值為?
nil
- 空指針的判斷
package?main import?"fmt" func?main()?{ ????var?p?*string ????fmt.Printf("p的值是%v?\n",?p) ????if?p?!=?nil?{ ????????fmt.Println("非空指針") ????}?else?{ ????????fmt.Println("空指針") ????} }
1.4 new 的使用
new
是一個內置的函數(shù),它的函數(shù)簽名如下:
func?new(Type)?*Type
其中:
-
Type
表示類型,new
函數(shù)只接受一個參數(shù),這個參數(shù)是一個類型 -
*Type
表示類型指針,new
函數(shù)返回一個指向該類型內存地址的指針。
new
函數(shù)不太常用,使用new
函數(shù)得到的是一個類型的指針,并且該指針對應的值為該類型的零值。
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
函數(shù)對a
進行初始化之后就可以正常對其賦值了:
func?main()?{ ????var?a?*int ????a?=?new(int) ????*a?=?10 ????fmt.Println(*a) }
make
也是用于內存分配的,區(qū)別于new
,它只用于slice
、map
以及chan
的內存創(chuàng)建,而且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型,所以就沒有必要返回他們的指針了。
1.5 new與make的區(qū)別
- 二者都是用來做內存分配的。
-
make
只用于slice
、map
以及channel
的初始化,返回的還是這三個引用類型本身; - 而
new
用于類型的內存分配,并且內存對應的值為類型零值,返回的是指向類型的指針。
2. Map
map
是一種無序的基于key-value的數(shù)據(jù)結構,Go語言中的map是引用類型,必須初始化才能使用。
2.1 什么是Map
key,value存儲
最通俗的話說:Map
是一種通過key
來獲取value
的一個數(shù)據(jù)結構,其底層存儲方式為數(shù)組,在存儲時key
不能重復,當key
重復時,value
進行覆蓋,我們通過key
進行hash
運算(可以簡單理解為把key
轉化為一個整形數(shù)字)然后對數(shù)組的長度取余,得到key
存儲在數(shù)組的哪個下標位置,最后將key
和value
組裝為一個結構體,放入數(shù)組下標處。
hash沖突
數(shù)組一個下標處只能存儲一個元素,也就是說一個數(shù)組下標只能存儲一對key
,value
,?hashkey(xiaoming)=4
占用了下標0的位置,假設我們遇到另一個key
,hashkey(xiaowang)
也是4
,這就是hash
沖突(不同的key
經(jīng)過hash
之后得到的值一樣),那么key=xiaowang
的怎么存儲?
hash沖突的常見解決方法
-
開放定址法:?也就是說當我們存儲一個
key
,value
時,發(fā)現(xiàn)hashkey(key)
的下標已經(jīng)被別key
占用,那我們在這個數(shù)組中空間中重新找一個沒被占用的存儲這個沖突的key
,那么沒被占用的有很多,找哪個好呢?常見的有:線性探測法,線性補償探測法,隨機探測法,這里以線性探測為對比。 -
拉鏈法:?何為拉鏈,簡單理解為鏈表,當
key
的hash
沖突時,我們在沖突位置的元素上形成一個鏈表,通過指針互連接,當查找時,發(fā)現(xiàn)key
沖突,順著鏈表一直往下找,直到鏈表的尾節(jié)點,找不到則返回空。
開放定址(線性探測)和拉鏈的優(yōu)缺點
- 拉鏈法比線性探測處理簡單
- 線性探測查找是會被拉鏈法會更消耗時間
- 線性探測會更加容易導致擴容,而拉鏈不會
- 拉鏈存儲了指針,所以空間上會比線性探測占用多一點
- 拉鏈是動態(tài)申請存儲空間的,所以更適合鏈長不確定的
2.2 Map 定義
Go
語言中?Map
的定義語法如下:
map[KeyType]ValueType
其中:
-
KeyType
: 表示鍵的類型。 -
ValueType
: 表示鍵對應的值的類型。
map
類型的變量默認初始值為nil
,需要使用make()
函數(shù)來分配內存。語法為:
?make(map[KeyType]ValueType,?[cap])
其中cap
表示map
的容量,該參數(shù)雖然不是必須的,但是我們應該在初始化map
的時候就為其指定一個合適的容量。
2.3 map基本使用
map
中的數(shù)據(jù)都是成對出現(xiàn)的,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) }
2.4 map的遍歷
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
時的元素順序與添加鍵值對的順序無關。
2.5 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("查無此人") ????} }
2.6 map使用delete()函數(shù)刪除鍵值對
使用delete()
內建函數(shù)從map
中刪除一組鍵值對,?delete()
函數(shù)的格式如下:
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) ????} }
原文鏈接:https://mdnice.com/writing/b286e12c8f7141f8ac42dee05410b662
相關推薦
- 2023-05-06 React組件渲染后對DOM的操作方式_React
- 2022-05-24 Pytho的HTTP交互httpx包模塊使用詳解_python
- 2024-03-24 MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用
- 2024-03-02 【JQuery】Ajax 參數(shù)為數(shù)組 的方法
- 2022-06-17 C#關鍵字in、out、ref的作用與區(qū)別_C#教程
- 2023-04-07 C語言高級教程之變長數(shù)組詳解_C 語言
- 2021-12-15 liunx安裝Jenkins超詳細全過程_Linux
- 2023-04-07 C#中括號強轉、as、is區(qū)別詳解_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支