Go語言學習筆記(三)複合數據類型

Go語言中有四種複合數據類型:數組,slice,map,結構體

數組和結構體都是聚合類型,長度固定。而slice和map都是動態數據結構,長度可變。

1. 數組

var arrName  [len]T

arrName := [...]int{1, 2, 3}

arrName是數組的名字,len是數組的長度,需要時常量,在編譯時確定。T是數組元素的類型。

長度也可以通過初始化元素個數決定,這時,len部分使用"..."代替。

如果數組元素是可比較的,那麼數組也是可比較的。但只能是同類型的數組才能比較,否則編譯錯誤。

%t -  輸出一個bool值,%T - 輸出一個變量的類型。

****** 數組是按值傳遞的,但可以通過傳遞一個數組指針。


2.slice

表示一個擁有相同類型元素的可變長度序列:[]T,看上去像沒有長度的數組類型。

slice有三個屬性:指針,長度,容量, len, cap

一個底層數組可以對應多個slice,而且這些slice之間也可以重疊。

可以通過子串生成操作,從數組或者slice得到slice,訪問容量外的元素,會導致宕機錯誤。

創建一個數組的slice,等於爲數組創建了一個別名。

和數組不同,slice無法做比較,因此不能用 == 在測試兩個slice是否擁有相同的元素。標準庫裏面提供了高度優化的bytes.Equal來比較兩個字節slice ([]byte),但對於其他類型,則需要我們自己寫函數來比較。

slice只能與nil做比較,slice不能作爲map的key。

對於可能修改slice屬性的函數,一般都返回 修改後的slice,規則是:將函數返回值賦值給此前的slice。 xs = append(xs, y)

copy函數也很常用。


slice並不是純引用類型,而是像下面這種聚合類型:

type IntSlice struct {

  ptr             *int

  len, cap     int

}

對於下面的列子:

func modifySlice(s []int) {

  s[0] = 0

}

func appendSlice(s []int) {

  s = append(s, 4)

}

func main() {

  s := []int { 1, 2, 3 }

  fmt.Println(s) // [1,2,3]

  modifySlice(s) // [0,2,3], 雖然ptr是傳值的,但其是指針,可以修改其所指地址的內容,當然這裏要在len的範圍內。

  appendSlice(s) // [0,2,3], ptr,len, cap都是傳值的,雖然在函數裏面len發生了變化,ptr, cap是否發生變化不定,但當其返回這裏時,ptr, len, cap都不可能變化,因此s沒有變化

}

注意:Go語言中的參數,都是按值傳遞。


3. map

GO語言中的map是散列表的引用,map[K]V,其中K類型,必須可以通過 == 進行比較,雖然浮點數也可以,但不是一個好主意。

可以用make來創建一個map:ages := make( map[string]int ) 或者

ages := map[string]int {

  "alice":31,

  "charlie":34,

}

可以使用delete函數從map中刪除一個元素。 delete(ages, "alice")

但是map元素不是一個變量,不可以獲取它的地址。因爲map是動態變化的。

對於nil的map,可以查找,刪除,獲取元素個數,但是設置操作會導致錯誤。設置元素前,必須初始化map。

和slice一樣,map也是不可比較的,唯一合法的就是和nil做比較。

map可以實現集合類型,map[T]bool

unicode.ReplacementChar 就是解析Unicode編碼遇到不合法的UTF-8字符時,返回的值。

map值類型本身可以是複合類型:map[string]map[string]bool


4.結構體

type Name struct {

  ID int

  Name string

  ManagerID int

}

可以通過點號訪問起成員,點號也適用於結構體指針,和C語言不一樣,不需要 ->

結構體定義中不可以包含自己,但可以包含本身的指針,這樣可以構造鏈表,樹等結構。

沒有任何成員的結構體稱爲空結構體,寫作 struct {}。他沒有長度,也不攜帶任何信息。

其成員是否可以導出,看其名字的首字母是否大寫。

在Go這種按值調用的語言中,調用函數接收到的是實參的一個副本,並不是實參的引用。

Go允許我們定義不帶名稱的結構體成員,只需要制定類型即可;這種結構體成員稱爲匿名成員。這個結構體成員的類型必須是一個命名類型或者指向命名類型的指針。

type Point struct {

  X, Y   int

}

type Circle struct {

  Point

  Radius  int

}

var circle Circle

circle.X = 5


以快捷方式訪問匿名成員的內部變量,同樣適用於訪問匿名成員的內部方法。因此,外圍的結構體類型獲取的不僅是匿名成員的內部變量,還有相關的方法。這個機制就是從簡單類型對象組合成複合類型對象的主要方式。 - 在Go中,組合是面向對象編程方式的核心。


5.JSON

JavaScript對象表示法(JSON)是一種發送和接收格式化信息的標準。其它標準還有:XML,ASN.1,Google的ProtocolBuffer。

JSON基本類型:數字、布爾值、字符串。

基礎類型可以通過JSON的數組和對象進行組合。

JSON數組是一個有序的元素序列,每個元素之間使用逗號分割,兩邊使用方括號括起來。 - 數組,slice

JSON對象是一個從字符串到值的映射,寫成name:value對的序列,每個元素之間用逗號分割,兩邊使用花括號括起來。 - map,結構體

例子:

boolean true

number -234.23

string "She said \"Hello, 世界\""

array [“gold”, "silver", "bronze"]

object { "year":1980,

                           "event":"archery"

                            "medals":[“gold”, "silver", "bronze"]

                         }


json包的Marshal和UnMarshal對數據進行json封包和解包。

而MarshalIndent可以格式化結果成可讀的形式。包括前綴字符串和縮進字符串。


Marshal使用Go結構體成員名稱作爲JSON對象裏面字段的名稱,只有可導出的成員可以轉換爲JSON字段。


標籤定義:由一串由空格分開的標籤鍵值對key:"value"組成的。value在雙引號內,因此是原生的字符串字面量。

json鍵控制encoding/json的行爲。

例子:

type Movie struct {

  Title string

  Year int `json:"released"`

  Color bool`json:"color,omitempty"`

  Actors []string

}

Year在json對象中的名稱是released

Color在json對象中的名稱是color,且如果其值爲零或者爲空,則不輸出到JSON對象中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章