一、数组Array
- 定义数组的格式:
var<varName>[n]<type> (n>=0,n表示数组元素个数)
-
数组长度也是类型的一部分
,因此具有不同长度的数组为不同类型 - 注意区分
指向数组的指针
和指针数组
- 数组在Go中为值类型
- 数组之间可以使用==或!=进行比较,但不可以使用< 或 >
- 可以使用
new
来创建数组,此方法返回一个指向数组的指针 - Go支持多维数组
示例:
package main import "fmt" func main() { // var a [2]int a := [2]int{1,2} fmt.Println(a) }
打印结果:
[1 2]
new 创建数据
// var a [2]int a := [10]int{} a[1] = 2 fmt.Println(a) p := new([10]int) p[1] = 2 fmt.Println(p)
打印结果:
➜ run arr.go [0 2 0 0 0 0 0 0 0 0] &[0 2 0 0 0 0 0 0 0 0]
看一下,上边有什么不同吗?第二行结果带了一个地址符&
多维数组
a := [2][3]int{ {1,2,3},{4,5,6}} fmt.Println(a)
打印结果:
[[1 2 3] [4 5 6]]
冒泡排序法:
package main import "fmt" // 冒泡排序 func main() { // ...可以表示不确定的元素数 a := [...]int{1,4,9,20,13,3} fmt.Println(a) // 计算数组的长度 num := len(a) for i := 0; i < num; i++ { // 外边的循环,每循环一次,会将最大的值排在前边 for j := i + 1; j < num; j++ { if a[i] < a[j] { temp := a[i] a[i] = a[j] a[j] = temp } } } fmt.Println(a) }
打印结果:
[1 4 9 2 5 0 20 13 3] [20 13 9 5 4 3 2 1 0]
二、切片Slice
- 其本身并不是数组,它指向底层的数组
作为变长数组的替代方案,可以关联底层数组的局部或全部
- 为
引用类型
- 可以直接创建或从底层数组获取生成
- 使用
len()
获取元素个数,cap()
获取容量 - 一般使用
make
创建 - 如果多个slice指向相同底层数组,其中一个的值改变会影响全部
make([]T,len,cap)
- 其中cap可以省略,则和len的值相同
- len表示存数的元素个数,cap表示容量
示例:
package main import "fmt" func main() { // var s1 []int; a := [10]int{1,3,6,7,8,9} fmt.Println(a) s1 := a[5:10] // a[5,9] 注意:包含5,不包含10[) fmt.Println(s1) }
打印结果:
➜ myfirstgo go run slice.go [1 2 3 4 5 6 7 8 9 0] [6 7 8 9 0]
创建切片:
// 第一个参数表示数组类型,第二个参数表示元素个数,第三个参数表示容量,先分配10个连续的内存,如果不设置容量默认为元素个数 s1 := make([]int,10) fmt.Println(len(s1),cap(s1))
打印结果:
➜ myfirstgo go run slice.go 3 10
Reslice,即再次slice
- Reslice时索引以被slice的切片为准
- 索引不可以超过被slice的切片的容量cap()值
- 索引越界不会导致底层数组的重新分配而是引发错误
a := []byte{'a','b','c','d','e','f','g','h'} sa := a[2:5] sb := sa[1:3] fmt.Println(sb) // 打印出:[100 101] fmt.Println(string(sb)) // 打印出:de
如果sb的数组下标越界:
a := []byte{'a','h','i','j'} sa := a[2:5] fmt.Println(sa) fmt.Println(len(sa),cap(sa)) // 打印sa的元素个数和容量 sb := sa[3:5] // 超过sa的下标 // fmt.Println(sb) fmt.Println(string(sb))
打印结果:
➜ myfirstgo go run slice.go [99 100 101] 3 8 [102 103] fg
slice 指向一个连续的内存块,如,我们取一个数组的前几个元素,则实际它取得是前几个元素的地址,我们可以根据地址拿到未取到的数组元素,是不是和其他语言比,很神奇啊
Append
- 可以在slice尾部追加元素
- 可以将一个slice追加在另一个slice尾部
- 如果最终长度未超过追加到slice的容量则返回原始slice
- 如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
s1 := make([]int,6) fmt.Printf("%p\n",s1) // 打印出内存地址: 0xc420016180 s1 = append(s1,1,3) fmt.Printf("%v %p\n",s1,s1) // 打印出内存地址:0xc420016180 s1 = append(s1,s1) // 打印出内存地址:0xc420066060
打印结果:
➜ myfirstgo go run slice.go 0xc420016180 [0 0 0 1 2 3] 0xc420016180 [0 0 0 1 2 3 1 2 3] 0xc420066060
由以上我们可以看到,如果追加的数组元素超过其容量,则会分配一个新的地址给这个数组,原来的会被干掉。
Copy
s1 := []int{1,5} s2 := []int{7,9} // 拷贝s2的元素到s1中 copy(s1,s2) // copy(s2,s1) fmt.Println(s1)
打印结果:
[7 8 9 4 5]
三、map(集合)
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
- 类似其他语言中的哈希表或者字典,以key-value形式存储数据
-
Key必须是支持==或!=比较运算的类型
,不可以是函数、map或slice - Map查找比线性搜索快得多,但比使用索引访问数据的类型慢100倍
-
Map使用make()创建
,支持:=
这种简写方式 -
make([keyType]valueType,cap)
,cap表示容量,可省略 - 超出容量时会自动扩容,但尽量提供一个合理的初始值
- 使用
len()
获取元素个数 - 键值对不存在时自动添加,使用
delete()
删除某键值对 - 使用
for range
对map和slice进行迭代
操作
1、定义 Map
可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */ var map_variable map[key_data_type]value_data_type /* 使用 make 函数 */ map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就会创建一个 nil map
。nil map 不能用来存放键值对
举例:
package main import "fmt" func main() { // 声明map变量 // var m map[int]string // m = map[int]string{} // m = make(map[int]string) m := make(map[int]string) // 赋值 m[1] = "love" // 删除 delete(m,1) fmt.Println(m) }
打印:
➜ myfirstgo go run map.go map[]
多个map嵌套:
var m map[int]map[int]string m = make(map[int]map[int]string) a,ok := m[2][1] if !ok { m[2] = make(map[int]string) } m[2][1] = "MeiM" a = m[2][1] fmt.Println(a,ok)
打印:
➜ myfirstgo go run map.go MeiM false
迭代
sm := make([]map[int]string,5) for _,v := range sm { v = make(map[int]string,1) // 此处的v为拷贝,而不是引用,不会改变原值 v[1] = "OK" fmt.Println(v) } fmt.Println(sm)
打印:
➜ myfirstgo go run map.go map[1:OK] map[1:OK] map[1:OK] map[1:OK] map[1:OK] [map[] map[] map[] map[] map[]]
2、小试牛刀
根据for range
用法,尝试将类型为 map[int]string
的键和值进行交换,变成类型为 map[string]int
需要转换为下面的例子:
m1 := map[int]string{1:"a",2:"b",3:"c"} m2 := map[string]int{"a":1,"b":2,"c":3}
示例:
m1 := map[int]string{1:"a",3:"c"} // m2 := map[string]int{"a":1,"c":3} m2 := make(map[string]int) for key,v := range m1 { // fmt.Println(key) // fmt.Println(v) m2[v] = key } fmt.Println(m2)
打印结果:
➜ myfirstgo go run map.go map[a:1 b:2 c:3]原文链接:https://www.f2er.com/go/187909.html