Go語言基礎學習之指針詳解
今天來說說 Go 語言基礎中的指針。
Go 語言中指針是很容易學習的,Go 語言中使用指針可以更簡單的執(zhí)行一些任務。
1. 什么是指針
Go 語言中,一個指針變量指向了一個值的內(nèi)存地址。和 C、C++ 中的指針不同,Go 語言中的指針不能進行計算和偏移操作。
Go 語言中的函數(shù)傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創(chuàng)建一個指向該變量地址的指針變量。傳遞數(shù)據(jù)使用指針,而無須拷貝數(shù)據(jù)。
Go 語言中的指針操作非常簡單,只有記住兩個符號就可以了。
- &(取地址)
- *(根據(jù)地址取值)
var ip *int /* 指向整型*/
畫個重點,我們想徹底搞明白指針,必須要掌握 3 個概念:
- 指針地址
- 指針類型
- 指針取值
接下來我們從這 3 點大家闡述 Go 語言指針,方便大家掌握。
2. 指針地址 & 指針類型
Go 語言變量在運行時都會被指定一個內(nèi)存地址,即變量在內(nèi)存中的位置。Go 語言通常在使用時會在變量前放一個 &
代表對變量進行 “ 取地址 ” 操作。Go 語言常用的值類型 (string、int、array、struct、float、bool )都會有對應的指針類型。如:string、 int、*int64 等。
每個變量在運行時都擁有一個地址,這個地址代表變量在內(nèi)存中的位置。Go語言中使用&字符放在變量前面對變量進行“取地址”操作。 Go語言中的值類型(int、float、bool、string、array、struct)都有對應的指針類型,如:int、int64、*string等。
取變量指針的語法如下:
package main import "fmt" func main(){ a := 10 /* 聲明實際變量 */ ip := &a /* 指針變量的存儲地址 */ fmt.Printf("a 變量的地址是: %x\n", &a ) /* 指針變量的存儲地址 */ fmt.Printf("ip 變量儲存的指針地址: %x\n", ip ) /* 使用指針訪問值 */ fmt.Printf("*ip 變量的值: %d\n", *ip ) }
運行結(jié)果:
a 變量的地址是: 0xc000010200
ip 變量儲存的指針地址: 0xc000010200
*ip 變量的值: 10
其中:
- a: 代表被取地址的變量,類型為 int
- ip: 用于接收地址的變量,
ip
的類型就為 *int,稱做int
的指針類型。*
代表指針。
用圖來表示一下 ip := &a
:
以上就是指針地址和指針類型。
3. 指針取值
對變量使用 &
會獲取該變量的指針,對指針使用 *
會獲取到值,也就是 “指正取值”。舉個例子更好的理解一下:
package main import "fmt" func main() { a := 20 /* 聲明實際變量 */ b := &a /* 指針變量的存儲地址 */ 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) }
控制臺輸出結(jié)果:
type of b:*int
type of c:int
value of c:10
小結(jié)一下:
- 指針變量的值是指針地址 (可以結(jié)合上圖更好的理解)
- 對變量進行取地址
&
操作,可以獲得這個變量的指針變量 - 對指針變量進行取值
*
操作,可以獲得指針變量指向的原變量的值
函數(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. 空指針
當一個指針被定義后沒有分配到任何變量時,它的值為 nil
。
nil
指針也稱為空指針。
nil
在概念上和其它語言的 null、None、nil、NULL
一樣,都指代零值或空值。
一個指針變量通??s寫為 ptr
。
舉個例子:
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
舉個例子:
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ù)傳入的類型分配一片內(nèi)存空間并返回指向這片內(nèi)存空間的指針。
func new(Type) *Type
解釋一下:
- Type 表示類型,new 函數(shù)只接受一個參數(shù),這個參數(shù)是一個類型
- *Type 表示類型指針,new 函數(shù)返回一個指向該類型內(nèi)存地址的指針
舉個例子:
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ū)別
面試高頻題,這個要考,記一下。
- make 和 new 都是用來做內(nèi)存分配
- make 只用于 slice、map 、channel 的初始化,返回的還是這三個引用類型本身,因為這三種類型就是引用類型,所以就沒必要返回其指針了
- new 用于類型的內(nèi)存分配,并且內(nèi)存對應的值為類型零值,返回的是指向類型的指針。
8. 問題
Q: 執(zhí)行下面的代碼會出現(xià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: 會出現(xiàn) panic runtime error: invalid memory address or nil pointer dereference
。出錯行數(shù)在第 7 行。
原因:在 Go 語言中我們使用引用類型的變量需要先申明、分配內(nèi)存空間,否則在賦值是會出錯。值類型的變量除外,因為其在申明時就分配了默認的內(nèi)存空間。這也是 new 和 make 的作用。
到此這篇關(guān)于Go語言基礎學習之指針詳解的文章就介紹到這了,更多相關(guān)Go語言指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang限流器time/rate設計與實現(xiàn)詳解
在?Golang?庫中官方給我們提供了限流器的實現(xiàn)golang.org/x/time/rate,它是基于令牌桶算法(Token?Bucket)設計實現(xiàn)的,下面我們就來看看他的具體使用吧2024-03-03詳解Go語言如何實現(xiàn)類似Python中的with上下文管理器
熟悉?Python?的同學應該知道?Python?中的上下文管理器非常好用,那么在?Go?中是否也能實現(xiàn)上下文管理器呢,下面小編就來和大家仔細講講吧2023-07-07用gin開發(fā)的golang項目三種開發(fā)模式方式
這篇文章主要介紹了用gin開發(fā)的golang項目三種開發(fā)模式方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01Golang使用協(xié)程實現(xiàn)批量獲取數(shù)據(jù)
服務端經(jīng)常需要返回一個列表,里面包含很多用戶數(shù)據(jù),常規(guī)做法當然是遍歷然后讀緩存。使用Go語言后,可以并發(fā)獲取,極大提升效率,本文就來聊聊具體的實現(xiàn)方法,希望對大家有所幫助2023-02-02Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)
這篇文章主要介紹了Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)2022-01-01Go語言遍歷map實現(xiàn)(訪問map中的每一個鍵值對)
這篇文章主要介紹了Go語言遍歷map實現(xiàn)(訪問map中的每一個鍵值對),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01