亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

簡(jiǎn)單聊一聊Go語(yǔ)言中的數(shù)組和切片

 更新時(shí)間:2021年07月18日 16:06:09   作者:架構(gòu)精進(jìn)之路  
數(shù)組和切片由于語(yǔ)法十分相似,在使用中容易混淆,要認(rèn)真區(qū)分,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中數(shù)組和切片的相關(guān)資料,需要的朋友可以參考下

1. 數(shù)組

數(shù)組是一個(gè)由固定長(zhǎng)度的特定類(lèi)型元素組成的序列,一個(gè)數(shù)組可以由零個(gè)或多個(gè)元素組成。因?yàn)閿?shù)組的長(zhǎng)度是固定的,因此在 Go 語(yǔ)言中很少直接使用數(shù)組。和數(shù)組對(duì)應(yīng)的類(lèi)型是 Slice(切片),它是可以增長(zhǎng)和收縮的動(dòng)態(tài)序列,slice 功能也更靈活。

數(shù)組的每個(gè)元素可以通過(guò)索引下標(biāo)來(lái)訪問(wèn),索引下標(biāo)的范圍是從 0 開(kāi)始到數(shù)組長(zhǎng)度減 1 的位置。內(nèi)置的 len 函數(shù)將返回?cái)?shù)組中元素的個(gè)數(shù)。

var a [3]int             // array of 3 integers
fmt.Println(a[0])        // print the first element
fmt.Println(a[len(a)-1]) // print the last element, a[2]

默認(rèn)情況下,數(shù)組的每個(gè)元素都被初始化為元素類(lèi)型對(duì)應(yīng)的零值,對(duì)于數(shù)字類(lèi)型來(lái)說(shuō)就是 0。

var q [3]int = [3]int{1, 2, 3}
var r [3]int = [3]int{1, 2}
fmt.Println(r[2]) // "0"

如果在數(shù)組的長(zhǎng)度位置出現(xiàn)的是“...”省略號(hào),則表示數(shù)組的長(zhǎng)度是根據(jù)初始化值的個(gè)數(shù)來(lái)計(jì)算。因此,上面 q 數(shù)組的定義可以簡(jiǎn)化為:

q := [...]int{1, 2, 3}
fmt.Printf("%T\n", q) // "[3]int"

數(shù)組的長(zhǎng)度是數(shù)組類(lèi)型的一個(gè)組成部分,因此[3]int 和[4]int 是兩種不同的數(shù)組類(lèi)型。

數(shù)組的長(zhǎng)度必須是常量表達(dá)式,因?yàn)閿?shù)組的長(zhǎng)度需要在編譯階段確定。

q := [3]int{1, 2, 3}
q = [4]int{1, 2, 3, 4} // compile error: cannot assign [4]int to [3]int

如果一個(gè)數(shù)組的元素類(lèi)型是可以相互比較的,那么數(shù)組類(lèi)型也是可以相互比較的,這時(shí)候我們可以直接通過(guò)==比較運(yùn)算符來(lái)比較兩個(gè)數(shù)組,只有當(dāng)兩個(gè)數(shù)組的所有元素都是相等的時(shí)候數(shù)組才是相等的。不相等比較運(yùn)算符!=遵循同樣的規(guī)則。

a := [2]int{1, 2}
b := [...]int{1, 2}
c := [2]int{1, 3}
fmt.Println(a == b, a == c, b == c) // "true false false"
d := [3]int{1, 2}
fmt.Println(a == d) // compile error: cannot compare [2]int == [3]int

2. 切片(Slice)

Slice(切片)代表變長(zhǎng)的序列,序列中每個(gè)元素都有相同的類(lèi)型。一個(gè) slice 類(lèi)型一般寫(xiě)作[]T,其中 T 代表 slice 中元素的類(lèi)型;slice 的語(yǔ)法和數(shù)組很像,只是沒(méi)有固定長(zhǎng)度而已。

一個(gè) slice 是一個(gè)輕量級(jí)的數(shù)據(jù)結(jié)構(gòu),提供了訪問(wèn)數(shù)組子序列(或者全部)元素的功能,而且 slice 的底層確實(shí)引用一個(gè)數(shù)組對(duì)象。

