GO语言入门 - (五)集合类型

进阶,进阶,向集合类型出发。。。
集合类型
很多同一个类型的元素放在一起的场景就是集合。
数组(array),切片(slice),映射(map)都是集合类型,用以存放同一类元素。
1. Array(数组) 数组存放的是固定长度,相同类型的数据
而且这些存放的元素是连续的
存放的数据类型没有限制
示例代码如下:
package mainimport "fmt"func main() { // 这里中括号里面的5表示的是数组的长度,后面花括号里面的是初始化 array := [5]string{"a","b","c","d","e"} fmt.Println("array的值为::", array) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

1.1 数组在内存中是连续存放的,并且每个元素都有一个下标: GO语言入门 - (五)集合类型
文章图片

这里我们就可以通过 array[下标] 来获取某个特定的元素:
package mainimport "fmt"func main() { // 这里中括号里面的5表示的是数组的长度,后面花括号里面的是初始化 array := [5]string{"a","b","c","d","e"} fmt.Println("array中第四个值为:", array[3]) }

【GO语言入门 - (五)集合类型】运行结果为:
GO语言入门 - (五)集合类型
文章图片

1.2 数组的长度可以省略 Go语言会自动根据大括号中间元素的个数自动推导数组的长度。
这里只是适用于所有元素都被初始化的时候。
package mainimport "fmt"func main() { // 中括号里面用三个英文句号来省略数组的长度 array := [...]string{"a","b","c","d","e"} fmt.Println("array的值为:", array) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

如果只是初始化特定索引的元素做初始化,就不能省略数组长度了
没有初始化的元素其默认值都是数组类型的零值,string就是空字符串
package mainimport "fmt"func main() { // 省略数组长度,只是初始化特定索引的话,数组长度就是最大的索引的长度 array := [...]string{1:"a",3:"c"} fmt.Println("array的长度为:", len(array)) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

1.3 数组循环 大部分情况下使用的是for range这种Go语言的新型循环
package mainimport "fmt"func main() { array := [...]string{"a","b","c","d","e"} for i,v := range array{ fmt.Println("key为:", i, ", value为:",v) } // 如果返回的值不需要,就可以用 _ 丢弃 for _,v := range array{ fmt.Println("value为:", v) } }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

2. Slice(切片) 切片和数组类似,可以把它理解为动态数组(切片的底层就是一个数组)
对数组任意分隔,就可以得到一个切片
package mainimport "fmt"func main() { array := [...]string{"a","b","c","d","e"} // 这里是从索引2开始到索引5结束,包含索引2但不包含索引5 slice := array[2:5] for i,v := range slice{ fmt.Println("key为:", i, ", value为:",v) } }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

2.1 基于数组生成切片 生成的切片也是可以根据索引获取元素的值
在数组array中,元素c的索引其实是2
但是对数组切片后
在新生成的切片slice中,它的索引是0
经过切片后,切片的索引范围改变了
2.2 切片是一个具备三个字段的数据结构:
  • 指向数组的指针data
  • 长度len
  • 容器cap
    GO语言入门 - (五)集合类型
    文章图片
2.3 切片声明
package mainimport "fmt"func main() { // 用make函数生成一个长度为4,容量为8的切片 // 切片的容量不能比切片的长度小 slice1 := make([]string,4,8) fmt.Println(slice1) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

当通过append函数往切片中追加元素的时候,会追加到空闲的内存上,当切片的长度要超过容量的时候,会进行扩容。
切片还可以通过字面量来初始化
通过字面量初始化的切片长度和容量相同
package mainimport "fmt"func main() { // 切片声明和数组唯一的不同就是中括号里面不需要指定长度或者... slice1 := []string{"a","b","c","d","e"} fmt.Println("长度为:", len(slice1), ",容量为:", cap(slice1)) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

2.3 Append追加元素
//追加一个元素 slice2 := append(slice1, "f") //追加多个元素 slice2 := append(slice1, "f", "g") //追加另一个切片 slice2 := append(slice1, slice3)

3. Map(映射) map是一个无需的 K-V 键值对集合
结构为 map[K]V
其中 K 对应 KEY,V 对应 Value
3.1 Map声明初始化 通过make方式创建
package mainimport "fmt"func main() { // 声明一个map key为string类型,value为int类型 nameAgeMap := make(map[string]int) // 如果key已经存在就更新key对应的value值 nameAgeMap["zhouzhaodong"] = 20 fmt.Println(nameAgeMap) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

通过字面量方式创建
package mainimport "fmt"func main() { // 声明一个map key为string类型,value为int类型 nameAgeMap := map[string]int{"zhouzhaodong": 20} // 添加新的键值对 nameAgeMap["xiaohua"] = 21 fmt.Println(nameAgeMap) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

3.2 Map获取和删除
// 添加新的键值对 nameAgeMap["xiaohua"] = 21 // 获取指定 Key 对应的 Value age := nameAgeMap["xiaohua"]

map的[]操作符可以返回两个值:
  1. 第一个值就是对应的 Value
  2. 第二个值标记该 Key 是否存在,如果存在,它的值为 true
package mainimport ( "fmt" )func main() { // 声明一个map key为string类型,value为int类型 nameAgeMap := map[string]int{"zhouzhaodong": 20} // 获取特定key的value值 age, ok := nameAgeMap["zhouzhaodong1"] if ok { fmt.Println(age) } else { fmt.Println("该key不存在") } }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

删除键值对直接使用 delete 函数即可
// 这里的delete函数有两个参数,第一个是Map集合,第二个是Key值 delete(nameAgeMap, "zhouzhaodong")

3.3 遍历 Map 这里映射的遍历是无序的,每次遍历的顺序可能不同
对于 map,for range 返回两个值:
  1. 第一个是 map 的 Key
  2. 第二个是 map 的 Value
package mainimport ( "fmt" )func main() { // 声明一个map key为string类型,value为int类型 nameAgeMap := map[string]int{"zhouzhaodong": 20} // 新增一个键值对 nameAgeMap["小花"] = 21 for k, v := range nameAgeMap{ fmt.Println("key=", k, ",value="https://www.it610.com/article/, v) } }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

4. String 和 []byte 所有的字符串都是一个不可变的字节数列,所以可以直接转化为字节数组
字符串还可以直接使用 [] 获取对应索引的字节值
package mainimport ( "fmt" )func main() { s := "猜猜我的长度" bs := []byte(s) fmt.Println("s=", s) fmt.Println("bs=", bs) // UTF8编码下,一个汉字是3个字节,所以这里s的长度为18 fmt.Println("s的长度为:", len(s)) fmt.Println(s[1], s[4], s[17]) }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

如果你想把一个汉字当做一个长度来计算的话,可以用如下方法
s := "猜猜我的长度" // 这里打印的结果是6 fmt.Println(utf8.RuneCountInString(s))

4.1 循环 使用 fro range 进行字符串的循环时,会自动的隐式解码Unicode字符串
package mainimport ( "fmt" )func main() { s := "猜猜我的长度" for i, v := range s{ fmt.Println(i, v) // string(v) 将Unicode转为对应的汉字 fmt.Println(i, string(v)) } }

运行结果为:
GO语言入门 - (五)集合类型
文章图片

个人博客地址
http://www.zhouzhaodong.xyz/

    推荐阅读