1. 程式人生 > 其它 >21天從Java轉向Go之第五天——水滴石穿(複合資料型別)

21天從Java轉向Go之第五天——水滴石穿(複合資料型別)

複合資料型別

  • 複合資料型別是由基本資料型別以各種方式組合而構成的。這章重點講解四種複合資料型別。分別是陣列、slice、map和結構體。

  • 陣列和結構體都是聚合型別。它們的值由記憶體中的一組變數構成。陣列的元素具有相同的型別。而結構體中的元素資料型別則可以不同。陣列和結構體的長度是固定的。而slice和map都是動態資料結構,它們的長度在元素新增到結構中時可以動態增長。

陣列



package main

import (
"fmt"
"reflect"
)

var array [3]int

type currency int
const (
RMB currency = iota
EUR
USD
)

func main() {
array[0] = 22
array[1] = 33
array[2] = 44

fmt.Println(array) //[22 33 44]
for i, v := range array {
fmt.Println(i, v)
//0 22
//1 33
//2 44
}
for _, v := range array {
fmt.Println(v) //22 33 44
}

//slice
arr2:= []int{1,2,3}
fmt.Println(reflect.TypeOf(arr2))
fmt.Printf("arr2型別:%T\n",arr2)

arr3:= [3]int{1,2,3}
fmt.Println(reflect.TypeOf(arr3))
fmt.Println(arr3)

arr4:= [...]int{1,2,3}
fmt.Println(reflect.TypeOf(arr4))
fmt.Println(arr3 == arr4) //true 陣列型別,長度相同才能比較
fmt.Println(&arr3 == &arr4) //false

money := [...]currency{RMB:8,USD:9,EUR:10}
fmt.Println(money)
for i, c := range money {
fmt.Println(i,c)
}

//可以指定索引位置的元素值,其他位置是零值
arr5:= [...]string{"11",10:"ssss","22"}
fmt.Println(arr5)

b:= [...]byte{1,2,3}
zeroClear2(&b)
fmt.Println("After zeroClear:",b)
}

func zeroClear(p *[3]byte) {
for i := range p {
p[i] = 0
}
}

func zeroClear2(p *[3]byte) {
*p = [3]byte{}
}

slice

  • slice表示一個擁有相同型別元素的可變長度的序列。slice通常寫作[]T,看上去像沒有指定長度的陣列。

  • slice是一種輕量級的資料結構,可以用來訪問陣列的部分或全部的元素,而這個陣列被稱為slice的底層陣列。

  • slice有三個屬性:指標、長度和容量。指標指向陣列的第一個可以從slice訪問的元素,這個元素並不一定是陣列的第一個元素。長度是指slice中元素的個數,不能超過slice的容量。容量的大小通常是從slice的起始元素到底層陣列的最後一個元素間元素的個數。

  • Go的內建函式len和cap用來返回slice的長度和容量。

  • 因為slice包含了指向陣列的指標,因此在函式傳遞引數時,函式內做的修改會影響到slice指向的底層陣列。

  • 對一個切片再次slice[m:n]運算時,是對slice的指向的底層陣列再計算(再切片運算)。slice[i]訪問slice切片的第i個位置的元素,slice[:n] 如果n大於slice指向底層陣列的容量cap,會導致程式宕機。如果大於len(slice)小於cap(slice),則會擴容slice



package main

import (
"fmt"
)

var arr = [...]int{1,2,3,4,5,6,7,8,9}

