Go核心語言編程 - 復合數(shù)據(jù)類型(3)

Go對應的復合數(shù)據(jù)類型有數(shù)組,字典,指針,切片,通道,結構和結構,他們字面類型如下:

[n] elementType //數(shù)組
map [keyType]valueType //字典
* pointerType //指針
[] elementType //切片
chan valueType //通道
struct {
    fieldType fieldType
}
interface {
    method1(inputParams)(returnParams)
}

? 指針

var a = 11
p := &a
type User struct{
    name string
    age int
}
andes := User{
    name: "andes",
    age: 18,
}
p := &andes
fmt.Println(p.name)
// Go不支持指針運算
a := 1234
p := &a
p++ //不允許,error
//函數(shù)中允許返回局部變量地址
func sum (a, b int) *int {
    sum := a + b
    return &sum //允許,sum會被分配在heap上
}

? 數(shù)組
? 數(shù)組初始化

var arr [2]int //聲明
array := [...]float64{7.0, 8.0}
a := [3]int{1, 2, 3} //指定長度初始化
b := [...]int{4, 5, 7} //不指定長度初始化
c := [3]int{1:1, 2:3} //指定長度,通過索引值初始化
d := [...]int{1:1, 2:3} //不指定長度,通過索引值初始化

? 數(shù)組特點
? 數(shù)組長度一旦創(chuàng)建就固定了,不可以追加元素
? 數(shù)組是值類型,數(shù)組賦值或者作為函數(shù)參數(shù)都是值拷貝

a1 := [3]int{1, 2, 3}
a2 := a1
a2[0] = 11 //這里拷貝了一份
fmt.Println(a1) //[1, 2, 3]
fmt.Println(a2) // [11, 2, 3] 

? 數(shù)組長度是數(shù)組類型的組成部分,[10]int和[20]int表示不同類型
? 可以根據(jù)數(shù)組創(chuàng)建切片
? 數(shù)組長度: len(array)
? 數(shù)組遍歷

a := [...]int{1, 2, 3}
b := a[0]
// 類似python遍歷
for i,v := range a {
    fmt.Printlb(i)
}
alength := len(a)
for i:=0, i<alength; i++ {
    
}

? 切片
因為Go的數(shù)組的長度定長和值拷貝限制了使用場景,Go提供了slice,這是一種可變數(shù)組

// src/runtime/slice.go
type slice struct {
    array unsafe.Pointer
    len int
    cap int
}

? 切片的創(chuàng)建
? 根據(jù)數(shù)組創(chuàng)建

// 創(chuàng)建語法array[a:b] 左邊包含,右邊不包含
var array = [...]int{1, 2, 3}
s1 := array[0:4]

? 根據(jù)內(nèi)置函數(shù)make創(chuàng)建切片

// len=10, cap=10
a := make([]int, 10)
// len=10, cap=15
a := make([]int, 10, 15)

? 切片的操作
? len()返回長度
? cap()返回容量
? append()追加元素
? copy()復制一個切片

a := [...]int{0, 1, 2, 3, 4}
b := make([]int, 2, 4)
c := a[0:3]
fmt.Println(len(b)) //2
fmt.Println(cap(b)) //4
b = append(b, 1)
fmt.Println(b) // [0, 0, 1]
fmt.Println(b) // 3
b = append(b, c)
fmt.Println(b) //[0, 0, 1, 0, 1, 2]
fmt.Println(len(b)) //6
fmt.Println(cap(b)) // 8, 底層數(shù)組發(fā)生自動擴展
d := make([]int, 2, 2)
copy(d, c) //復制d和c長度最小的
fmt.Println(d) // [0, 1]
fmt.Println(len(d)) // 2
fmt.Println(cap(d)) // 2

? map
map[K]T,K必須是任意可以比較的類型,T是值類型,map是一種引用類型
? 創(chuàng)建Map
? 直接創(chuàng)建

dict := map[string]string{"a": "a1", "b": "b1"}
fmt.Println(dict["a"])

? 使用make函數(shù)創(chuàng)建

dict1 := make(map[int]int)
dict2 := make(map[int]int, 10) //初始化容量是10
dict1[1]=1
dict2[1]=1

? map標準操作

d1 := make(map[string]string, 10)
// 1. 賦值
d1["name"] = "chs"
// 2. 訪問值
fmt.Println(d1["name"])
// 3. range遍歷, 但是不能保證每次遍歷的順序是一樣的
for k, v := range mp {
    fmt.Println("k=", k, "v=", v)
}
// 4. 刪除值
delete(d1, "name")

? map特殊操作
Go內(nèi)置的map不是并發(fā)安全的
// 如果map的value是一個復合對象,當修改復合對象的值時候,需要整體替換這個復合對象

type User struct {
    name string,
    arg int,
}
dict := make(map[string]User)
user := User{
    name: "chs",
    age: 18,
}
dict["chs"] = user
// dict["chs"].age = 29 //錯誤
user.age = 29
dict["chs"] = user //整體替換value

? struct
結構的類型可以是任意類型,而且它的存儲空間是連續(xù)的,其中字段按照聲明的順序存放
struct的有兩種形式:
? struct類型的字面量

struct {
    FieldName FieldType,
    FieldName FieldType,
}

? 自定義struct類型

type TypeName struct {
    FieldName FieldType,
    FieldName FieldType,
}

struct字面量用的不是很多,大多使用自定義類型的struct類型
? struct類型變量的初始化

package main
import "fmt"
type Person struct {
    name string
    age int
}
type Student struct {
    *Person
    number int
}
func main() {
    p := &Person{
        name: "chs",
        age: 28,
    }
    s := Student{
        Person: p,
        number: 110,
    }
    fmt.Println(s.age) //這里Student通過struct間接繼承了Person
}

參考<<Go語言核心編程>>

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。