<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 4250字,需瀏覽 9分鐘

           ·

          2021-04-12 05:28

          數(shù)組

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

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

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

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

          數(shù)組初始化

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

          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ù)組的每個位置都安排上具體的值。

          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ǎo)數(shù)組長度

          前面的案例都是指定了數(shù)組的長度,其實(shí)我們可以通過 [...] 的方式,告訴 go 編譯器,數(shù)組長度尚未確定,在初始化之后才能確定其長度,然后 go 在編譯階段就會自動進(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

          如果我們在指定索引的位置賦值了,最終長度取決于最末尾的索引,下面的代碼中,指定了索引 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)一個求數(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ù)組的聲明,相對于一維數(shù)組,就是看前面有幾個 [SIZE]

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

          我們拿三維數(shù)組舉例,第一個 [] ?內(nèi)的數(shù)字表示最外層數(shù)組的長度,往后以此類推。[2][3][4]int 表示最外層數(shù)組長度為 2,第二層數(shù)組長度為 3,最內(nèi)層數(shù)組長度為 4。其賦值方式也和一維數(shù)組一樣,只是多維數(shù)組需要將多個 {} 進(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ù)組要訪問某個值需要多個 []

          如果我們要拿到下圖的 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 方法的第二個參數(shù)表示切片的長度,雖然切片的長度可變,但是通過 make 方法創(chuàng)建切片時,需要指定一個長度。除了指定切片的長度,make 方法還支持傳入第三個參數(shù),用來指定切片的『容量』,如果沒有指定切片的容量,那初始狀態(tài)切片的容量與長度一致。

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

          長度與容量

          長度指的是,切片內(nèi)有多少個元素,而容量可以理解為,當(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 方法,在切片尾部追加一個新的值。

          s1?:=?make([]int,?3,?5)?//?聲明一個長度為?3,容量為?5?的切面
          s1?=?append(s1,?1)?//?在尾部追加一個值,長度會變成?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 方法是可以接受多個參數(shù),我們在追加一個值之后,繼續(xù)調(diào)用 append 方法,往切片后再追加兩個值:

          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))

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

          71739887bc6d71b2111c91b9f2d6960b.webp

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

          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)切片長度超過了其容量,容量會在原來的基礎(chǔ)上翻倍。那如果切片容量達(dá)到了 2000,長度超過 2000,容量也會變成 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 的時候,容量并沒有翻倍。為了避免切片容量無休止的擴(kuò)展,go 規(guī)定如果當(dāng)前切片的長度大于 1024 ,在長度超過其容量時,只會增加 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)截取出來,形成一個切片。當(dāng)然這個開頭結(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é)尾,我們就能將一個數(shù)組進(jìn)行一次拷貝操作,然后形成一個切片。(PS. 截取操作形成的新數(shù)據(jù)是一個切片)

          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)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色哟哟一区二区三区四区 | 人妻精品导航 | 亚洲欧洲无码在线观看 | 无人无码深夜久久 | 精品视频韩国 |