一個(gè) slice 由三個(gè)部分構(gòu)成:指針、長(zhǎng)度和容量。

  • 指針指向第一個(gè) slice 元素對(duì)應(yīng)的底層數(shù)組元素的地址,要注意的是 slice 的第一個(gè)元素并不一定就是數(shù)組的第一個(gè)元素。
  • 長(zhǎng)度對(duì)應(yīng) slice 中元素的數(shù)目;
  • 長(zhǎng)度不能超過(guò)容量,容量一般是從 slice 的開(kāi)始位置到底層數(shù)據(jù)的結(jié)尾位置。內(nèi)置的 len 和 cap 函數(shù)分別返回 slice 的長(zhǎng)度和容量。

表示一年中每個(gè)月份名字的字符串?dāng)?shù)組,還有重疊引用了該數(shù)組的兩個(gè) slice。數(shù)組這樣定義:

months := [...]string{1: "January", /* ... */, 12: "December"}

因此一月份是 months[1],十二月份是 months[12]。

通常,數(shù)組的第一個(gè)元素從索引 0 開(kāi)始,但是月份一般是從 1 開(kāi)始的,因此我們聲明數(shù)組時(shí)直接跳過(guò)第 0 個(gè)元素,第 0 個(gè)元素會(huì)被自動(dòng)初始化為空字符串。

slice 的切片操作 s[i:j],其中 0 ≤ i≤ j≤ cap(s),用于創(chuàng)建一個(gè)新的 slice,引用 s 的從第 i 個(gè)元素開(kāi)始到第 j-1 個(gè)元素的子序列。新的 slice 將只有 j-i 個(gè)元素。如果 i 位置的索引被省略的話將使用 0 代替,如果 j 位置的索引被省略的話將使用 len(s)代替。因此,months[1:13]切片操作將引用全部有效的月份,和 months[1:]操作等價(jià);months[:]切片操作則是引用整個(gè)數(shù)組。讓我們分別定義表示第二季度和北方夏天月份的 slice,它們有重疊部分:

Q2 := months[4:7]
summer := months[6:9]
fmt.Println(Q2)     // ["April" "May" "June"]
fmt.Println(summer) // ["June" "July" "August"]

兩個(gè) slice 都包含了六月份。

append 函數(shù)

append 函數(shù)用于向 slice 追加元素:

var runes []rune
for _, r := range "Hello, 世界" {
    runes = append(runes, r)
}
fmt.Printf("%q\n", runes) // "['H' 'e' 'l' 'l' 'o' ',' ' ' '世' '界']"

為了提高內(nèi)存使用效率,新分配的數(shù)組一般略大于保存 x 和 y 所需要的最低大小。通過(guò)在每次擴(kuò)展數(shù)組時(shí)直接將長(zhǎng)度翻倍從而避免了多次內(nèi)存分配,也確保了添加單個(gè)元素操作的平均時(shí)間是一個(gè)常數(shù)時(shí)間。這個(gè)程序演示了效果:

func main() {
    var x, y []int
    for i := 0; i < 10; i++ {
        y = appendInt(x, i)
        fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y)
        x = y
    }
}

//每一次容量的變化都會(huì)導(dǎo)致重新分配內(nèi)存和copy操作:
0  cap=1    [0]
1  cap=2    [0 1]
2  cap=4    [0 1 2]
3  cap=4    [0 1 2 3]
4  cap=8    [0 1 2 3 4]
5  cap=8    [0 1 2 3 4 5]
6  cap=8    [0 1 2 3 4 5 6]
7  cap=8    [0 1 2 3 4 5 6 7]
8  cap=16   [0 1 2 3 4 5 6 7 8]
9  cap=16   [0 1 2 3 4 5 6 7 8 9]

讓我們仔細(xì)查看 i=3 次的迭代。當(dāng)時(shí) x 包含了[0 1 2]三個(gè)元素,但是容量是 4,因此可以簡(jiǎn)單將新的元素添加到末尾,不需要新的內(nèi)存分配。然后新的 y 的長(zhǎng)度和容量都是 4,并且和 x 引用著相同的底層數(shù)組,如圖 4.2 所示。

