Golang 基礎語法-高級數據類型(3)

Golang 基礎語法-高級數據類型(3)

本文主要介紹 golang 內置數據類型的 array, slice, map。這幾種數據類型在平常使用中是很是常見的。java

array

定義語法以下:
var arr [n]type
其中 arr 是數組變量的名稱(標識符), [n]type 表示這個數組是類型爲 type 且長度爲 n 的數組(type 能夠是任何基本類型,也能夠是任何自定義類型)
//實例演示
var arr [10]int //定義一個長度爲10的 int 類型的數組
arr[0] = 42 //array 數組下標是從0開始的,給數組第一個元素賦值42
arr[1] = 13//給數組第二個元素賦值13
//打印數組第一個元素
fmt.Printf("數組 arr 第一個元素是 %d\n", arr[0])
//打印數組最後一個元素,arr[9]由於沒有初始化,輸出 int 類型的零值 0
fmt.Printf("數組 arr 最後一個元素是 %d\n", arr[9])
定義數組的時候,能夠把[n]type 看作一個完整的類型,舉個例子,[3]int 和 [4]int 能夠認爲是不一樣的數據類型,數組的長度也是不可修改的

當把一個 array類型的數據做爲函數參數傳遞的時候,傳遞的是 array 的copy(拷貝值)而不是引用python

/**
 * 數組是值傳遞而非引用傳遞
 */
func test(arr [4]int) int {
    var sum int
    for i, v := range arr {
        sum = sum + v
        arr[i] = sum
    }
    //打印結果是[1 3 7 12]
    fmt.Printf("%+v\n", arr)
    return sum
}
func main() {
    arr := [4]int{1, 2, 4, 5}
    //打印結果 12
    fmt.Printf("%d\n", test(arr))
    //打印結果[1 2 4 5],把 arr 傳遞給 test函數,且函數內修改了數組,沒有影響原數組,證實數組在函數參數中是傳遞 copy而不是引用
    fmt.Printf("%v\n", arr)
}
//快捷方式定義數組
arr := [3]int{1, 2, 3}
//使用 ...替代長度讓編譯器自動計算數組的長度
arr1 := [...]int{3, 5, 5}
//二維數組
darr :=[2][3]int{[3]int{1,2,3}, [3]int{33,33,33}}
darr1 := [2][3]int{{2, 3, 4}, {1, 3, 4}}

slice(切片或者變長數組)

數組在一開始的時候,就要知道它的長度,然而不少時候咱們並不能肯定數組的大小,須要一種 "動態數組".在 golang 中 slice 爲咱們提供了這種可能。golang

slice 的定義和 array 很是相近,區別就是不用設置 n
語法 var slice[]int

說明:以上語法定義了一個 int 類型的 slice,數組

//實例說明
//定義一個byte 類型的 slice,注意 byte 是uint8的別名,byte類型的 slice中,若是元素賦值爲漢字超出 uint8的範圍就會報錯
slice := []byte{'a', 'b', 'c'}
slice 能夠從已經存在的數組(array)或者切片(slice)從新定義一個切片,語法格式爲[i:j], i 是開始的索引,j 是結束的索引,可是最終的 slice 不包含 j 這個元素
//實例演示
var ar = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
var a, b []byte
//變量a 實際上的內容爲 c,d,e 且 a 和 ar 共用底層數據
a = ar[2:5]
//變量 b 實際上的內容爲 d,e 且 b 和 ar 共用底層數據
b = ar[3:5]
//思考以下結果是什麼?
ar[4] = 'x'
fmt.Printf("%c\n", ar[4])//顯然是 x
fmt.Printf("%c\n", a[2])//a[2]實際上指向的是 ar[4],結果是 x
fmt.Printf("%c\n", b[1])//b[1]實際上指向的是 ar[4],結果是 x
ar[:n] 等價於 ar[0:n]
ar[n:] 等價於 ar[n:len(ar)]
ar[:] 等價於 ar[0:len(ar)]
//實例演示
var arr = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}

var aSlice, bSlie []byte
aSlice = arr[:3] // a b c
aSlice = arr[5:] //f g h i j
aSlice = arr[:] // a b c d e f g h i j
aSlice = arr[3:7] // d e f g, 長度 len=4, 容量 cap=10-3
bSlice = aSlice[1:3] // e f

slice 是引用類型,所以任何改變都會影響指向同一個 slice的其餘 slice 或 數組。數據結構

slice 相似於結構體,包涵了下面三個部分app

  • 一個指針:指向 slice 的起始地址
  • slice 的長度 int 類型
  • slice 的容量 int 類型

有一些內置函數能夠操做 slice函數

  • len 獲取 slice的長度
  • cap 獲取 slice 的最大容量
  • append 追加一個或者多個 slice 到slice
  • copy 複製一個 slice 的全部元素到另一個 slice,返回複製元素的個數

map

Map是一種鍵值對數據結構,相似python 中的字典。定義語法以下:ui

map[keyType]valueType

slice 中索引只能是 int,在 map 中 key能夠是 int string 等任何你想要的類型指針

實例演示以下code

//使用 string 類型的 key,int類型的 value,可使用 make 初始化
var numbers map[string]int
//定義而且使用 make 初始化
numbers := make(map[string]int)
//初始化後能夠賦值
numbers["one"] = 1
numbers["two"] = 2
numbers["three"] = 3
//獲取 map 某個 key 的 value
fmt.Println(numbers["three"])

map 須要注意

  • map是無序的,每次打印顯示的結果可能都是不同的,只能使用 key 獲取 value
  • map 沒有固定的長度,它是一種引用型變量
  • len函數能夠用於獲取 map 的長度,返回 map 有多少個 key
  • 經過 key改變 map 的 value 很是容易 只須要 使用相似m["k"] = 1的語法修改
//定義而且初始化 map
rating := map[string]float32 {"C":5, "Go":4.5, "PHP":100}
javaRating, ok := rating["Java"]
if ok {
    //do something
}else{
    //do something
}
//刪除 map 中的某個鍵值對
delete(rating, "C")

m := make(map[string]string)
m["hello"] = "world"
m1 := m
m1["hello"] = "girl" //m["hello"]的值也是 girl,由於底層指向數據一致

make 和 new 的區別

make 是 go 內置的一個方法,用於爲 map,slice,channel 等內置類型分配內存,new能夠爲全部類型分配
new(T)給 T 分配零值內存,返回零值的內存地址,其實就是 *T,更詳細的說,就是返回一個指針,指針指向的是 T 的零值

new 返回指針

make 主要用於 slice map channel,返回初始化後的 T。緣由在於 map slice channel底層的數據必須在初始化後才能指向他們。舉個例子,slice 包涵了一個指針,這個指針實際指向的是另一個結構(包涵指針 長度 容量),在這些數據初始化以前 slice 是 nil,所以 slice,map,channel使用 make爲他們底層的數據結構賦值合適的初始值

make 返回 非零值

個人博客即將同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/dev...

相關文章
相關標籤/搜索