加 Golang學習 QQ群共同學習進步成家立業工作 ^-^ 群号:96933959
數組 Arrays
數組是同一種資料類型的固定長度的序列。
數組是值類型,是以改變副本的值,不會改變本身的值;
當作為方法的入參傳入時将複制一份數組而不是引用同一指針。
通過從0開始的下标索引通路元素值。
數組定義
var a []int
a = make([]int, 5)
var a1 [5]int = [5]int{1, 2, 3, 4, 5} //len:5 content:[1 2 3 4 5]
var a2 = [5]int{1, 2, 3, 4, 5} //len:5 content:[1 2 3 4 5]
var a3 = [...]int{1, 2, 3, 4, 5} //len:5 content:[1 2 3 4 5]
var a4 = [...]int{1: 100, 2: 200} //len:3 content:[0 100 200]
var a5 = [...]string{1: "nick", 2: "dawn"} //len:3 content:[ nick dawn]
數組定義後,長度不能變。
長度是數組類型的一部分,具有不同長度的數組,其類型是不同的。
是以,var a[5] int 和 var a[9]int 是不同的類型。
數組使用
通過下标通路,超出會報錯
arr := [5]int{1, 2, 3}
//fmt.Println(arr[5]) //報錯
通過for周遊數組元素
func main() {
arr := [5]int{1, 2, 3}
for i:=0; i<len(arr); i++ {
fmt.Println(arr[i]) //12300
}
for i,v := range arr{
fmt.Printf("index[%d]:content[%v]\n", i, v)
}
}
值類型數組指派,改變副本不會改變自身
func main() {
arr := [5]int{1, 2, 3}
arr2 := arr
arr2[0] = 10
fmt.Println(arr) //[1 2 3 0 0]
fmt.Println(arr2) //[10 2 3 0 0]
}

栗子(斐波那契數列)
二維數組
多元數組,二維數組舉例
var a1 [2][5]int
二維數組周遊
func main() {
var a1 [2][5]int = [...][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}
for row, v := range a1 {
for col, v1 := range v {
fmt.Printf("(%d,%d)=%d ", row, col, v1)
}
fmt.Println()
}
}
切片 Slices
切片是長度可變、容量固定的相同的元素序列。
切片是數組的一個引用,是以切片是引用類型。
是以在當傳遞切片時将引用同一指針,修改值将會影響其他的對象。
slice 與 array 接近,但是在新的元素加入的時候可以增加長度。slice 總是指向底層的一個 array。slice本身不是數組,slice 是一個指向 array的指針。
切片定義
建立切片跟建立數組唯一的差別在于 Type 前的“ [] ”中是否有數字,為空,則代表切片,否則則代表數組。
s1 := [] int{1, 2, 3} //直接初始化切片,[]表示是切片類型,初始化值依次是1,2,3.其cap=len=3
s2 := arr[:] //初始化切片s2,是數組arr的引用
s3 := arr[startIndex:endIndex] //将arr中從下标startIndex到endIndex-1下的元素建立為一個新的切片
s4 := arr[startIndex:] //預設endIndex時将表示一直到arr的最後一個元素
s5 := arr[:endIndex] //預設startIndex時将表示從arr的第一個元素開始
s6 := s1[startIndex:endIndex] //通過切片s6初始化切片截取s1
s7 := make([]int, len, cap) //通過内置函數make()初始化切片s,cap可以省略(省略時,值等同于len)
len() 與 cap()
長度是指已經被賦過值的最大下标+1,可通過内置函數len()獲得。
容量是指切片目前可容納的最多元素個數,可通過内置函數cap()獲得。
arr := [5]int{1, 2, 3}
fmt.Println(len(arr)) //5
fmt.Println(cap(arr)) //5
切片使用
周遊及修改
for i, v := range slice0 {
slice0[i] = strings.ToUpper(v)
fmt.Printf("index[%d]content[%s,%s]\n", i, v, slice0[i])
}
append 及 copy
append操作:slice可以在尾部追加元素,甚至還可以将一個slice追加到另一個slice的尾部,如果最終的長度沒有超過原始的slice,那麼append操作将傳回原來的slice,否則将重新配置設定記憶體位址。
copy操作:copy操作傳回複制的元素的個數,複制的數量是len(src)和len(dst)中最小的值。
slice := []int{1, 2}
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[2],content:[1 2]
slice = append(slice, 5, 6, 8, 9)
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9]
slicecp := make([]int, len(slice))
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9]
n := copy(slicecp, slice)
fmt.Printf("len[%d],content:%v, retN:%d\n", len(slice), slice, n) //len[6],content:[1 2 5 6 8 9], retN:6
slicecp[0] = 10
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9]
fmt.Printf("len[%d],content:%v\n", len(slicecp), slicecp) //len[6],content:[10 2 5 6 8 9]
sliceN := append(slice, slicecp...)
fmt.Printf("len[%d],content:%v\n", len(sliceN), sliceN) //len[12],content:[1 2 5 6 8 9 10 2 5 6 8 9]
值類型修改值會影響本身。
slice0 := []string{"a", "b", "c", "d", "e"}
slice1 := slice0
slice1[0] = "Nick"
fmt.Println(slice0) //[Nick b c d e]
fmt.Println(slice1) //[Nick b c d e]
記憶體布局與擴容
切片是引用類型,指針内部隻向一個數組。
代碼實作,記憶體位址表示是同一塊位址。
func main() {
var a []int = []int{1, 2, 3, 4, 5}
s := a[1:]
fmt.Printf("a=%p, s=%p \n", &(a[1]), s) //a=0xc420016188, s=0xc420016188
s = append(s, 10, 10, 10)
fmt.Printf("a=%p, s=%p \n", &a[1], s) //a=0xc420016188, s=0xc4200141c0
}
切片的長度是可變的,那自動擴容是怎樣的機制呢?
是 double(雙倍),看下面代碼。
func main() {
var a [5]int = [...]int{1, 2, 3, 4, 5}
s := a[1:]
fmt.Println(cap(s), len(s)) //4 4
s = append(s, 10, 10, 10)
fmt.Println(cap(s), len(s)) //8 7
s = append(s, 10)
fmt.Println(cap(s), len(s)) //8 8
s = append(s, 10)
fmt.Println(cap(s), len(s)) //16 9
s = append(s, 10, 10, 10, 10)
fmt.Println(cap(s), len(s)) //16 13
s = append(s, 10, 10, 10, 10, 10, 10)
fmt.Println(cap(s), len(s)) //32 19
}

