加 Golang學習 QQ羣共同窗習進步成家立業工做 ^-^ 羣號:96933959數組
數組是同一種數據類型的固定長度的序列。數據結構
數組是值類型,所以改變副本的值,不會改變自己的值;app
看成爲方法的入參傳入時將複製一份數組而不是引用同一指針。ide
經過從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 是不一樣的類型。spa
經過下標訪問,超出會報錯指針
arr := [5]int{1, 2, 3} //fmt.Println(arr[5]) //報錯
經過for遍歷數組元素code
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] }
package main import ( "fmt" ) func test1(n int) { var a []int a = make([]int, n) a[0] = 1 a[1] = 1 for i := 2; i < n; i++ { a[i] = a[i-1] + a[i-2] } for _, v := range a { fmt.Println(v) } } func main() { test1(10) }
多維數組,二維數組舉例
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() } }
切片是長度可變、容量固定的相同的元素序列。
切片是數組的一個引用,所以切片是引用類型。
所以在當傳遞切片時將引用同一指針,修改值將會影響其餘的對象。
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 }
package main import ( "fmt" ) type slice struct { pre *[100]int len int cap int } func make1(s slice, cap int) slice { s.pre = new([100]int) s.len = 0 s.cap = cap return s } func modify(s slice) { s.pre[1] = 1000 } func testSlice() { var s1 slice s1 = make1(s1, 10) s1.pre[0] = 100 modify(s1) fmt.Println(s1.pre) } func main() { testSlice() }
map在Go語言中是做爲一種內建類型存在。
key-value的數據結構,又叫字典或關聯數組。
map是引用類型。
map聲明是不會分配內存的,須要make初始化。
聲明
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", //注意是逗號 }
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" }
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) }
Items := make([]map[int][int], 5) For i := 0; i < 5; i++ { items[i] = make(map[int][int]) }
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,把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) }