Go語言實戰筆記(四)| Go 數組

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。

數組,是用來儲存集合資料的,這種情境非常多,我們編碼的過程中,都少不了要讀取或者儲存資料。當然除了數組之外,我們還有切片、Map映射等資料結構可以幫我們儲存資料,但是數組是它們的基礎。

內部實現

要想更清晰的瞭解數組,我們得瞭解它的內部實現。數組是長度固定的資料類型,必須儲存一段相同類型的元素,而且這些元素是連續的。我們這裡強調固定長度,可以說這是和切片最明顯的區別。

數組儲存的類型可以是內建類型,比如整型或者字串,也可以是自訂的資料結構。因為是連續的,所以索引比較好計算,所以我們可以很快的索引數組中的任何資料。

這裡的索引,一直都是0,1,2,3這樣的,因為其元素類型相同,我們也可以使用反射,擷取類型佔用大小,進行移位,擷取相應的元素,這個反射的時候,我們再講。

聲明和初始化

數組的聲明和初始化,和其他類型差不多。聲明的原則是:

  1. 指明儲存資料的類型。
  2. 儲存元素的數量,也就是數組長度。
1
var array [5]int

以上我們聲明了一個數組array,但是我們還沒有對他進行初始化,這時候數組array裡面的值,是對應元素類型的零值,也就是說,現在這個數組是5個0,這和我們java不一樣,java裡是null。

數組一旦聲明後,其元素類型和大小都不能變了,如果還需要儲存更多的元素怎麼辦?那麼只能通過建立一個新的數組,然後把原來數組的資料複製過去。

剛剛聲明的數組已經被預設的元素類型零值初始化了,如果我們再次進行初始化怎麼做呢,可以採用如下辦法:

12
var array [5]intarray = [5]int{1,2,3,4,5}

這兩步比較繁瑣,Go為我們提供了:=操作符,可以讓我們在建立數組的時候直接初始化。

1
array:=[5]int{1,2,3,4,5}

這種簡短變數聲明的方式不僅適用於數組,還適用於任何資料類型,這也是Go語言中常用的方式。

有時候我們更懶,連數組的長度都不想指定,不過沒有關係,使用...代替就好了,Go會自動推匯出數組的長度。

1
array:=[...]int{1,2,3,4,5}

假如我們只想給索引為1和3的數組初始化相應的值,其他都為0怎麼做呢,直接的辦法有:

1
array:=[5]int{0,1,0,4,0}

還有一種更好的辦法,上面講預設初始化為零值,那麼我們就可以利用這個特性,只初始化索引1和3的值:

1
array:=[5]int{1:1,3:4}

使用數組

數組的訪問非常簡單,通過索引即可,操作符為[],因為記憶體是連續的,所以索引訪問的效率非常高。

12
array:=[5]int{1:1,3:4}fmt.Printf("%d",array[1])

修改數組中的一個元素也很簡單:

1234
array:=[5]int{1:1,3:4}fmt.Printf("%d\n",array[1])array[1] = 3fmt.Printf("%d\n",array[1])

如果我們要迴圈列印數組中的所有值,一個傳統的就是常用的for迴圈:

1234567
func main() {array := [5]int{1: 1, 3: 4}for i := 0; i < 5; i++ {fmt.Printf("索引:%d,值:%d\n", i, array[i])}}

不過大部分時候,我們都是使用for rang迴圈:

1234567
func main() {array := [5]int{1: 1, 3: 4}for i, v := range array {fmt.Printf("索引:%d,值:%d\n", i, v)}}

這兩段範例程式碼,輸出的結果是一樣的。

同樣類型的數組是可以相互賦值的,不同類型的不行,會編譯錯誤。那麼什麼是同樣類型的數組呢?Go語言規定,必須是長度一樣,並且每個元素的類型也一樣的數組,才是同樣類型的數組。

123
array := [5]int{1: 1, 3: 4}var array1 [5]int = array //successvar array2 [4]int = array1 //error

指標數組和數組本身差不多,只不過元素類型是指標。

1
array := [5]*int{1: new(int), 3:new(int)}

這樣就建立了一個指標數組,並且為索引1和3都建立了記憶體空間,其他索引是指標的零值nil,這時候我們要修改指標變數的值也很簡單,如下即可:

12
array := [5]*int{1: new(int), 3:new(int)}*array[1] = 1

以上需要注意的是,只可以給索引1和3賦值,因為只有它們分配了記憶體,才可以賦值,如果我們給索引0賦值,啟動並執行時候,會提示無效記憶體或者是一個nil指標引用。

1
panic: runtime error: invalid memory address or nil pointer dereference

要解決這個問題,我們要先給索引0分配記憶體,然後再進行賦值修改。

1234
array := [5]*int{1: new(int), 3:new(int)}array[0] =new(int)*array[0] = 2fmt.Println(*array[0])

函數間傳遞數組

在函數間傳遞變數時,總是以值的方式,如果變數是個數組,那麼就會整個複製,並傳遞給函數,如果數組非常大,比如長度100多萬,那麼這對記憶體是一個很大的開銷。

12345678910
func main() {array := [5]int{1: 2, 3:4}modify(array)fmt.Println(array)}func modify(a [5]int){a[1] =3fmt.Println(a)}

通過上面的例子,可以看到,數組是複製的,原來的數組沒有修改。我們這裡是5個長度的數組還好,如果有幾百萬怎麼辦,有一種辦法是傳遞數組的指標,這樣,複製的大小隻是一個數群組類型的指標大小。

12345678910
func main() {array := [5]int{1: 2, 3:4}modify(&array)fmt.Println(array)}func modify(a *[5]int){a[1] =3fmt.Println(*a)}

這是傳遞數組的指標的例子,會發現數組被修改了。所以這種情況雖然節省了複製的記憶體,但是要謹慎使用,因為一不小心,就會修改原數組,導致不必要的問題。

這裡注意,數組的指標和指標數組是兩個概念,數組的指標是*[5]int,指標數組是[5]*int,注意*的位置。

針對函數間傳遞數組的問題,比如複製問題,比如大小僵化問題,都有更好的解決辦法,這個就是切片,它更靈活,下一篇我們將詳細介紹。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.