数组+切片+map

数组

  • 数组是同一种数据类型固定长度的序列

  • 数组定义:var a [len]int,比如:var a [6]int,长度一旦定义不能改变

  • 长度是数组类型的一部分,因此,var a [5]int 和 var a [10]int 是不同的类型

  • 数组可以通过下标进行访问,下标是从0 开始,最后一个元素的下标是len - 1

  • 访问越界:如果下标在数组合法范围之外,则会触发访问越界,会panic

  • 数组是值类型,因此改变副本的值,不会改变本身的值

arr2 := arr1
arr2[2] = 10   // 不会改变arr1

长度不等的数组类型不等

func test(arr [5]int) {
    arr[0] = 1
}

func mian() {
    var a [10]int
    test(a)   // error
}

通过函数修改数组的值

因为数组是值类型,所以传到函数中是副本,因此要在函数中修改数组的值需要将数组的地址传入

func test(arr *[5]int) {
    (*arr)[0] = 10
}

func main() {
    var a [5]int
    test(&a)
}

数组初始化

// part1
var arg0 [5]int = [5]int{1, 2, 3, 4, 5}
// part2
var arg1 = [5]int{1, 2, 3, 4, 5}
// part3
var arg2 = [...]int{1, 2, 3, 4, 5}
// part4
var str = [5]string{3: "hello world", 4: "tom"}  // 0 1 2 是空的,稀疏数组

多维数组

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

遍历多维数组

for index, v := range f {    // 每一行
    for index1, v1 := range v {   // 每一列
        // do some operation
    }
}

切片

  • 切片是数组的一个引用,因此切片是引用类型

  • 切片的长度可以改变,因此,切片是一个可变的数组

  • 切片遍历的方式和数组一样,可以用len()求长度

  • cap可以求出slice最大的容量,0 <= len(slice) <= cap(arry),其中arry是slice引用的数组

  • 切片的定义:var 变量名 []类型,比如:var str []string、var arr []int

  • 切片初始化:var slice []int = arr[start:end],包含start到end之间的元素,但是不包含end

  • var slice []int = arr[0:end] 可以简写成 var slice []int = arr[:end]

  • var slice []int = arr[start:len(arr)] 可以简写成 var slice []int = arr[start:]

  • var slice []int = arr[0:len(arr)] 可以简写成 var slice []int = arr[:]

  • 如果切片要去掉最后一个元素,可以这样写 slice = slice[:len(slice) - 1]

通过make创建切片

var slice []type = make([]type, len)
slice := make([]type, len)
slice := make([]type, len, cap)

用内置函数操作切片

slice = append(slice, 10)

// 添加切片
var a = []int{1, 2, 3}
var b = []int{4, 5, 6}
a = append(a, b...)

切片扩容

var a [5]int = [...]int{1, 2, 3, 4, 5}
s := a[1:]
fmt.Printf("len[%d] cap[%d]\n", len(s), cap(s))
s[1] = 100
fmt.Println("before a:", a)  // [1, 2, 100, 4, 5]

s = append(s, 10)
s = append(s, 10)
s = append(s, 10)
s = append(s, 10)
s = append(s, 10)
s = append(s, 10)
fmt.Println("before a:", a)   // [1, 2, 100, 4, 5]  a在slice容量超过前后没有变化,说明slice在内存不够的情况下会新开辟一片内存对数据进行存储
fmt.Printf("len[%d] cap[%d]\n", len(s), cap(s))  // 开辟后的内存是原来的两倍,即cap(s)是原来的两倍

切片拷贝

s1 := []int{1, 2, 3, 4, 5}
s2 := make([]int, 10)
copy(s2, s1)

string与slice

string底层是一个byte数组,因此,可以进行切片操作

str := "hello world"
s1 := str[0:5]
fmt.Println(s1)

s2 := str[5:]
fmt.Println(s2)

排序

排序操作主要都在sort包中,导入就可以使用了

import("sort")

sort.Ints对整数进行排序,sort.Strings对字符串进行排序,sort.Float64s对浮点数进行排序

// 注意不能传入数组,因为数组是值类型的,要传切片,切片是引用类型的
var a = [5]int{1, 48, 5, 69, 21}
sort.Ints(a[:])


sort.SearchInts(a []int, b int)   // 从数组a中查找b,前提是a必须有序
sort.SearchFloats(a []float64, b float64)  // 从数组a中查找b,前提是a必须有序
sort.SearchStrings(a []string, b string)  // 从数组a中查找b,前提是a必须有序

map

key-value的数据结构,又叫字典或关联数组

声明

var map1 map[keyType]valueType
// eg
var a map[string]string
var a1 map[string]int
var a2 map[int]string
var a3 map[string]map[string]string

注意:

声明是不会分配内存的,初始化需要make

初始化

// 使用make初始化
var a map[string]string
a = make(map[string]string, 10)

b := make(map[string]string, 10)

b["abc"] = "efg"

// 声明时初始化
var c map[string]int = map[string]int{
    "a": 1,
    "b": 2,
}

map相关操作

// 插入和更新
a["hello"] = "world"

// 查找
val, ok := a["hello"]   // val是对应的value,ok存储的是是否有值,为bool类型

// 遍历
for k, v := range a {
    fmt.Println(k, v)
}

// 删除
delete(a, "hello")

// 长度
len(a)

 

posted @ 2019-05-23 22:17  Jin同学  阅读(190)  评论(0)    收藏  举报