在下一次迭代時(shí) i=4,現(xiàn)在沒(méi)有新的空余的空間了,因此 appendInt 函數(shù)分配一個(gè)容量為 8 的底層數(shù)組,將 x 的 4 個(gè)元素[0 1 2 3]復(fù)制到新空間的開(kāi)頭,然后添加新的元素 i,新元素的值是 4。新的 y 的長(zhǎng)度是 5,容量是 8;后面有 3 個(gè)空閑的位置,三次迭代都不需要分配新的空間。當(dāng)前迭代中,y 和 x 是對(duì)應(yīng)不同底層數(shù)組的 view。這次操作如圖 4.3 所示。

內(nèi)置的 append 函數(shù)可能使用比 appendInt 更復(fù)雜的內(nèi)存擴(kuò)展策略。

因此,通常我們并不知道 append 調(diào)用是否導(dǎo)致了內(nèi)存的重新分配,因此我們也不能確認(rèn)新的 slice 和原始的 slice 是否引用的是相同的底層數(shù)組空間。

同樣,我們不能確認(rèn)在原先的 slice 上的操作是否會(huì)影響到新的 slice。

總結(jié)

到此這篇關(guān)于Go語(yǔ)言中數(shù)組和切片的文章就介紹到這了,更多相關(guān)Go語(yǔ)言數(shù)組和切片內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Go語(yǔ)言如何對(duì)數(shù)據(jù)庫(kù)進(jìn)行CRUD操作

    詳解Go語(yǔ)言如何對(duì)數(shù)據(jù)庫(kù)進(jìn)行CRUD操作

    在這篇文章中,主要帶大家來(lái)學(xué)習(xí)一下在Go語(yǔ)言中如何對(duì)數(shù)據(jù)庫(kù)進(jìn)行CRUD操作,從而探討一下Go的接口編程,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05
  • 關(guān)于golang 字符串 int uint int64 uint64 互轉(zhuǎn)問(wèn)題

    關(guān)于golang 字符串 int uint int64 uint64&

    這篇文章主要介紹了golang 字符串 int uint int64 uint64 互轉(zhuǎn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • Go 語(yǔ)言中的指針的使用

    Go 語(yǔ)言中的指針的使用

    在Go語(yǔ)言中,指針是存儲(chǔ)另一變量?jī)?nèi)存地址的變量,通過(guò)&操作符獲取變量地址,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • Go 語(yǔ)言中關(guān)于接口的三個(gè)

    Go 語(yǔ)言中關(guān)于接口的三個(gè)

    這篇文章主要介紹了Go 語(yǔ)言中關(guān)于接口的三個(gè)"潛規(guī)則",本文通過(guò)實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Go并發(fā)編程結(jié)構(gòu)體多字段原子操作示例詳解

    Go并發(fā)編程結(jié)構(gòu)體多字段原子操作示例詳解

    這篇文章主要為大家介紹了Go并發(fā)編程結(jié)構(gòu)體多字段原子操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go分布式鏈路追蹤實(shí)戰(zhàn)探索

    Go分布式鏈路追蹤實(shí)戰(zhàn)探索

    這篇文章主要為大家介紹了Go分布式鏈路追蹤實(shí)戰(zhàn)示例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 詳解Golang中單元測(cè)試的使用

    詳解Golang中單元測(cè)試的使用

    單元測(cè)試是檢測(cè)你寫(xiě)的一個(gè)函數(shù)是否具備安全性的一次檢測(cè),這篇文章主要為大家詳細(xì)介紹了Golang中單元測(cè)試的具體使用,希望對(duì)大家有所幫助
    2023-07-07
  • go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    go-zero 應(yīng)對(duì)海量定時(shí)/延遲任務(wù)的技巧

    這篇文章主要介紹了go-zero 如何應(yīng)對(duì)海量定時(shí)/延遲任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Golang中json和jsoniter的區(qū)別使用示例

    Golang中json和jsoniter的區(qū)別使用示例

    這篇文章主要介紹了Golang中json和jsoniter的區(qū)別使用示例,本文給大家分享兩種區(qū)別,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2023-12-12
  • Golang操作命令行的幾種方式總結(jié)

    Golang操作命令行的幾種方式總結(jié)

    這篇文章主要介紹了Golang操作命令行的幾種方式總結(jié),文章通過(guò)圍主題思想展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09

最新評(píng)論