欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Go語(yǔ)言中的數(shù)組和切片

 更新時(shí)間:2016年09月11日 09:37:31   投稿:daisy  
Go語(yǔ)言中的數(shù)組大概相當(dāng)與C/C++中的數(shù)組,固定大小,不能夠動(dòng)態(tài)擴(kuò)展大小,而切片大概相當(dāng)與C++中的Vector,可以動(dòng)態(tài)擴(kuò)展大小,當(dāng)大小超過(guò)容量時(shí),重新分配一塊內(nèi)存,然后將數(shù)據(jù)復(fù)制到新的內(nèi)存區(qū)域。下面我們通過(guò)幾個(gè)問(wèn)題來(lái)更好理解golang 的數(shù)組和切片,一起來(lái)看看吧。

一、類(lèi)型

數(shù)組是值類(lèi)型,將一個(gè)數(shù)組賦值給另一個(gè)數(shù)組時(shí),傳遞的是一份拷貝。

切片是引用類(lèi)型,切片包裝的數(shù)組稱(chēng)為該切片的底層數(shù)組。

我們來(lái)看一段代碼

//a是一個(gè)數(shù)組,注意數(shù)組是一個(gè)固定長(zhǎng)度的,初始化時(shí)候必須要指定長(zhǎng)度,不指定長(zhǎng)度的話(huà)就是切片了
a := [3]int{1, 2, 3}
//b是數(shù)組,是a的一份拷貝
b := a
//c是切片,是引用類(lèi)型,底層數(shù)組是a
c := a[:]
for i := 0; i < len(a); i++ {
 a[i] = a[i] + 1
}
//改變a的值后,b是a的拷貝,b不變,c是引用,c的值改變
fmt.Println(a) //[2,3,4]
fmt.Println(b) //[1 2 3]
fmt.Println(c) //[2,3,4]

二、make

make 只能用于slice, map channel, 所以下面一段代碼生成了一個(gè)slice,是引用類(lèi)型

s1 := make([]int, 0, 3)

for i := 0; i < cap(s1); i++ {
 s1 = append(s1, i)
}
s2 := s1
for i := 0; i < len(a); i++ {
 s1[i] = s1[i] + 1
}

fmt.Println(s1) //[1 2 3]
fmt.Println(s2) //[1 2 3]

三、當(dāng)對(duì)slice append 超出底層數(shù)組的界限時(shí)

//n1是n2的底層數(shù)組
n1 := [3]int{1, 2, 3}
n2 := n1[0:3]
fmt.Println("address of items in n1: ")
for i := 0; i < len(n1); i++ {
 fmt.Printf("%p\n", &n1[i])
}
//address of items in n1:
//0xc20801e160
//0xc20801e168
//0xc20801e170
fmt.Println("address of items in n2: ")
for i := 0; i < len(n2); i++ {
 fmt.Printf("%p\n", &n2[i])
}
//address of items in n2:
//0xc20801e160
//0xc20801e168
//0xc20801e170

//對(duì)n2執(zhí)行append操作后,n2超出了底層數(shù)組n1的j
n2 = append(n2, 1)
fmt.Println("address of items in n1: ")
for i := 0; i < len(n1); i++ {
 fmt.Printf("%p\n", &n1[i])
}
//address of items in n1:
//0xc20801e160
//0xc20801e168
//0xc20801e170

fmt.Println("address of items in n2: ")
for i := 0; i < len(n2); i++ {
 fmt.Printf("%p\n", &n2[i])
}
//address of items in n2:
//0xc20803a2d0
//0xc20803a2d8
//0xc20803a2e0
//0xc20803a2e8

四、引用“失效”

實(shí)現(xiàn)了刪除slice最后一個(gè)item的函數(shù)

func rmLast(a []int) {
 fmt.Printf("[rmlast] the address of a is %p", a)
 a = a[:len(a)-1]
 fmt.Printf("[rmlast] after remove, the address of a is %p", a)
}

調(diào)用此函數(shù)后,發(fā)現(xiàn)原來(lái)的slice并沒(méi)有改變

func main() {
 xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
 fmt.Printf("[main] the address of xyz is %p\n", xyz)
 rmLast(xyz)
 fmt.Printf("[main] after remove, the address of xyz is %p\n", xyz)
 fmt.Printf("%v", xyz) //[1 2 3 4 5 6 7 8 9]
}

打印出來(lái)的結(jié)果如下:

[main] the address of xyz is 0xc2080365f0
[rmlast] the address of a is 0xc2080365f0
[rmlast] after remove, the address of a is 0xc2080365f0
[main] after remove, the address of xyz is 0xc2080365f0
[1 2 3 4 5 6 7 8 9]

這里直接打印了slice的指針值,因?yàn)?code>slice是引用類(lèi)型,所以指針值都是相同的,我們換成打印slice的地址看下

