複合數據類型

複合數據類型

主要內容

  1. 重點介紹以下四種常用複合數據類型:

    • 數組
    • slice
    • map
    • 結構體

    數組和結構體的長度是固定的;slice和map都是動態數據結構,它們的長度在元素添加到結構體中時可以動態增長

  2. 使用這些數據類型構成的結構化數據編碼爲json數據,從json數據轉換爲結構化數據

數組

數組是一個由固定長度且多個相同數據類型元素的序列。因此,無法添加或者刪除元素。

聲明方式:

// 第一種聲明,初始化方式
var q [3]int = [3]int{1, 2, 3}

// 第二種:...表示數組的長度由初始化元素的個數決定
q := [...]int{1, 2, 3}

數組的長度也是數組類型的一部分

// [3]int和[4]int是兩種不同的數組類型
q := [3]int{1, 2, 3}
// 編譯報錯,理由如上
q = [4]int{1, 2, 3, 4} 

數組初始化:

// 初始化索引的順序是無關緊要的
type Currency int
const (
    USD Currency = iota // 美元
    EUR // 歐元
    GBP // 英鎊
    RMB // 人民幣
) 
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}
fmt.Println(RMB, symbol[RMB])

// 定義了一個含有100個元素的數組r,最後一個元素被初始化爲-1,其它元素都是用0初始化。
r := [...]int{99: -1}

數組間的比較:數組類型和元素類型確定能不能比較;元素相等決定數組相等

a := [2]int{1, 2}
b := [...]int{1, 2}
c := [2]int{1, 3}
// a與b數組類型相同,元素類型相同,可比較
// a與b的各個元素相等,則a與b相等
// a與c,b與c,數組類型相同,元素類型相同,元素不相等
fmt.Println(a == b, a == c, b == c) // "true false false"
d := [3]int{1, 2}
// 編譯錯誤,數組類型不同,不能比較
fmt.Println(a == d) 

函數調用參數傳遞:Go把數組和其他的類型都看成值傳遞,而在其他語言中,數組是隱式的使用引用傳遞

顯式地傳入一個數組指針,那樣的話函數通過指針對數組的任何修改都可以直接反饋到調用者。

func zero(ptr *[32]byte) {
    //  ptr是指針變量,使用range只返回一個索引?
    for i := range ptr {
        // 將ptr數組清零
        ptr[i] = 0
    }
}

// 另一種清零寫法
func zero(ptr *[32]byte) {
    // [32]byte{}生成一個有你32字節元素的數組
    // 數組中每個元素的值是字節類型的零值,即0.
    // 
    *ptr = [32]byte{}
}

使用指針:1.高效。 2.允許被調函數修改調用方數組中的元素。

slice

Slice(切片)代表變長的序列,序列中每個元素都有相同的類型。

slice的底層是數組,一個底層數組可以對應多個slice。
months是底層數組,Q2和summer是slice。
image

slice 屬性:

- 指針:指向第一個slice元素對應的底層數組元素的地址,要注意的是slice的第一個元素並不一定就是數組的第一個元素
- 長度:slice中元素的個數
- 容量:一般是從slice的**開始位置**到**底層數據的結尾位置**

slice操作符:左閉右開

// s即序列或底層數組。引用了s的i到j-1索引位置的元素
// 切片長度爲:j-i
s[i:j]
// 引用了s的位置i到最後一個索引的元素
s[i:]
// 引用了s從0到j-1索引的元素。
s[:j]
// 引用整個數組
s[:]

引用異常:panic異常和slice擴容

// 根據上圖的顯示,months有13個元素。
// 初始化時,使用了 索引號:值的方式初始化。
months := [...]string{1: "January", /* ... */, 12: "December"}
// summer引用了months數組的6-8的元素。
// 其中指針指向6,長度爲3,容量爲7(指針開始位置爲6,底層數組的結束位置爲12.)
summer := months[6:9]
// panic 異常,引用超過了被引用對象summer的容量。導致宕機
fmt.Println(summer[:20]) 
// endlessSummer的引用超出了被引用對象summer的長度3。
// 因此endlessSummer**長度**會擴展到5.應用也會變爲
// 從6-11
endlessSummer := summer[:5] 

數組與slice初始化一點區別:

// 數組有固定長度
a := [...]int {0,1,2,3,4,5}
// slice無固定長度
s := []int{0,1,2,3,4,5}

slice無法直接使用==做比較:slice的元素是非直接的,它可以包含自身;底層數組元素改變,同一個slice在不同的時間會有不同的元素。

slice允許的比較操作:和nil比較。

檢查slice爲空:使用len(s) == 0,而非 s==nil

make創建slie:

// 長度和容量相等
make([]T, len)
// 指定長度和容量
make([]T, len, cap)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章