第四章 符合資料型別
複合資料型別包括陣列,切片,map,結構體
陣列
陣列是一個由固定長度的特定型別的元素組成的序列,一個數組可以由零個或多個元素組成。
因為陣列的長度固定,所以golang中很少直接使用陣列,都是使用和陣列對應型別的slice 漢譯切片 它是可以增長和收縮的動態序列,slice功能也更靈活,但是要理解slice 工作原理的話首先需要理解陣列,因為slice就是基於陣列做片段化引用的這麼個東西
在陣列字面值中,如果在陣列長度位置出現“…” 省略號,則表示陣列的長度是按照初始化長度來計算的。陣列的長度是陣列型別的組成部分[3]int 不是一個型別[4]int!!
Slice
切片代表一個變長序列,序列中每一個元素都有相同的型別。一個slice型別一般寫作[]T,其中T代表slice中元素的型別;slice的預發和陣列很像,只是沒有固定長度而已。一個slice由三部分構成:指標,長度和容量,指標是指向第一個slice元素對應的底層陣列元素的地址,要注意的是slice的第一個元素不一定是陣列的第一個元素,長度對應slice中元素的數目;長度不能超過容量,容量一般是從slice開始位置到底層資料的結尾位置。內建的len和cap函式分別返回長度和容量。
翻轉陣列切片操作
func reverse(s []int){ for i,j:=0,len(s) -1;i<j;i,j = i+1,j-1{ s[i],s[j] = s[j],s[i] } }
slice不能像陣列一樣進行直接比較== != 因為本身切片是底層陣列的間接引用 位元組型別的切片可以呼叫bytes.Equal 函式進行判斷但是對於其他型別的就只能是迴圈range判斷每一個內容是否相同了。
func equal(x,y []string) bool{ if len(x)!=len(y){ return false } for i:=range x { if x[i] !=y[i]{ return false } } return true }
內建函式append 用於向切片中追加元素;
append函式的工作原理,1 判斷slice容量是否夠用,如果夠用,將元素新增到slice末尾,如果不夠用,那麼選取雙倍容量的地址,拷貝當前元素到該地址,然後將元素新增到末尾
Map
雜湊表是一種巧妙並且實用的資料結構。它是一個無序的key/value對的集合,其中所有的key都是不同的,然後通過給定的key可以在常數時間複雜度內檢索、更新或刪除對應的value零值nil 意思就是沒有引用任何雜湊表
在go語言中,一個map就是一個雜湊表的引用,map型別可以寫為map[K]V。key和value之間可以是不同的資料型別。KEY的資料型別必須是支援==比較運算子的資料型別 儘量不要使用浮點數來當key
map中的值並不是一個變數,所以我們不能對map做取地址操作,
_ = &ages['bob'] //錯誤。 compile error
禁止對map元素取址操作是因為map可能隨著元素數量的增長而重新分配更大的記憶體空間,從而導致之前的地址無效。
map的迭代順序是不確定的,並且不同的雜湊函式實現導致不同的遍歷順序。在實踐中,遍歷的順序是隨機的,每次遍歷都不一樣。
如果要按順序遍歷map,必須顯式地對key進行排序,下面是常用的排序處理方式:
import "sort" var names [] string for name :=range ages{ names = append(names,name) } sort.Strings(names) for _,name:=range names{ fmt.Printf("%s\t%d\n",name,ages[name]) }
直接向nil值的map存入元素會報異常,需要先建立一個map才可以存資料,make一下。可以使用
age,ok :=ages["bob"]
來判斷一個map的對應元素是否存在
結構體
結構體是一種聚合的資料型別。ofollow,noindex">定義
結構體的零值是指所有的成員都是零值
結構體初始化,可以選擇直接賦值
type Point struct{x,y int} p:=Point{1,2}
這種初始化最大缺點就是賦值順序不能亂,一般用於小結構體的初始化。
另一種為通過KEY賦值
anim := gif.GIF{LoopCount:nframe}
這種賦值不需要考慮順序問題。
結構體可以作為引數或者返回值傳遞於函式之間。通常較大的結構體通過指標傳遞。
json
go語言對於這些標準格式的編碼和解碼有良好的支援,由標準庫encodind/json、encoding/xml、encoding/asn1等支援。google通訊的protocol不常用,使用github.com/golang/protobuf包提供支援。
在go中只有可匯出的結構體成員才會被編碼,換言之,不可匯出的成員,轉化為json也是看不到的。json編碼函式為json.Marshal ,json.MarshalIndent函式將產生整齊縮排的輸出。UnMarshal函式進行解碼。
簡單的輸出printf就可以了,複雜的列印格式由text/template和html/template等模板包提供。它們提供了一個將變數值填充進文字或者HTML格式的模板的機制。模板通常在編譯時 就測試好了,如果模板解析失敗,將是致命錯誤,template.Must輔助函式可以簡化處理這類錯誤。