網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
今天來(lái)說(shuō)說(shuō) Go 語(yǔ)言基礎(chǔ)中的指針。
Go 語(yǔ)言中指針是很容易學(xué)習(xí)的,Go 語(yǔ)言中使用指針可以更簡(jiǎn)單的執(zhí)行一些任務(wù)。
1. 什么是指針
Go 語(yǔ)言中,一個(gè)指針變量指向了一個(gè)值的內(nèi)存地址。和 C、C++ 中的指針不同,Go 語(yǔ)言中的指針不能進(jìn)行計(jì)算和偏移操作。
Go 語(yǔ)言中的函數(shù)傳參都是值拷貝,當(dāng)我們想要修改某個(gè)變量的時(shí)候,我們可以創(chuàng)建一個(gè)指向該變量地址的指針變量。傳遞數(shù)據(jù)使用指針,而無(wú)須拷貝數(shù)據(jù)。
Go 語(yǔ)言中的指針操作非常簡(jiǎn)單,只有記住兩個(gè)符號(hào)就可以了。
- &(取地址)
- *(根據(jù)地址取值)
var ip *int /* 指向整型*/
畫(huà)個(gè)重點(diǎn),我們想徹底搞明白指針,必須要掌握 3 個(gè)概念:
- 指針地址
- 指針類(lèi)型
- 指針取值
接下來(lái)我們從這 3 點(diǎn)大家闡述 Go 語(yǔ)言指針,方便大家掌握。
2. 指針地址 & 指針類(lèi)型
Go 語(yǔ)言變量在運(yùn)行時(shí)都會(huì)被指定一個(gè)內(nèi)存地址,即變量在內(nèi)存中的位置。Go 語(yǔ)言通常在使用時(shí)會(huì)在變量前放一個(gè)?&
?代表對(duì)變量進(jìn)行 “ 取地址 ” 操作。Go 語(yǔ)言常用的值類(lèi)型 (string、int、array、struct、float、bool )都會(huì)有對(duì)應(yīng)的指針類(lèi)型。如:string、?int、*int64 等。
每個(gè)變量在運(yùn)行時(shí)都擁有一個(gè)地址,這個(gè)地址代表變量在內(nèi)存中的位置。Go語(yǔ)言中使用&字符放在變量前面對(duì)變量進(jìn)行“取地址”操作。 Go語(yǔ)言中的值類(lèi)型(int、float、bool、string、array、struct)都有對(duì)應(yīng)的指針類(lèi)型,如:int、int64、*string等。
取變量指針的語(yǔ)法如下:
package main import "fmt" func main(){ a := 10 /* 聲明實(shí)際變量 */ ip := &a /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("a 變量的地址是: %x\n", &a ) /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("ip 變量?jī)?chǔ)存的指針地址: %x\n", ip ) /* 使用指針訪問(wèn)值 */ fmt.Printf("*ip 變量的值: %d\n", *ip ) }
運(yùn)行結(jié)果:
a 變量的地址是: 0xc000010200
ip 變量?jī)?chǔ)存的指針地址: 0xc000010200
*ip 變量的值: 10
其中:
- a: 代表被取地址的變量,類(lèi)型為 int
- ip: 用于接收地址的變量,
ip
?的類(lèi)型就為 *int,稱(chēng)做?int
?的指針類(lèi)型。*
代表指針。
用圖來(lái)表示一下?ip := &a
:
以上就是指針地址和指針類(lèi)型。
3. 指針取值
對(duì)變量使用?&
會(huì)獲取該變量的指針,對(duì)指針使用?*
?會(huì)獲取到值,也就是 “指正取值”。舉個(gè)例子更好的理解一下:
package main import "fmt" func main() { a := 20 /* 聲明實(shí)際變量 */ b := &a /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("type of b:%T\n", &a ) c := *b // 指針取值(根據(jù)指針去內(nèi)存取值) fmt.Printf("type of c:%T\n", c) fmt.Printf("value of c:%v\n", c) }
控制臺(tái)輸出結(jié)果:
type of b:*int
type of c:int
value of c:10
小結(jié)一下:
- 指針變量的值是指針地址 (可以結(jié)合上圖更好的理解)
- 對(duì)變量進(jìn)行取地址?
&
操作,可以獲得這個(gè)變量的指針變量 - 對(duì)指針變量進(jìn)行取值?
*
操作,可以獲得指針變量指向的原變量的值
函數(shù)傳值:
package main import "fmt" func main() { x := 2 mod1(x) fmt.Println(x) // 2 mod2(&x) fmt.Println(x) // 1024 } func mod1(x int) { x = 1024 } func mod2(x *int) { *x = 1024 }
4. 空指針
當(dāng)一個(gè)指針被定義后沒(méi)有分配到任何變量時(shí),它的值為?nil
。
nil
?指針也稱(chēng)為空指針。
nil
在概念上和其它語(yǔ)言的?null、None、nil、NULL
一樣,都指代零值或空值。
一個(gè)指針變量通常縮寫(xiě)為?ptr
。
舉個(gè)例子:
package main import "fmt" func main() { var ptr *int fmt.Printf("ptr 的值為 : %x\n", ptr) // ptr 的值為 : 0 }
空指針判斷:
package main import "fmt" func main() { var ptr *string fmt.Println(ptr) fmt.Printf("ptr的值是%v\n", ptr) if ptr != nil { fmt.Println("非空") } if ptr == nil { fmt.Println("空值") } }
5. make
make
?是用于初始化內(nèi)置的數(shù)據(jù)結(jié)構(gòu),比如?slice
、map
?和?channel
。
func make(t Type, size ...IntegerType) Type
舉個(gè)例子:
package main import "fmt" func main() { var user map[string]int user = make(map[string]int, 10) user["age"] = 18 fmt.Println(user) /** slice := make([]int, 0, 100) hash := make(map[int]bool, 10) ch := make(chan int, 5) **/ }
6. new
new
?的作用是根據(jù)傳入的類(lèi)型分配一片內(nèi)存空間并返回指向這片內(nèi)存空間的指針。
func new(Type) *Type
解釋一下:
- Type 表示類(lèi)型,new 函數(shù)只接受一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)類(lèi)型
- *Type 表示類(lèi)型指針,new 函數(shù)返回一個(gè)指向該類(lèi)型內(nèi)存地址的指針
舉個(gè)例子:
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 }
7. make 和 new 的區(qū)別
面試高頻題,這個(gè)要考,記一下。
- make 和 new 都是用來(lái)做內(nèi)存分配
- make 只用于 slice、map 、channel 的初始化,返回的還是這三個(gè)引用類(lèi)型本身,因?yàn)檫@三種類(lèi)型就是引用類(lèi)型,所以就沒(méi)必要返回其指針了
- new 用于類(lèi)型的內(nèi)存分配,并且內(nèi)存對(duì)應(yīng)的值為類(lèi)型零值,返回的是指向類(lèi)型的指針。
8. 問(wèn)題
Q:?執(zhí)行下面的代碼會(huì)出現(xiàn)啥問(wèn)題?
package main import "fmt" func main() { var a *int *a = 100 fmt.Println(*a) var user map[string]int user["age"] = 18 fmt.Println(user) }
A:?會(huì)出現(xiàn)?panic runtime error: invalid memory address or nil pointer dereference
。出錯(cuò)行數(shù)在第 7 行。
原因:在 Go 語(yǔ)言中我們使用引用類(lèi)型的變量需要先申明、分配內(nèi)存空間,否則在賦值是會(huì)出錯(cuò)。值類(lèi)型的變量除外,因?yàn)槠湓谏昝鲿r(shí)就分配了默認(rèn)的內(nèi)存空間。這也是 new 和 make 的作用。
原文鏈接:https://segmentfault.com/a/1190000043187142
相關(guān)推薦
- 2022-08-26 Python?Pandas中l(wèi)oc和iloc函數(shù)的基本用法示例_python
- 2022-04-28 WPF使用Grid網(wǎng)格面板布局_實(shí)用技巧
- 2022-03-31 C語(yǔ)言實(shí)現(xiàn)任意進(jìn)制轉(zhuǎn)換器_C 語(yǔ)言
- 2022-07-06 關(guān)于Pandas?count()與values_count()的用法及區(qū)別_python
- 2023-03-28 Pytorch實(shí)現(xiàn)將label變成one?hot編碼的兩種方式_python
- 2022-07-01 Oracle數(shù)據(jù)庫(kù)用戶(hù)密碼過(guò)期的解決方法_oracle
- 2022-11-16 Android?十六進(jìn)制狀態(tài)管理實(shí)例詳解_Android
- 2022-01-04 微信小程序內(nèi)部A頁(yè)面向內(nèi)嵌H5頁(yè)面跳轉(zhuǎn),并且傳參
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支