1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Go 語言的數(shù)組與切片

        共 4250字,需瀏覽 9分鐘

         ·

        2021-04-12 05:28

        數(shù)組

        數(shù)組是一組類型相同的,長度固定的,按數(shù)字編號(hào)排列的數(shù)據(jù)序列。由于 go 語言中,數(shù)組的類型相同且長度固定,所以在聲明數(shù)組的時(shí)候,就會(huì)體現(xiàn)這兩個(gè)特點(diǎn)。

        var?array?[5]int?//?[0?0?0?0?0]

        數(shù)組通過 [SIZE](方括號(hào)內(nèi)為數(shù)組長度) 加上 TYPE(類型) 的形式聲明,上面的代碼就表示 array 變量為一個(gè)長度為 5,且五個(gè)數(shù)據(jù)的類型都為 int。

        在之前介紹變量的時(shí)候,介紹過 int 類型的默認(rèn)值為 0,所以 array 的值為 [0 0 0 0 0]。

        數(shù)組初始化

        數(shù)組在初始化階段,需要通過 {} 的方式,指定數(shù)組每個(gè)位置的具體值。

        var?array?[3]int?=?[3]int{1,?2,?3}?//?[1?2?3]

        可以看到 {} 的前面也要帶上數(shù)組的長度與類型,由于 go 能夠進(jìn)行類型推導(dǎo),變量后聲明的類型顯得有點(diǎn)多余,是可以省略的。

        var?array?=?[3]int{1,?2,?3}?//?[1?2?3]

        ?? 指定索引賦值

        初始化的過程中,我們還可以指定索引進(jìn)行賦值,也就是不必給數(shù)組的每個(gè)位置都安排上具體的值。

        var?array?=?[5]int{1:?77,?3:?77}?//?[0?77?0?77?0]

        上面的數(shù)組輸出的結(jié)果為:[0 77 0 77 0]。和其他語言一樣,數(shù)組的索引是從 0 開始的,我們給索引為 13 位置都指定了值為 77 ,其他位置由于沒有指定具體值,就是其類型的默認(rèn)值。

        ?? 自動(dòng)推導(dǎo)數(shù)組長度

        前面的案例都是指定了數(shù)組的長度,其實(shí)我們可以通過 [...] 的方式,告訴 go 編譯器,數(shù)組長度尚未確定,在初始化之后才能確定其長度,然后 go 在編譯階段就會(huì)自動(dòng)進(jìn)行推導(dǎo)。

        var?array?=?[...]int{1,?2,?3,?4,?5}?//?[1?2?3?4?5]
        fmt.Println("array?length?is",?len(array))

        我們可以通過 len 方法獲取數(shù)組的長度,上面代碼的運(yùn)行結(jié)果如下:

        a542902a2787c0546dba3e3ccb410a35.webp

        如果我們?cè)谥付ㄋ饕奈恢觅x值了,最終長度取決于最末尾的索引,下面的代碼中,指定了索引 5 的值為 77,則數(shù)組的長度為 6。

        var?array?=?[...]int{1:?77,?5:?77}?//?[0?77?0?0?0?77]
        fmt.Println("array?length?is",?len(array))
        5d4b0ffcae1ed9c7f3501833f83508a7.webp

        賦值與訪問

        與其他語言一樣,數(shù)組的賦值和訪問都是通過 [Index] 操作的。

        var?array?=?[...]int{1,?2,?3}
        array[0]?=?100?//?索引?0?的位置重新賦值為?100
        fmt.Println("array?is",?array)
        00b2b7eb7d2f347c1a2428f0f572f058.webp

        取值也是同樣的操作,我們現(xiàn)在實(shí)現(xiàn)一個(gè)求數(shù)組平均數(shù)的函數(shù):

        func?getAverage(array?[5]int)?float32?{
        ?var?sum?int
        ?var?avg?float32

        ?for?i?:=?0;?i?<?5;?i++?{
        ??sum?+=?array[i]
        ?}

        ?avg?=?float32(sum)?/?5

        ?return?avg
        }
        var?array?=?[5]int{1,?2,?3,?4,?5}
        fmt.Println("average?is",?getAverage(array))
        29c9d2760067b799ecc169e9fcfd77bd.webp

        多維數(shù)組

        多維數(shù)組的聲明,相對(duì)于一維數(shù)組,就是看前面有幾個(gè) [SIZE]。

        var?a1?[2][3]int?//?二維數(shù)組
        var?a1?[2][3][4]int?//?三維數(shù)組

        我們拿三維數(shù)組舉例,第一個(gè) [] ?內(nèi)的數(shù)字表示最外層數(shù)組的長度,往后以此類推。[2][3][4]int 表示最外層數(shù)組長度為 2,第二層數(shù)組長度為 3,最內(nèi)層數(shù)組長度為 4。其賦值方式也和一維數(shù)組一樣,只是多維數(shù)組需要將多個(gè) {} 進(jìn)行嵌套。

        var?a1?=?[2][3][4]int{
        ??{
        ????{1,?2,?3,?4},
        ????{1,?2,?3,?4},
        ????{1,?2,?3,?4},
        ??},
        ??{
        ????{1,?2,?3,?4},
        ????{1,?2,?3,?4},
        ????{1,?2,?3,?4},
        ??},
        }
        fmt.Println(a1)

        打印結(jié)果:

        27c7cd841cc686aeddb676976ff0bd4e.webp

        多維數(shù)組的訪問和一維數(shù)組一樣,也是通過 [] + 數(shù)組索引,只是多維數(shù)組要訪問某個(gè)值需要多個(gè) []。

        如果我們要拿到下圖的 2,訪問方式為:array[0][1][1]

        d2110fb68cf22a1b0448431f9858b74e.webp
        fmt.Println("array[0][1][1]?=?",?array[0][1][1])
        395423cfcfc50630732731e09a35b09d.webp

        切片

        前面介紹過,數(shù)組是一組類型相同且長度固定的數(shù)據(jù)集合,而切片就是一種比較抽象的數(shù)組,其長度不固定,聲明方式與數(shù)組類似([] 中不顯示注明數(shù)組長度,也不使用 [...] 的方式進(jìn)行長度的推導(dǎo)):

        var?slice?[]int

        切片初始化

        切片的初始化與數(shù)組類似,只要省略掉 [] 內(nèi)注明的數(shù)組長度即可:

        var?s1?=?[]int{1,?2,?3}
        s2?:=?[]int{1,?2,?3}?//?簡寫

        除了這種字面量的聲明方式,還可以通過 go 的內(nèi)置方法:make,來進(jìn)行切片的初始化:

        var?s1?=?make([]int,?3)
        s2?:=?make([]int,?3)?//?簡寫

        make 方法的第二個(gè)參數(shù)表示切片的長度,雖然切片的長度可變,但是通過 make 方法創(chuàng)建切片時(shí),需要指定一個(gè)長度。除了指定切片的長度,make 方法還支持傳入第三個(gè)參數(shù),用來指定切片的『容量』,如果沒有指定切片的容量,那初始狀態(tài)切片的容量與長度一致。

        func?make([]T,?len,?cap)

        長度與容量

        長度指的是,切片內(nèi)有多少個(gè)元素,而容量可以理解為,當(dāng)前切片在內(nèi)存中開辟了多大的空間。前面介紹過,可以通過 len 方法獲取到數(shù)組的長度,獲取切片的長度也可以使用該方法。要獲取切片的容量,可以使用 cap 方法。

        s1?:=?make([]int,?5)
        fmt.Printf("The?length?of?s1?is?%d\n",?len(s1))
        fmt.Printf("The?capacity?of?s1?is?%d\n",?cap(s1))
        e01d3841055833b6b8fa4b5c9ee2c520.webp

        可以看到初始狀態(tài)下,切片的長度與容量一致。如果要修改切片的長度,可以通過 append 方法,在切片尾部追加一個(gè)新的值。

        s1?:=?make([]int,?3,?5)?//?聲明一個(gè)長度為?3,容量為?5?的切面
        s1?=?append(s1,?1)?//?在尾部追加一個(gè)值,長度會(huì)變成?4

        fmt.Printf("The?length?of?s1?is?%d\n",?len(s1))
        fmt.Printf("The?capacity?of?s1?is?%d\n",?cap(s1))
        01c51e26bdb2c38c9e0517487b31a119.webp

        append 方法是可以接受多個(gè)參數(shù),我們?cè)谧芳右粋€(gè)值之后,繼續(xù)調(diào)用 append 方法,往切片后再追加兩個(gè)值:

        s1?:=?make([]int,?3,?5)
        s1?=?append(s1,?1)
        s1?=?append(s1,?2,?3)
        fmt.Println(s1)?//?[0?0?0?1?2?3]
        fmt.Printf("The?length?of?s1?is?%d\n",?len(s1))
        fmt.Printf("The?capacity?of?s1?is?%d\n",?cap(s1))

        此時(shí)的切片的長度已經(jīng)變成了 6,超過了切片的容量,那這個(gè)時(shí)候切換的容量會(huì)不會(huì)也變成 6?

        71739887bc6d71b2111c91b9f2d6960b.webp

        根據(jù)輸出的結(jié)果,此時(shí)切片的容量變成了 10,這意味著切片的容量的擴(kuò)充是在之前的基礎(chǔ)上進(jìn)行翻倍操作的。為了驗(yàn)證這個(gè)結(jié)論,我們?cè)谇衅罄^續(xù)追加 5 個(gè)值,讓切片的長度變成 11,超出當(dāng)前的容量,看看容量會(huì)變成多少。

        s1?:=?make([]int,?3,?5)
        s1?=?append(s1,?1)
        s1?=?append(s1,?2,?3)
        s1?=?append(s1,?4,?5,?6,?7,?8)

        fmt.Printf("The?length?of?s1?is?%d\n",?len(s1))
        fmt.Printf("The?capacity?of?s1?is?%d\n",?cap(s1))
        7a3e9d9cf032e234eee9ddd8bc074c4c.webp

        可以看到切片的容量變成了 20,這也驗(yàn)證了我們之前的結(jié)論,當(dāng)切片長度超過了其容量,容量會(huì)在原來的基礎(chǔ)上翻倍。那如果切片容量達(dá)到了 2000,長度超過 2000,容量也會(huì)變成 4000 嗎?

        s1?:=?make([]int,?1024)
        s1?=?append(s1,?1)

        fmt.Printf("\nThe?length?of?s1?is?%d\n",?len(s1))
        fmt.Printf("The?capacity?of?s1?is?%d\n",?cap(s1))
        89cc35a5ae3c4519aa395ea106bc8cb0.webp

        可以看到,我們新定義的切片長度為 1024,在長度變成 1025 的時(shí)候,容量并沒有翻倍。為了避免切片容量無休止的擴(kuò)展,go 規(guī)定如果當(dāng)前切片的長度大于 1024 ,在長度超過其容量時(shí),只會(huì)增加 25% 的容量。

        切片截取

        切片之所以叫切片,是因?yàn)樗梢酝ㄟ^切出數(shù)組中的某一塊來創(chuàng)建。語法規(guī)則也很簡單:Array[start:end]。

        arr?:=?[5]int{1,?2,?3,?4,?5}
        slice?:=?arr[1:3]

        fmt.Println(slice)?//?[2?3]
        83ad6d5fabe69fa62acaced32b3b7ec4.webp

        arr[1:3] 表示將數(shù)組的從索引為 1 的位置一直到索引為 3 的位置(不包括 3)截取出來,形成一個(gè)切片。當(dāng)然這個(gè)開頭結(jié)尾的數(shù)字也是可以省略的,如果我們?nèi)绻覀兪÷蚤_頭就表示截取開始的位置為 0,省略結(jié)尾就表示截取結(jié)束的位置一直到數(shù)組的最后一位。

        arr?:=?[5]int{1,?2,?3,?4,?5}
        slice?:=?arr[1:]
        fmt.Println(slice)?//?[2?3?4?5]
        d3bf8884f0493fd653941714651da5aa.webp

        通過省略截取的開頭和結(jié)尾,我們就能將一個(gè)數(shù)組進(jìn)行一次拷貝操作,然后形成一個(gè)切片。(PS. 截取操作形成的新數(shù)據(jù)是一個(gè)切片)

        arr?:=?[5]int{1,?2,?3,?4,?5}
        slice?:=?arr[:]

        fmt.Printf("slice?=?%v,?slice?type?is?%T",?slice,?slice)
        3319e76f797debe8ad5c772b0ad8a5dd.webp


        瀏覽 44
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            freejapanxxxxhdvideo | 看黄免费在线观看 | 自慰在线观看 | 欧美激情三级 | 欧美黑人狂躁少妇无码中文字幕 | 亚洲一区二区三区avav老司机 | 男人添女荫道口免费视频 | AⅤ无码痴汉电车人妻91 | 少妇高潮在线视频 | 日本妇乱大交xxxxx |