Go語言學習筆記(三)數組 & 切片 & map

加 Golang學習 QQ羣共同窗習進步成家立業工做 ^-^ 羣號:96933959數組

數組 Arrays

數組是同一種數據類型的固定長度的序列。數據結構

數組是值類型,所以改變副本的值,不會改變自己的值;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()
    }
}

 

切片 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
}
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

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 排序

  1. 先獲取全部key,把key進行排序
  2.  按照排序好的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)
}
相關文章
相關標籤/搜索