[TOC]
0X00 Go语言基础之数组
描述: 本文主要介绍Go语言中数组(array)及它的基本使用。
Q: 什么是Array(数组)?
答: 学过C语言的同学都知道,数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。
1.数组定义
基本语法:
[TOC]
描述: 本文主要介绍Go语言中数组(array)及它的基本使用。
Q: 什么是Array(数组)?
答: 学过C语言的同学都知道,数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。
基本语法:
[TOC]
描述: 本文主要介绍Go语言中数组(array)及它的基本使用。
Q: 什么是Array(数组)?
答: 学过C语言的同学都知道,数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。
基本语法:1
2
3
4var 数组变量名 [元素数量]T
// 定义一个长度为3元素类型为int的数组a
var a [3]int
比如:var a [5]int
, 数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。注意: [5]int
和[10]int
是不同的类型。
1 | var a [3]int |
Tips :数组可以通过下标进行访问,下标是从0
开始,最后一个元素下标是:len-1
,访问越界(下标在合法范围之外),则触发访问越界,会panic。
数组的初始化也有很多方式。
1.方法一
初始化数组时可以使用初始化列表来设置数组元素的值。
1 | func main() { |
2.方法二
按照上面的方法每次都要确保提供的初始值和数组长度一致,一般情况下我们可以让编译器根据初始值的个数自行推断数组的长度,例如:
1 | func main() { |
3.方法三(非常值得学习)
我们还可以使用指定索引值的方式来初始化数组,例如:
1 | func main() { |
遍历数组a有以下两种方法:
1 | func main() { |
Go语言是支持多维数组的,我们这里以二维数组为例(数组中又嵌套数组)。
1 | func main() { |
注意: 多维数组只有第一层可以使用...
来让编译器推导数组长度。例如:
1 | //支持的写法 |
1 | func main() { |
输出:
1 | 北京 上海 |
描述: 数组是值类型,赋值和传参会复制整个数组
。因此改变副本的值,不会改变本身的值。
1 | // go 语言中默认传参是值传递(拷贝原变量的值即 Ctrl+c 、Ctrl+v ) |
注意:
[n]*T
表示指针数组,*[n]T
表示数组指针 。示例演示:
1 | package main |
执行结果:
1 | a 数组类型 [2]int , 元素: [0 0] |
描述: 本文主要介绍Go语言中切片(slice)及它的基本使用。
Q: 为什么要引入切片这个特性?
描述: 因为数组的长度是固定的并且数组长度属于类型的
一部分,所以数组有很多的局限性。
例如:1
2
3
4
5
6
7func arraySum(x [3]int) int{
sum := 0
for _, v := range x{
sum = sum + v
}
return sum
}
这个求和函数只能接受[3]int
类型,其他的都不支持。 再比如,1
a := [3]int{1, 2, 3}
数组a中已经有三个元素了,我们不能再继续往数组a中添加新元素了, 所以为了解决上述问题我们引入了Python一样切片的编程语言特性。
描述: 切片(Slice)
是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装
。
特点:
地址
、长度
和容量
。切片一般用于快速地操作一块数据集合。声明切片类型的基本语法如下:
1 | var name []T |
Tips : 在定义时可看出与数组定义var array [number]T
间的区别,其不需要设置元素个数。
举个例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14func main() {
// 声明切片类型
var a []string //声明一个字符串切片
var b = []int{} //声明一个整型切片并初始化
var c = []bool{false, true} //声明一个布尔切片并初始化
var d = []bool{false, true} //声明一个布尔切片并初始化
fmt.Println(a) //[]
fmt.Println(b) //[]
fmt.Println(c) //[false true]
fmt.Println(a == nil) //true
fmt.Println(b == nil) //false
fmt.Println(c == nil) //false
// fmt.Println(c == d) //切片是引用类型,不支持直接比较,只能和nil比较
}
描述: 切片拥有自己的长度和容量,我们可以通过使用内置的len()
函数求长度,使用内置的cap()
函数求切片的容量。
1 | // 切片长度与容量 |
描述: 切片表达式从字符串、数组、指向数组或切片的指针构造子字符串或切片。
它有两种变体:一种指定low和high两个索引界限值的简单的形式,另一种是除了low和high索引界限值外还指定容量的完整的形式。
描述: 切片的底层就是一个数组,所以我们可以基于数组通过切片表达式得到切片。 切片表达式中的low
和high
表示一个索引范围(左包含,右不包含)
,也就是下面代码中从数组a中选出1<=索引值<4
的元素组成切片s,得到的切片长度=high-low
,容量等于得到的切片的底层数组的容量。
1 | func main() { |
输出:1
s:[2 3] len(s):2 cap(s):4
为了方便起见,可以省略切片表达式中的任何索引。省略了low
则默认为0;省略了high
则默认为切片操作数的长度:1
2
3a[2:] // 等同于 a[2:len(a)]
a[:3] // 等同于 a[0:3]
a[:] // 等同于 a[0:len(a)]
注意:对于数组或字符串,如果0 <= low <= high <= len(a)
,则索引合法,否则就会索引越界(out of range)。
Tips : 对切片再执行切片表达式时(切片再切片
),high
的上限边界是切片的容量cap(a)
,而不是长度。
常量索引必须是非负的,并且可以用int类型的值表示;对于数组或常量字符串,常量索引也必须在有效范围内。如果low
和high
两个指标都是常数,它们必须满足low <= high
。如果索引在运行时超出范围,就会发生运行时panic
。
1 | func main() { |
输出:1
2s:[2 3] len(s):2 cap(s):4
s2:[5] len(s2):1 cap(s2):1
描述: 对于数组,指向数组的指针,或切片a(注意不能是字符串)支持完整切片表达式:
1 | a[low : high : max] |
描述: 上面的代码会构造与简单切片表达式a[low: high]
相同类型、相同长度和元素的切片。另外它会将得到的结果切片的容量设置为max-low
。在完整切片表达式中只有第一个索引值(low)可以省,它默认为0。
1 | func main() { |
输出结果:1
t:[2 3] len(t):2 cap(t):4
Tips : 完整切片表达式需要满足的条件是0 <= low <= high <= max <= cap(a)
,其他条件和简单切片表达式相同。
描述: 切片的遍历方式和数组是一致的,支持索引遍历和for range
遍历。
1 | func main() { |
描述: 切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)
。
举个例子,现在有一个数组a := [8]int{0, 1, 2, 3, 4, 5, 6, 7}
,切片s1 := a[:5]
,相应示意图如下。
切片s2 := a[3:6]
,相应示意图如下:
Tips : 由上面两图可知切片的容量是数组长度 - 切片数组起始索引下标
,例如 a[1:] = 8 - 1 其容量为7
描述: 我们上面都是基于数组来创建的切片,如果需要动态的创建一个切片,我们就需要使用内置的make()
函数,格式如下:
格式说明:
1 | make([]T, size, cap) |
举个例子:
1 | func main() { |
上面代码中a
的内部存储空间已经分配了10个,但实际上只用了2个。 容量并不会影响当前元素的个数,所以len(a)
返回2,cap(a)
则返回该切片的容量。
描述: Go语言的内建函数append()
可以为切片动态添加元素。 可以一次添加一个元素,可以添加多个元素,也可以添加另一个切片中的元素(后面加…)。
1 | func main(){ |
注意: 通过var声明的零值切片可以在append()
函数直接使用,无需初始化。
1 | var s []int |
注意: 没有必要像下面的代码一样初始化一个切片再传入append()
函数使用,
1 | s := []int{} // 没有必要初始化 |
描述: 每个切片会指向一个底层数组,这个数组的容量够用就添加新增元素。当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行“扩容”,此时该切片指向的底层数组就会更换。“扩容”操作往往发生在append()
函数调用时,所以我们通常都需要用原变量接收append函数的返回值。
举个例子:1
2
3
4
5
6
7
8func main() {
//append()添加元素和切片扩容
var numSlice []int
for i := 0; i < 10; i++ {
numSlice = append(numSlice, i)
fmt.Printf("%v len:%d cap:%d ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
}
}
输出情况:1
2
3
4
5
6
7
8
9
10[0] len:1 cap:1 ptr:0xc0000a8000
[0 1] len:2 cap:2 ptr:0xc0000a8040
[0 1 2] len:3 cap:4 ptr:0xc0000b2020
[0 1 2 3] len:4 cap:4 ptr:0xc0000b2020
[0 1 2 3 4] len:5 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5] len:6 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6] len:7 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6 7] len:8 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6 7 8] len:9 cap:16 ptr:0xc0000b8000
[0 1 2 3 4 5 6 7 8 9] len:10 cap:16 ptr:0xc0000b8000
从上面的结果可以看出:
append()
函数将元素追加到切片的最后并返回该切片。1,2,4,8,16
这样的规则自动进行扩容,每次扩容后都是扩容前的2倍。append() 函数还支持一次性追加多个元素,例如:1
2
3
4
5
6
7
8
9var citySlice []string
// 追加一个元素
citySlice = append(citySlice, "北京")
// 追加多个元素
citySlice = append(citySlice, "上海", "广州", "深圳")
// 追加切片
a := []string{"成都", "重庆"}
citySlice = append(citySlice, a...)
fmt.Println(citySlice) // [北京 上海 广州 深圳 成都 重庆]
描述: 首先我们来看一个问题1
2
3
4
5
6
7
8
9func main() {
a := []int{1, 2, 3, 4, 5}
b := a
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(b) //[1 2 3 4 5]
b[0] = 1000
fmt.Println(a) //[1000 2 3 4 5]
fmt.Println(b) //[1000 2 3 4 5]
}
Tips : 由于切片是引用类型,所以a和b其实都指向了同一块内存地址。修改b的同时a的值也会发生变化。
Go语言内建的copy()
函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()
函数的使用格式如下:
1 | copy(destSlice, srcSlice []T) |
举个例子:1
2
3
4
5
6
7
8
9
10
11func main() {
// copy()复制切片
a := []int{1, 2, 3, 4, 5}
c := make([]int, 5, 5)
copy(c, a) //使用copy()函数将切片a中的元素复制到切片c
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
c[0] = 1000
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1000 2 3 4 5]
}
描述: Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。 代码如下:
1 | func main() { |
总结一下就是:要从切片a中删除索引为index
的元素,操作方法是a = append(a[:index], a[index+1:]...)
描述: 要检查切片是否为空,请始终使用len(s) == 0
来判断,而不应该使用s == nil
来判断。
1 | d := [5]int{1, 2, 3, 4, 5} |
描述: 切片之间是不能比较的,我们不能使用==
操作符来判断两个切片是否含有全部相等元素。 切片唯一合法的比较操作是和nil
比较。 一个nil
值的切片并没有底层数组,一个nil
值的切片的长度和容量都是0。
但是我们不能说一个长度和容量都是0的切片一定是nil
,例如下面的示例:1
2
3var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
所以要判断一个切片是否是空的,要是用len(s) == 0
来判断,不应该使用s == nil
来判断。
描述: 下面的代码中演示了拷贝前后两个变量共享底层数组,对一个切片的修改会影响另一个切片的内容,这点需要特别注意。
1 | func main() { |
描述: 可以通过查看$GOROOT/src/runtime/slice.go
源码,其中扩容相关代码如下:
1 | newcap := old.cap |
从上面的代码可以看出以下内容:
(newcap=old.cap,for {newcap += newcap/4})
直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
Tips : 需要注意的是,切片扩容还会根据切片中元素的类型不同而做不同的处理,比如int
和string
类型的处理方式就不一样。
示例演示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73package main
import "fmt"
func main() {
// 切片声明与定义
var a []string //声明一个字符串切片
var b = []int{} //声明一个整型切片并初始化
var c = []bool{false, true} //声明一个布尔切片并初始化
// - 切片 a 变量值为空/零值。
if a == nil {
fmt.Println("a 切片元素:", a)
}
fmt.Println("b 切片元素:", b)
fmt.Println("c 切片元素:", c)
// 切片长度与容量
var lth = []int{}
var lth64 = []float64{1, 2, 3}
fmt.Println("切片长度", len(lth), ",切片容量", cap(lth))
fmt.Println("切片长度", len(lth64), ",切片容量", cap(lth64))
// 切片表达式
d := [5]int{1, 2, 3, 4, 5}
s := [5]string{"Let", "'s", "Go", "语言", "学习"}
s1 := d[1:3] // s := d[low(包含):high(不包含)] == d[1] d[2]
s2 := d[2:] // 等同于 a[2:5] == d[2] d[3] d[4]
s3 := d[:3] // 等同于 a[0:3] == d[0] d[1] d[2]
s4 := d[:] // 等同于 a[0:5] == d[0] d[1] d[2] d[3] d[4]
s5 := s[1:4:5] // 等同于 s[1:4] == s[1] s[2] s[3]
fmt.Printf("s1:%v len(s1):%v cap(s1):%v\n", s1, len(s1), cap(s1)) // 注意此种情况 { 2 .. 5 容量为 4 }
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2)) // { 3 .. 5 容量为 3 }
fmt.Printf("s3:%v len(s3):%v cap(s3):%v\n", s3, len(s3), cap(s3)) // 注意此种情况 { 1 .. 5 容量为 5 }
fmt.Printf("s4:%v len(s4):%v cap(s4):%v\n", s4, len(s4), cap(s4)) // { 1 .. 5 容量为 5}
fmt.Printf("s5:%v len(s5):%v cap(s5):%v\n", s5, len(s5), cap(s5)) // s5:['s Go 语言] len(s5):3 cap(s5):4
// 判断切片是否为空
if len(d) != 0 {
fmt.Println("变量 d 切片不为空: ", d)
}
// 切片遍历
for i, v := range s {
fmt.Printf("i: %d, v: %v , 切片指针地址: %p \n", i, v, &v)
}
fmt.Println()
// make() 构造切片
e := make([]int, 2, 10)
fmt.Printf("e:%v len(e):%d cap(e):%d \n", e, len(e), cap(e)) // 长度 2,容量为 10
// append() 添加元素 {7,8,9}
f := append(e, 7, 8, 9) // f:[0 0 7 8 9] len(f):5 cap(f):10
f = append(f, e...) // 追加切片
fmt.Printf("f:%v len(f):%d cap(f):%d \n", f, len(f), cap(f)) // 长度 7,容量为 10
// copy() 复制切片
slice1 := []int{1, 2, 3, 4, 5}
slice2 := make([]int, 7, 7)
copy(slice2, slice1)
slice2[6] = 2048
fmt.Println("slice1 : ", slice1, "\t slice2 :", slice2)
// 切片赋值拷贝
slice3 := make([]int, 3)
slice4 := slice3
slice4[0] = 1024
slice4[2] = 4096
fmt.Printf("slice3 : %v, ptr : %p \n", slice3, slice3)
fmt.Printf("slice4 : %v, ptr : %p \n", slice4, slice4)
}
执行结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22a 切片元素: []
b 切片元素: []
c 切片元素: [false true]
切片长度 0 ,切片容量 0
切片长度 3 ,切片容量 3
s1:[2 3] len(s1):2 cap(s1):4
s2:[3 4 5] len(s2):3 cap(s2):3
s3:[1 2 3] len(s3):3 cap(s3):5
s4:[1 2 3 4 5] len(s4):5 cap(s4):5
s5:['s Go 语言] len(s5):3 cap(s5):4
变量 d 切片不为空: [1 2 3 4 5]
i: 0, v: Let , 切片指针地址: 0xc000010270
i: 1, v: 's , 切片指针地址: 0xc000010270
i: 2, v: Go , 切片指针地址: 0xc000010270
i: 3, v: 语言 , 切片指针地址: 0xc000010270
i: 4, v: 学习 , 切片指针地址: 0xc000010270
e:[0 0] len(e):2 cap(e):10
f:[0 0 7 8 9 0 0] len(f):7 cap(f):10
slice1 : [1 2 3 4 5] slice2 : [1 2 3 4 5 0 2048]
slice3 : [1024 0 4096], ptr : 0xc000018288
slice4 : [1024 0 4096], ptr : 0xc000018288
Tips 总结: 数组是值类型,且包含元素的类型和元素个数,需注意元素的个数(数组长度)
属于数组类型的一部分。
描述: Go语言中提供的映射关系容器为map, 其内部使用散列表(hash)实现。
描述: Map 是一种无序的基于key-value
的数据结构, 并且它是引用类型,所以必须初始化值周才能进行使用。
语法定义:
1 | map[KeyType]ValueType |
Tips : map类型的变量默认初始值为nil
,需要使用make()函数来分配内存
。语法为:make(map[KeyType]ValueType, [cap])
, 其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
描述:Map 中的数据都是成对出现的其Map的基本使用示例代码如下:
1 | // 1.采用Make初始化Map类型的变量。 |
描述: 在进行Map类型的变量遍历之前,我们先学习判断map中键是否存在。
(1) 键值判断
描述: 判断Map中某个键是否存在可以采用如下特殊写法: value, ok := map[key]
1
2
3
4
5
6
7
8scoreMap := make(map[string]int)
scoreMap["小明"] = 100
value, ok := scoreMap["张三"]
if ok {
fmt.Println("scoreMap 存在该 '张三' 键")
} else {
fmt.Println("scoreMap 不存在该键值")
}
(2) 键值遍历
描述: Go 语言中不像Python语言一样有多种方式进行遍历, 大道至简就 for...range
遍历 Map
就可以搞定。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18scoreMap := make(map[string]int)
scoreMap["Go"] = 90
scoreMap["Python"] = 100
scoreMap["C++"] = 60
// 遍历 k-v 写法
for k, v := range scoreMap {
fmt.Println(k, v)
}
// 遍历 k 写法
for k := range scoreMap {
fmt.Println(k)
}
// 遍历 v 写法
for _, v := range scoreMap {
fmt.Println(v)
}
Tips :遍历map时的元素顺序与添加键值对的顺序无关。
描述: 我们可使用 delete() 内建函数
从map中删除一组键值对, delete()
函数的格式如下: delete(map, key)
其中 map:
表示要删除键值对的map, key:
表示要删除的键值对的键。
1 | scoreMap := make(map[string]int) |
描述: 第一次看到时可能比较绕,其实可以看做在切片中存放Map类型变量。
简单示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23func demo3() {
var mapSlice = make([]map[string]string, 3)
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
fmt.Println()
// 对切片中的map元素进行初始化
mapSlice[0] = make(map[string]string, 10)
mapSlice[1] = make(map[string]string, 10)
mapSlice[2] = make(map[string]string, 10)
mapSlice[0]["name"] = "WeiyiGeek"
mapSlice[0]["sex"] = "Man"
mapSlice[1]["姓名"] = "极客"
mapSlice[1]["性别"] = "男"
mapSlice[2]["hobby"] = "Computer"
mapSlice[2]["爱好"] = "电脑技术"
for i, v := range mapSlice {
//fmt.Printf("index:%d value:%v\n", i, v)
for _, value := range v {
fmt.Printf("index:%d value:%v\n", i, value)
}
}
}
执行结果:1
2
3
4
5
6
7
8
9
10index:0 value:map[]
index:1 value:map[]
index:2 value:map[]
index:0 value:Man
index:0 value:WeiyiGeek
index:1 value:极客
index:1 value:男
index:2 value:Computer
index:2 value:电脑技术
描述: 同样在Map中存放切片类型的数据。
代码演示了map中值为切片类型的操作:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 值为切片类型的map
func demo4() {
var sliceMap = make(map[string][]string, 3)
var key = [2]string{"Country", "City"}
fmt.Println("初始化 sliceMap 其值 : ", sliceMap)
for _, v := range key {
// 判断键值是否存在如果不存在则初始化一个容量为2的切片
value, ok := sliceMap[v]
if !ok {
value = make([]string, 0, 2)
}
if v == "Country" {
value = append(value, "中国", "巴基斯坦")
} else {
value = append(value, "北京", "上海","台湾")
}
// 将切片值赋值给Map类型的变量
sliceMap[v] = value
}
执行结果:1
2初始化 sliceMap 其值 : map[]
map[City:[北京 上海] Country:[中国 巴基斯坦]]
Tips : 非常重要、重要 Slice切片与Map
在使用时一定要做初始化操作(在内存空间申请地址)。
1.Map类型的基础示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50func demo1() {
// 1.Map 定义
var a1 map[string]int8 // (未分配内存)
fmt.Println("Map 类型 的 a1 变量 :", a1)
if a1 == nil {
fmt.Println("默认初始化的Map类型的a1变量值: nil")
}
// 2.基本使用利用Make进行分配内存空间存储Map。
b1 := make(map[string]string, 8)
b1["姓名"] = "WeiyiGeek"
b1["性别"] = "男|man"
b1["爱好"] = "计算机技术"
b1["出生日期"] = "2021-08-08"
// 指定输出
fmt.Printf("b1['姓名'] = %v \n", b1["姓名"])
// 整体输出
fmt.Printf("Map b1 Type: %T , Map b1 Value: %v \n", b1, b1)
// 3.在声明时填充元素。
c1 := map[string]string{
"username": "WeiyiGeek",
"sex": "Man",
"hobby": "Computer",
}
// 指定输出
fmt.Printf("c1['username'] = %v \n", c1["username"])
// 整体输出
fmt.Printf("Map c1 Type: %T , Length : %d , Map c1 Value: %v \n", c1, len(c1), c1)
// 4.判断c1中的键值时候是否存在 sex Key.
value, ok := c1["sex"]
if ok {
fmt.Println("c1 Map 变量中存在 'sex' 键 = ", value)
} else {
fmt.Println("c1 Map 变量中不存在 sex 键")
}
// 5.遍历Map
for k, v := range b1 {
fmt.Println(k, "=", v)
}
// 6.删除指定键值对,例如删除c1中的hobby键值。
delete(c1, "hobby")
fmt.Printf("Map 现存在的键 : ")
for k := range c1 {
fmt.Print(k, " ")
}
}
执行结果:1
2
3
4
5
6
7
8
9
10
11
12Map 类型 的 a1 变量 : map[]
默认初始化的Map类型的a1变量值: nil
b1['姓名'] = WeiyiGeek
Map b1 Type: map[string]string , Map b1 Value: map[出生日期:2021-08-08 姓名:WeiyiGeek 性别:男|man 爱好:计算机技术]
c1['username'] = WeiyiGeek
Map c1 Type: map[string]string , Length : 3 , Map c1 Value: map[hobby:Computer sex:Man username:WeiyiGeek]
c1 Map 变量中存在 'sex' 键 = Man
出生日期 = 2021-08-08
姓名 = WeiyiGeek
性别 = 男|man
爱好 = 计算机技术
Map 现存在的键 : username sex
2.按照指定顺序遍历map
1 | func demo2() { |
执行结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20stu00 4
stu01 48
stu02 66
stu03 18
stu04 13
stu05 89
stu06 80
stu07 16
stu08 11
stu09 26
stu10 42
stu11 45
stu12 24
stu13 47
stu14 92
stu15 77
stu16 12
stu17 16
stu18 17
stu19 76
Tips : 探究上述示例中Array 数组、Slice 切片、Map 映射
有序与无序输出演示。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29func demo5() {
// Array
var Arr = [...]int{1, 2, 6, 4, 5}
// Slice
var Sli = []int{1, 2, 6, 4, 5}
// Map
var Map = map[string]int{
"a1": 1,
"b2": 2,
"c3": 3,
"d6": 6,
"e5": 5,
}
fmt.Printf("Type : %T, Value : %v \n", Arr, Arr)
for _, A := range Arr {
fmt.Printf("%v ", A)
}
fmt.Println()
fmt.Printf("Type : %T, Value : %v \n", Sli, Sli)
for _, S := range Sli {
fmt.Printf("%v ", S)
}
fmt.Println()
fmt.Printf("Type : %T, Value : %v \n", Map, Map)
for _, M := range Map {
fmt.Printf("%v ", M)
}
}
执行结果:1
2
3
4
5
6Type : [5]int, Value : [1 2 6 4 5]
1 2 6 4 5
Type : []int, Value : [1 2 6 4 5]
1 2 6 4 5
Type : map[string]int, Value : map[a1:1 b2:2 c3:3 d6:6 e5:5]
1 2 3 6 5
你好看友,欢迎关注博主微信公众号哟! ❤
这将是我持续更新文章的动力源泉,谢谢支持!(๑′ᴗ‵๑)
温馨提示: 未解锁的用户不能粘贴复制文章内容哟!
方式1.请访问本博主的B站【WeiyiGeek】首页关注UP主,
将自动随机获取解锁验证码。
Method 2.Please visit 【My Twitter】. There is an article verification code in the homepage.
方式3.扫一扫下方二维码,关注本站官方公众号
回复:验证码
将获取解锁(有效期7天)本站所有技术文章哟!
@WeiyiGeek - 为了能到远方,脚下的每一步都不能少
欢迎各位志同道合的朋友一起学习交流,如文章有误请在下方留下您宝贵的经验知识,个人邮箱地址【master#weiyigeek.top】
或者个人公众号【WeiyiGeek】
联系我。
更多文章来源于【WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少】, 个人首页地址( https://weiyigeek.top )
专栏书写不易,如果您觉得这个专栏还不错的,请给这篇专栏 【点个赞、投个币、收个藏、关个注、转个发、赞个助】,这将对我的肯定,我将持续整理发布更多优质原创文章!。
最后更新时间:
文章原始路径:_posts/编程世界/Go/3.Go编程快速入门学习.md
转载注明出处,原文地址:https://blog.weiyigeek.top/2020/4-23-592.html
本站文章内容遵循 知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议