溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言之數組

發布時間:2020-05-25 19:38:21 來源:網絡 閱讀:346 作者:baby神 欄目:編程語言

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


內部實現


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


數組存儲的類型可以是內置類型,比如整型或者字符串;也可以是自定義的數據結構。因為是連續的,所以索引比較好計算,所以我們可以很快地索引數組中的任何數據。


這里的索引,一直都是0、1、2、3這樣的,因為其元素類型相同。我們也可以使用反射,獲取類型占用大小,進行移位,獲取相應的元素。這部分在說到反射的時候,我們再講。


聲明和初始化


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


  1. 指明存儲數據的類型。

  2. 存儲元素的數量,也就是數組長度。


var array [5]int


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


數組一旦聲明后,其元素類型和大小都不能變了,如果還需要存儲更多的元素怎么辦?那么只能通過創建一個新的數組,然后把原來數組的數據復制過去。


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


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


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


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


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


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


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


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


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


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


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


使用數組


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


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


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


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


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


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循環:


func main() {
    array := [5]int{1: 1, 3: 4}

    for i, v := range array {
        fmt.Printf("索引:%d,值:%d\n", i, v)
    }
}


這兩段示例代碼,輸出的結果是一樣的。


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


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


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


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


這樣就創建了一個指針數組,并且為索引 1 和 3 都創建了內存空間,其他索引是指針的零值nil,這時候我們要修改指針變量的值也很簡單,如下即可:


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


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


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


要解決這個問題,我們要先給索引 0 分配內存,然后再進行賦值修改。


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


函數間傳遞數組


在函數間傳遞變量時,總是以值的方式。如果變量是個數組,那么就會整個復制,并傳遞給函數。如果數組非常大,比如長度 100 多萬,那么這對內存是一個很大的開銷。


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

func modify(a [5]int){
    a[1] =3
    fmt.Println(a)
}


通過上面的例子,可以看到,數組是復制的,原來的數組沒有修改。我們這里是 5 個長度的數組還好,如果有幾百萬怎么辦,有一種辦法是傳遞數組的指針,這樣,復制的大小只是一個數組類型的指針大小。


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

func modify(a *[5]int){
    a[1] =3
    fmt.Println(*a)
}


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


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


針對函數間傳遞數組的問題,比如復制問題,比如大小僵化問題,都有更好的解決辦法,這個就是切片,它更靈活


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女