偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

咱們來(lái)重新認(rèn)識(shí)一下Golang的切片

開發(fā) 前端
我們先來(lái)看一下Golang中的數(shù)組,大家都知道Golang其實(shí)是c語(yǔ)言寫的,那么在數(shù)組這一塊Golang和c語(yǔ)言的含義一樣么?當(dāng)然是不一樣的。

今天廢話不用多說(shuō),咱們來(lái)直接進(jìn)入正題

切片究竟是什么?

在聊切片之前,我們先來(lái)看一下golang中的數(shù)組,大家都知道golang其實(shí)是c語(yǔ)言寫的,那么在數(shù)組這一塊golang和c語(yǔ)言的含義一樣么?當(dāng)然是不一樣的。

golang數(shù)組

  • Go數(shù)組是值語(yǔ)義的,這意味著一個(gè)數(shù)組變量表示的是「整個(gè)數(shù)組」。
  • Go語(yǔ)言中傳遞數(shù)組是純粹的「值拷貝」。

c語(yǔ)言數(shù)組

  • 數(shù)組變量可視為指向數(shù)組「第一個(gè)元素的指針」。

因?yàn)間olang中數(shù)組是純粹的值拷貝,所以在golang中,更地道的方式是使用「切片」, 「切片之于數(shù)組就像是文件描述符之于文件」數(shù)組更多是“退居幕后”,承擔(dān)的是底層存儲(chǔ)空間的角色;而切片則走向“前臺(tái)”,為底層的存儲(chǔ)(數(shù)組)打開了一個(gè)訪問的“窗口”。

圖片

切片和數(shù)組的關(guān)系

其實(shí)通過golang源碼也可以看出來(lái),其實(shí)切片就是數(shù)組的指針。

//$GOROOT/src/runtime/slice.go
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

如何聲明一個(gè)切片?

方式一

s := make([]byte, 5)

圖片

我們看到通過上述語(yǔ)句創(chuàng)建的切片,編譯器會(huì)自動(dòng)為切片建立一個(gè)「底層數(shù)組」,如果沒有在make中指定cap參數(shù),那么cap = len,即編譯器建立的數(shù)組長(zhǎng)度為len。

方式二(數(shù)組切片化)