模仿切片
map
map在Go語言中是作為一種内建類型存在。
key-value的資料結構,又叫字典或關聯數組。
map是引用類型。
map聲明是不會配置設定記憶體的,需要make初始化。
map聲明初始化
聲明
var a map[keytype]valuetype
var a map[string]string
var a map[string]int
var a map[int]string
var a map[string]map[string]string //嵌套
聲明并初始化
var a map[string]string
a = make(map[string]string, 10)
a := make(map[string]string, 10)
a := make(map[string]string)
var a map[string]string = map[string]string{}
var a map[string]string = map[string]string{
"A": "A", //注意是逗号
}
map 使用
增删改查
m["name"] = "Nick" // "create"
delete(m, "name") // "delete"
m["name"] = "Dawn" // "update"
name := m["name"] // "read"
讀取不異常
name, errbool := m["name"]
if !errbool {
m["name"] = "Nick"
}
二維map
func modify(a map[string]map[string]string) {
_, ok := a["name"]
if !ok {
a["name"] = make(map[string]string)
}
a["name"]["Nick"] = "suoning"
a["name"]["Nicky"] = "manyRou"
}
func testMap3() {
var a map[string]map[string]string
a = make(map[string]map[string]string, 10) //初始化一維
a["name"] = make(map[string]string) //初始化二維
modify(a)
fmt.Println(a)
}
slice of map
Items := make([]map[int][int], 5)
For i := 0; i < 5; i++ {
items[i] = make(map[int][int])
}
map 排序
- 先擷取所有key,把key進行排序
- 按照排序好的key,進行周遊
import "sort"
func testMapSort() {
var a map[int]int
a = make(map[int]int, 5)
a[8] = 10
a[5] = 10
a[2] = 10
a[1] = 10
a[9] = 10
var keys []int
for k, _ := range a {
keys = append(keys, k)
}
sort.Ints(keys)
for _, v := range keys {
fmt.Println(v, a[v])
}
}
map 反轉
初始化另外一個map,把key、value互換即可
func testMapSort1() {
var a map[string]int
var b map[int]string
a = make(map[string]int, 5)
b = make(map[int]string, 5)
a["name"] = 53
a["ege"] = 10
for k, v := range a {
b[v] = k
}
fmt.Println(b)
}