func rmLast(a []int) {
 fmt.Printf("[rmlast] the address of a is %p", &a)
 a = a[:len(a)-1]
 fmt.Printf("[rmlast] after remove, the address of a is %p", &a)
}
func main() {
 xyz := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
 fmt.Printf("[main] the address of xyz is %p\n", &xyz)
 rmLast(xyz)
 fmt.Printf("[main] after remove, the address of xyz is %p\n", &xyz)
 fmt.Printf("%v", xyz) //[1 2 3 4 5 6 7 8 9]
}

結(jié)果:

[main] the address of xyz is 0xc20801e1e0
[rmlast] the address of a is 0xc20801e200
[rmlast] after remove, the address of a is 0xc20801e200
[main] after remove, the address of xyz is 0xc20801e1e0
[1 2 3 4 5 6 7 8 9]

這次可以看到slice作為函數(shù)參數(shù)傳入函數(shù)時(shí),實(shí)際上也是拷貝了一份slice,因?yàn)?code>slice本身是個(gè)指針,所以從現(xiàn)象來(lái)看,slice是引用類(lèi)型

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)或者工作帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。

相關(guān)文章

  • 詳解go中的引用類(lèi)型

    詳解go中的引用類(lèi)型

    這篇文章主要介紹了go中的引用類(lèi)型,文中給大家提到了值類(lèi)型和引用類(lèi)型的區(qū)別,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    后端服務(wù)通常會(huì)需要?jiǎng)?chuàng)建子協(xié)程來(lái)進(jìn)行相應(yīng)的作業(yè),但進(jìn)程接受到終止信號(hào)或正常結(jié)束時(shí),并沒(méi)有判斷或等待子協(xié)程執(zhí)行結(jié)束,下面這篇文章主要給大家介紹了關(guān)于Golang如何優(yōu)雅的終止一個(gè)服務(wù)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Golang基于Vault實(shí)現(xiàn)敏感數(shù)據(jù)加解密

    Golang基于Vault實(shí)現(xiàn)敏感數(shù)據(jù)加解密

    數(shù)據(jù)加密是主要的數(shù)據(jù)安全防護(hù)技術(shù)之一,敏感數(shù)據(jù)應(yīng)該加密存儲(chǔ)在數(shù)據(jù)庫(kù)中,降低泄露風(fēng)險(xiǎn),本文將介紹一下利用Vault實(shí)現(xiàn)敏感數(shù)據(jù)加解密的方法,需要的可以參考一下
    2023-07-07
  • go語(yǔ)言中的json與map相互轉(zhuǎn)換實(shí)現(xiàn)

    go語(yǔ)言中的json與map相互轉(zhuǎn)換實(shí)現(xiàn)

    本文主要介紹了go語(yǔ)言中的json與map相互轉(zhuǎn)換實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Go語(yǔ)言流程控制詳情

    Go語(yǔ)言流程控制詳情

    這篇文章主要介紹了Go語(yǔ)言流程控制詳情,流程控制包含分三大類(lèi):條件判斷,循環(huán)控制和無(wú)條件跳轉(zhuǎn)。下面關(guān)于更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-03-03
  • go-zero源碼閱讀之布隆過(guò)濾器實(shí)現(xiàn)代碼

    go-zero源碼閱讀之布隆過(guò)濾器實(shí)現(xiàn)代碼

    布隆過(guò)濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中。它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都比一般的算法要好的多,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難,這篇文章主要介紹了go-zero源碼閱讀-布隆過(guò)濾器,需要的朋友可以參考下
    2023-02-02
  • 淺析Golang開(kāi)發(fā)中g(shù)oroutine的正確使用姿勢(shì)

    淺析Golang開(kāi)發(fā)中g(shù)oroutine的正確使用姿勢(shì)

    很多初級(jí)的Gopher在學(xué)習(xí)了goroutine之后,在項(xiàng)目中其實(shí)使用率不高,所以這篇文章小編主要來(lái)帶大家深入了解一下goroutine的常見(jiàn)使用方法,希望對(duì)大家有所幫助
    2024-03-03
  • go語(yǔ)言實(shí)現(xiàn)LRU緩存的示例代碼

    go語(yǔ)言實(shí)現(xiàn)LRU緩存的示例代碼

    LRU是一種常見(jiàn)的緩存淘汰策略,用于管理緩存中的數(shù)據(jù),本文主要介紹了go語(yǔ)言實(shí)現(xiàn)LRU緩存的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 解析Golang中引用類(lèi)型是否進(jìn)行引用傳遞

    解析Golang中引用類(lèi)型是否進(jìn)行引用傳遞

    這篇文章主要為大家介紹了Golang中引用類(lèi)型是否進(jìn)行引用傳遞剖析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang中對(duì)json的優(yōu)雅處理方式

    Golang中對(duì)json的優(yōu)雅處理方式

    這篇文章主要給大家介紹了關(guān)于Golang中對(duì)json的優(yōu)雅處理方式,解析JSON在golang中很麻煩,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06

最新評(píng)論