u := [10]byte{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
s := u[3:7]

圖片

數(shù)組切片化

  • 切片s打開了一個(gè)操作數(shù)組u的窗口。
  • 切片截取數(shù)組是「左包含右不包含」的原則。比如u[3,7]為包含u[3]但是不包含u[7]。
  • 「切片的長(zhǎng)度len」為4,計(jì)算方式為(high-low),在這個(gè)case中也就是7-3=4。
  • 「切片的容量cap」為s的第一個(gè)元素s[0]到數(shù)組u的末尾,所以是7。

當(dāng)然可以基于一個(gè)數(shù)組建立多個(gè)切片

u := [10]byte{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
s1 := u[1:5]
s2 := u[6:9]
s3 := u[3:7]

圖片

基于一個(gè)數(shù)組建立多個(gè)切片

也可以基于已有切片再次創(chuàng)建切片,也叫reslicing

u := [10]byte{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
s1 := u[1:5]
s2 := s1[2:4]

圖片

reslicing

動(dòng)態(tài)擴(kuò)容

在講動(dòng)態(tài)擴(kuò)容之前,我們先來(lái)看一些例子。

// chapter3/sources/slice_append.go
var s []int  // s被賦予零值nil
s = append(s, 11)
fmt.Println(len(s), cap(s)) //1 1
s = append(s, 12)
fmt.Println(len(s), cap(s)) //2 2
s = append(s, 13)
fmt.Println(len(s), cap(s)) //3 4
s = append(s, 14)
fmt.Println(len(s), cap(s)) //4 4
s = append(s, 15)
fmt.Println(len(s), cap(s)) //5 8

我們看到切片s的len值是線性增長(zhǎng)的,但cap值卻呈現(xiàn)出不規(guī)則的變化。通過下圖我們更容易看清楚多次append操作究竟是如何讓切片進(jìn)行動(dòng)態(tài)擴(kuò)容的。

圖片

動(dòng)態(tài)擴(kuò)容

我們看到append會(huì)根據(jù)切片的需要,在「當(dāng)前底層數(shù)組容量無(wú)法滿足」的情況下,「動(dòng)態(tài)分配新的數(shù)組」,新數(shù)組長(zhǎng)度會(huì)按一定算法擴(kuò)展(參見$GOROOT/src/runtime/slice.go中的growslice函數(shù))。新數(shù)組建立后,append會(huì)把「舊數(shù)組中的數(shù)據(jù)復(fù)制到新數(shù)組中」,之后新數(shù)組便成為切片的底層數(shù)組,舊數(shù)組后續(xù)會(huì)被「垃圾回收」掉。

這樣的append操作有時(shí)會(huì)給Gopher帶來(lái)一些困惑,比如通過語(yǔ)法u[low: high]形式進(jìn)行數(shù)組切片化而創(chuàng)建的切片,一旦切片cap觸碰到數(shù)組的上界,再對(duì)切片進(jìn)行append操作,切片就會(huì)和原數(shù)組解除綁定。

小結(jié)練習(xí)

根據(jù)自己對(duì)切片的理解,先看看自己能不能想到每一步結(jié)果都會(huì)輸出啥。

// chapter3/sources/slice_unbind_orig_array.go

func main() {
    u := []int{11, 12, 13, 14, 15}
    fmt.Println("array:", u) // [11, 12, 13, 14, 15]
    s := u[1:3]
    fmt.Printf("slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // [12, 13]
    s = append(s, 24)
    fmt.Println("after append 24, array:", u)
    fmt.Printf("after append 24, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s)
    s = append(s, 25)
    fmt.Println("after append 25, array:", u)
    fmt.Printf("after append 25, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s)
    s = append(s, 26)
    fmt.Println("after append 26, array:", u)
    fmt.Printf("after append 26, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s)

    s[0] = 22
    fmt.Println("after reassign 1st elem of slice, array:", u)
    fmt.Printf("after reassign 1st elem of slice, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s)
}

答案揭曉

$go run slice_unbind_orig_array.go
array: [11 12 13 14 15]
slice(len=2, cap=4): [12 13]
after append 24, array: [11 12 13 24 15]
after append 24, slice(len=3, cap=4): [12 13 24]
after append 25, array: [11 12 13 24 25]
after append 25, slice(len=4, cap=4): [12 13 24 25]
after append 26, array: [11 12 13 24 25]
after append 26, slice(len=5, cap=8): [12 13 24 25 26]
after reassign 1st elem of slice, array: [11 12 13 24 25]
after reassign 1st elem of slice, slice(len=5, cap=8): [22 13 24 25 26]

我們看到在添加元素25之后,切片的元素已經(jīng)觸碰到底層數(shù)組u的邊界;此后再添加元素26,append發(fā)現(xiàn)底層數(shù)組已經(jīng)無(wú)法滿足添加新元素的要求,于是新創(chuàng)建了一個(gè)底層數(shù)組(數(shù)組長(zhǎng)度為cap(s)的2倍,即8),并將原切片的元素復(fù)制到新數(shù)組中。在這之后,即便再修改切片中的元素值,原數(shù)組u的元素也沒有發(fā)生任何改變,因?yàn)榇藭r(shí)切片s與數(shù)組u已經(jīng)解除了綁定關(guān)系,s已經(jīng)不再是數(shù)組u的描述符了。

責(zé)任編輯:姜華 來(lái)源: 程序員小飯
相關(guān)推薦

2022-09-08 13:58:39

Spring高并發(fā)異步

2020-10-15 07:13:53

算法監(jiān)控數(shù)據(jù)

2022-12-07 08:13:55

CNI抽象接口

2019-11-28 10:40:45

Kafka架構(gòu)KafkaConsum

2018-04-02 09:07:36

CIO

2014-01-06 11:23:54

Mesos設(shè)計(jì)架構(gòu)

2013-04-17 11:21:59

Windows PhoWindows Pho

2018-12-24 09:51:22

CPU天梯圖Inter

2023-05-29 08:32:40

JAVA重寫重載

2024-05-27 00:00:00

AmpPHP非阻塞

2021-04-22 21:15:38

Generator函數(shù)生成器

2010-10-22 11:10:24

軟考

2021-11-11 05:00:02

JavaMmap內(nèi)存

2016-11-07 11:34:28

數(shù)據(jù)可視化大數(shù)據(jù)

2016-12-13 15:41:40

JavaHashMap

2019-10-31 13:40:52

JavaPHP編程語(yǔ)言

2019-02-24 21:27:26

物聯(lián)網(wǎng)網(wǎng)關(guān)物聯(lián)網(wǎng)IOT

2017-01-03 17:22:16

公共云安全

2019-09-02 08:53:46

程序員

2020-09-17 07:08:04

TypescriptVue3前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)