4.数组、切片、map
数组
数组的定义
var 变量名称 [长度]数据类型
// 其中长度需要是确定的量,不可以是变量或表达式
数组初始化
- 定义时使用
var citys = [4]string{"北京","上海","广州","深圳"}
- 编译器推导数组的长度
var boolArray = [...]bool{false, true}
- 使用索引值的方式
var langArray = [...]string{1:"Golang", 3:"Python", 6:"Java"}
// 除了下标为1,3,6的位置有值外,其他地方都是空串
数组的遍历
- 使用for循环
var citys = [4]string{"北京","上海","广州","深圳"}
for i:=0,i<len(citys);i++{
fmt.Println(i)
fmt.Println(citys[i])
}
- for range 遍历
for index, value := range citys{
fmt.Println(index, value)
}
for _, value := range citys{
fmt.Println(value)
}
多维数组
二维数组
其实就是数组里再嵌套一个数组
citys:=[3][2]string{
{"北京","西安"},
{"上海","杭州"},
{"天津","广州"}
}
fmt.Println(citys[1][1]) // 杭州
遍历二维数组
for _,v1:=range citys{
for _, v2 := range v1{
fmt.Println(v2)
}
}
数组是值类型,所以在走赋值操作的时候其实是都是值传递
package main
import "fmt"
func main() {
x:=[2]int{1,2,3}
fmt.Println(x) // [1,2]
f1(x)
fmt.Println(x) // [1,2]
// 在调用函数的前后x的值没有变化,因为在传递的时候不是传递的地址(索引传递),所以函数内修改的值不会改变x本身的值
}
func f1(a[2]int){
a[0] = 100
}
切片
拥有相同类型元素的可变长度的序列,是基于数组类型的一层封装
但切片和数组不同,切片是引用类型
切片在容量不够时会自动扩容,但是在定义切片的时候应提前想好切片的容量,尽量避免自动扩容,自动扩容会产生额外的内存消耗
定义
var a []string // 中括号内不需要加数字
var b []int{1,2,3} // 定义时初始化
// 基于数组得到切片
a:=[5]int{1,2,3,4,5}
b:=a[1:4] //[2,3,4] 左闭右开
c:=b[:] // c:=b[0:len(b)]的简写。对切片再次切片
// make函数构造切片
d:=make([]int, 5, 10) // 得到一个长度为5,容量为10的切片,容量不写时默认和长度一致
fmt.Println(len(d)) // 长度为5
fmt.Println(cap(d)) // 容量为10
切片不能直接进行比较,不可以使用==操作符来判断两个切片是否含有全部相等的元素,切片唯一合法的比较操作是和nil比较
一个nil值的切片并没有底层数组,其长度和容量都是0,但一个长度和容量都是0的切片不一定是nil
var 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
// 所以无法通过是否==nil来判断一个切片是否为空,应该判断len()==0
切片的赋值拷贝
a:=make([]int, 3) // [0,0,0]
b := a // 这时候a和b是共用一个底层数组的
b[0] = 100 // a:[100,0,0] b:[100,0,0]
切片的遍历
// 与数组的遍历相同
a:[]int{1,2,3,4,5}
for i:=0;i<len(a);i++{
fmt.Println(a[i])
}
for i,v:=range a{
fmt.Println(i,v)
}
append方式添加元素
var a[]int // 此时并没有申请内存,所以无法通过下标的方式赋值
// a[0] = 100 会报错,切片需要初始化之后才能使用
a = append(a, 10) // 在原有数组容量不够的时候,会自动扩容,所以append函数必须要有一个变量来接受,因为它可能返回原来的数组,也可能返回一个新的数组
// 一次追加多个元素
var a[]int
a = append(a, 1,2,3,4,5)
// 切片中追加切片
b := []int{1,2,3,4}
a = append(a, b...)
使用copy()函数赋值切片
a:=[]int{1,2,3,4,5}
b = make([]int, 5, 5)
copy(b,a)
fmt.Println(a, b) // 此时a和b看起来是一样的,但他们并没有指向同一个内存地址
a[0] = 100
fmt.Println(a, b) // a:[100,2,3,4,5] b:[1,2,3,4,5]
切片的删除
// 借助append()实现删除操作
a:=[]string{"北京","上海","深圳"}
a = append(a[0:2], a[3:]...)
// append(a[:index], a[index+1:]...)
切片的排序
a:=[...]int{3,4,6,2,1}
sort.Ints(a[:]) // 因为切片的是指向数组的,所以对切片进行排序就是对原来的数组进行排序
fmt.Println(a)
map
go语言中,map也是一种引用类型,不初始化的时候无法直接使用
map是无序的,键值对的顺序和添加的顺序是无关的
map的声明
var a map[string]int
// 和切片一样,只声明不初始化的map,默认值是nil,无法直接使用
初始化
a = make(map[string]int, 8)
添加键值对
a["high"] = 12
a["width"] = 10
fmt.Printf("a:%#v\n", a)
声明的同时完成初始化
b:=map[int]bool{
1:true,
2:false,
}
判断某个键是否存在
var scoreMap = make(map[string]int,8)
scoreMap["张三"]=100
scoreMap["李四"]=200
v,ok := scoreMap["王五"]
if ok{
fmt.Println("王五在map中") // value=100
}else{
fmt.Println("王五不在map中")// value=0
}
map的遍历
var scoreMap = make(map[string]int,8)
scoreMap["张三"]=100
scoreMap["李四"]=200
for k,v := range scoreMap{
fmt.Println(k,v)
}
// 值遍历map中的key
for k := range scoreMap{
fmt.Println(k)
}
// 只遍历map中的value
for _,v:=range scoreMap{
fmt.Println(v)
}
删除map中的键值对
var scoreMap = make(map[string]int,8)
scoreMap["张三"]=100
scoreMap["李四"]=200
delete(scoreMap, "张三") // 删除的值不在map中时,也不会报错
fmt.Println(scoreMap)
map排序
package main
import (
"fmt"
"math/rand"
"sort"
)
func main() {
var scoreMap = make(map[string]int, 100)
for i := 0; i < 50; i++ {
key := fmt.Sprintf("stu%02d", i)
value := rand.Intn(100)
scoreMap[key] = value
}
// 1.先取出所有的key放到切片中
keys := make([]string, 0, 100)
for k := range scoreMap {
keys = append(keys, k)
}
// 2.对key做排序
sort.Strings(keys)
// 3.按照排序后的key对scoreMap排序
for _, v := range keys {
fmt.Println(v, scoreMap[v])
}
}
复杂类型数据
元素为map的切片
var mapSlice = make([]map[string]int, 8) //此时只是完成了切片的初始化,还无法直接使用
mapSlice[0] = make(map[string]int, 2)
mapSlice[0]["张三"] = 10
fmt.Println(mapSlice)
值是切片的map
var sliceMap = make(map[string][]int, 8) // 此时只是完成了map的初始化,无法直接使用
v, ok := sliceMap["中国"]
if ok {
fmt.Println(v)
fmt.Println(sliceMap["中国"])
} else {
sliceMap["中国"] = make([]int, 8) // 完成对切片的初始化
sliceMap["中国"][0] = 100
sliceMap["中国"][1] = 200
}
// 遍历sliceMap
for k, v := range sliceMap {
fmt.Println(k, v)
}
统计一个字符串中每个单词出现的次数
package main
import (
"fmt"
"strings"
)
func main() {
var s string = "how do you do"
var c map[string]int = make(map[string]int, 10)
words := strings.Split(s, " ")
for _, v := range words {
_, ok := c[v]
if ok {
c[v] += 1
} else {
c[v] = 1
}
}
fmt.Println(c)
}
// 也可以利用不存在的键返回对应零值的特性
func main() {
var s string = "how do you do"
var c map[string]int = make(map[string]int, 10)
words := strings.Split(s, " ")
for _, v := range words {
c[v] += 1
}
fmt.Println(c)
}

浙公网安备 33010602011771号