成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

咱們來重新認識一下Golang的切片

開發 前端
我們先來看一下Golang中的數組,大家都知道Golang其實是c語言寫的,那么在數組這一塊Golang和c語言的含義一樣么?當然是不一樣的。

今天廢話不用多說,咱們來直接進入正題

切片究竟是什么?

在聊切片之前,我們先來看一下golang中的數組,大家都知道golang其實是c語言寫的,那么在數組這一塊golang和c語言的含義一樣么?當然是不一樣的。

golang數組

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

c語言數組

  • 數組變量可視為指向數組「第一個元素的指針」。

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

圖片

切片和數組的關系

其實通過golang源碼也可以看出來,其實切片就是數組的指針。

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

如何聲明一個切片?

方式一

s := make([]byte, 5)

圖片

我們看到通過上述語句創建的切片,編譯器會自動為切片建立一個「底層數組」,如果沒有在make中指定cap參數,那么cap = len,即編譯器建立的數組長度為len。

方式二(數組切片化)

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

圖片

數組切片化

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

當然可以基于一個數組建立多個切片

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]

圖片

基于一個數組建立多個切片

也可以基于已有切片再次創建切片,也叫reslicing

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

圖片

reslicing

動態擴容

在講動態擴容之前,我們先來看一些例子。

// 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值是線性增長的,但cap值卻呈現出不規則的變化。通過下圖我們更容易看清楚多次append操作究竟是如何讓切片進行動態擴容的。

圖片

動態擴容

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

這樣的append操作有時會給Gopher帶來一些困惑,比如通過語法u[low: high]形式進行數組切片化而創建的切片,一旦切片cap觸碰到數組的上界,再對切片進行append操作,切片就會和原數組解除綁定。

小結練習

根據自己對切片的理解,先看看自己能不能想到每一步結果都會輸出啥。

// 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之后,切片的元素已經觸碰到底層數組u的邊界;此后再添加元素26,append發現底層數組已經無法滿足添加新元素的要求,于是新創建了一個底層數組(數組長度為cap(s)的2倍,即8),并將原切片的元素復制到新數組中。在這之后,即便再修改切片中的元素值,原數組u的元素也沒有發生任何改變,因為此時切片s與數組u已經解除了綁定關系,s已經不再是數組u的描述符了。

責任編輯:姜華 來源: 程序員小飯
相關推薦

2022-09-08 13:58:39

Spring高并發異步

2020-10-15 07:13:53

算法監控數據

2022-12-07 08:13:55

CNI抽象接口

2019-11-28 10:40:45

Kafka架構KafkaConsum

2018-04-02 09:07:36

CIO

2014-01-06 11:23:54

Mesos設計架構

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函數生成器

2010-10-22 11:10:24

軟考

2021-11-11 05:00:02

JavaMmap內存

2016-11-07 11:34:28

數據可視化大數據

2016-12-13 15:41:40

JavaHashMap

2019-10-31 13:40:52

JavaPHP編程語言

2019-02-24 21:27:26

物聯網網關物聯網IOT

2017-01-03 17:22:16

公共云安全

2019-09-02 08:53:46

程序員

2020-09-17 07:08:04

TypescriptVue3前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一伦一伦一伦 | 五月天激情综合网 | 免费观看一级特黄欧美大片 | 欧美综合国产精品久久丁香 | 国产视频第一页 | 久久av网站 | av中文字幕在线观看 | 成人精品国产 | 毛片黄片 | 久久精品福利视频 | 国产视频第一页 | 久久综合伊人 | 欧美日韩综合精品 | 国产乱码精品一区二区三区五月婷 | www.夜夜骑.com | 国产精品久久久久久久岛一牛影视 | 亚洲视频中文字幕 | 99综合| 一区二区在线 | 91麻豆精品一区二区三区 | 色在线视频网站 | 久草资源| 亚洲狠狠| 中文字幕视频在线 | com.国产| 一级黄色片网站 | 亚洲一区二区三区视频免费观看 | chinese中国真实乱对白 | av片免费观看| 一区二区三区四区电影视频在线观看 | 在线观看黄色电影 | 九九亚洲 | 91视频三区 | 欧美亚洲激情 | av小说在线| 成人在线h | 国产亚洲精品成人av久久ww | 欧美日韩一区二区电影 | 亚洲精彩视频 | 欧美一区二区黄 | 国产成人网 |