func main() {
slice1 := arr[1:4]
fmt.Println("slice1的len和cap分別是",len(slice1),cap(slice1)) //slice1的len和cap分別是 3 8
fmt.Println("slice1:",slice1) //slice1: [2 3 4]
slice2 := arr[2:8]
fmt.Println("slice1的len和cap分別是",len(slice2),cap(slice2)) //slice1的len和cap分別是 6 7
fmt.Println("slice2:",slice2) //slice2: [3 4 5 6 7 8]
slice2[1] = 1//slice陣列修改影響其他共用的底層陣列
fmt.Println("slice2:",slice2) //slice2: [3 1 5 6 7 8]
fmt.Println("slice1:",slice1) //[2 3 1]

//slice指向底層陣列切片
slice2 = slice2[:3]
fmt.Println(slice2) //[3 1 5] 縮容

slice2 = slice2[:7]
fmt.Println(slice2) //[3 1 5 6 7 8 9] 擴容
//slice2 = slice2[:8] //panic: runtime error: slice bounds out of range [:8] with capacity 7
fmt.Println(slice2) //[3 1 5]

//make函式
//指定長度 容量不指定預設和長度相同
ints := make([]int, 2)
//分別指定len和cap
ints2 := make([]int, 2,5)
fmt.Println(ints) //[0 0]
fmt.Println("ints","len:",len(ints),",cap:",cap(ints)) //ints len: 2 ,cap: 2
fmt.Println("ints2","len:",len(ints2),",cap:",cap(ints2)) //ints2 len: 2 ,cap: 5

//append函式 自動擴容
ints = append(ints, 1)
fmt.Println(ints) //[0 0 1]
fmt.Println(len(ints), cap(ints)) // 3 4

ints = append(ints, 1)
fmt.Println(ints) //[0 0 1 1]
fmt.Println(len(ints), cap(ints)) // 4 4

ints = append(ints, 1)
fmt.Println(ints)//[0 0 1 1 1]
fmt.Println(len(ints), cap(ints)) //5 8
//coupy函式 src複製到dst切片
i := copy(ints, arr[0:4])
fmt.Println("copy length:",i)
fmt.Println("ints:",ints)
}


map

  • map[K]V K是和V是字典鍵和值對應的資料型別,鍵的型別必須是通過==可以判斷的資料型別(切片不可以)。

  • 內建函式make可以用來初始化一個map



package main

import (
"fmt"
"sort"
)

var hashmap = make(map[int]string)

func main() {
hashmap[1] = "1"
hashmap[2] = "2"
hashmap[3] = "3"
hashmap[4] = "4"
hashmap[5] = "5"
fmt.Println(hashmap)

//使用字面量初始化map
m := map[int]string{1: "22", 2: "222", 3: "2222"}
fmt.Println(m)

//移除元素delete
delete(hashmap, 12)
fmt.Println(hashmap)
//賦值
hashmap[1] += "呢哇 1"
fmt.Println(hashmap)
//無法獲取map某元素的地址值 因為map是動態的 獲取到的地址可能已經變成其他元素了
//s := &hashmap[1]
m2 := &hashmap
fmt.Println(m2)
//遍歷
for k, v := range hashmap {
fmt.Println(k, v)
}

//按k的順序遍歷map
keys := make([]int, 0, len(hashmap))
for k := range hashmap {
keys = append(keys, k)
}
sort.Ints(keys)
for _, key := range keys {
v := hashmap[key]
fmt.Println("按k的順序排序:v=", v)
}

newMap := make(map[string]string)
newMap["sss"] = "sss"
fmt.Println(newMap)

//panic: assignment to entry in nil map
//var newMap2 map[string]string
//newMap2["sss"] = "ssss"
//fmt.Println(newMap2)

if _, ok := newMap["ssss"]; !ok {
fmt.Println("not exist ele","ssss")
}


}

結構體



package main

import (
"encoding/json"
"fmt"
)

type Man struct {
h Human
sex, gender int
Human
Hello string `json:"Hello"`
}

type Human struct {
Age int
height float32
}

func main() {
v := new(Man)
v.sex = 1
v.h.height = 177.11
v.h.Age = 28
v.Age = 30
v.height = 188
v.gender = 1
fmt.Println(*v)

man := Man{h: Human{Age: 28, height: 177.11}, sex: 1, gender: 1, Human: Human{Age: 100, height: 100.00}}
fmt.Println(man)
//結構體的比較 成員變數都可比較才能比較
fmt.Println(man == *v)
man = *v
fmt.Println(man)

marshal, err := json.Marshal(*v)
fmt.Println(err)
fmt.Printf("%s\n", marshal)

x := "{\"Hello\":\"111\"}"
v2 := new(Man)
json.Unmarshal([]byte(x), v2)
fmt.Printf("%#v",v2)

}