go 基础 -2
数组
数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。
// 定义 var 数组变量名 [元素数量]类型 //定义方法1,预先设置数组长度 var a [3]int //定义方法2,让编辑器自行推断 var b [...]int{1, 2, 4} //用索引值来初始化数组 var a int{1: 2, 6:999} //遍历数组 func main() { var a = [...]string{"北京", "上海", "深圳"} // 方法1:for循环遍历 for i := 0; i < len(a); i++ { fmt.Println(a[i]) } // 方法2:for range遍历 for index, value := range a { fmt.Println(index, value) } }
多维数组
Go语言是支持多维数组的,我们这里以二维数组为例(数组中又嵌套数组)
注意: 多维数组只有第一层可以使用...来让编译器推导数组长度
func main() { a := [3][2]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } fmt.Println(a) //[[北京 上海] [广州 深圳] [成都 重庆]] fmt.Println(a[2][1]) //支持索引取值:重庆 } // 遍历 func main() { a := [3][2]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } for _, v1 := range a { for _, v2 := range v1 { fmt.Printf("%s\t", v2) } fmt.Println() } }
数组是值类型,赋值和传参会复制整个数组。所以改变数组的值,不会改变数组本身
func main() { var a = [3]int{11, 22, 33} test1(a) fmt.Println(a) // [11 22 33] } func test1(x [3]int) { x[0] = 111 fmt.Println(x) // [111 22 33] }
切片
切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。
切片是一个引用类型,它的内部结构包含地址、长度和容量。
// 定义 var name []T var a []int //声明一个切片 var a = []int{} // 申明一个切片并初始化 //切片只有初始化之后才能使用 //len()函数求长度 cap()函数求容量 var a = []int {1,2,3} fmt.Println(len(a)) // 3 fmt.Println(cap(a)) // 3 // 切片表达式 // 对于数组或字符串,如果0 <= low <= high <= len(a),则索引合法,否则就会索引越界(out of range) // 对切片再执行切片表达式时(切片再切片),high的上限边界是切片的容量cap(a),而不是长度,尽量在定义时就确定容量,防止在程序运行时增加 // 下面的代码会构造与简单切片表达式a[low: high]相同类型、相同长度和元素的切片。 // 会将得到的结果切片的容量设置为max-low。 // 在完整切片表达式中只有第一个索引值(low)可以省略;它默认为0。 a[low : high : max] func main() { a := [5]int{1, 2, 3, 4, 5} t := a[1:3:5] fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t)) } // t:[2 3] len(t):2 cap(t):4 // make函数构造切片 // T:切片的元素类型 size:切片中元素的数量 cap:切片的容量 make([]T, size, cap) func main() { a := make([]int, 2, 10) fmt.Println(a) //[0 0] fmt.Println(len(a)) //2 fmt.Println(cap(a)) //10 } // 代码中a的内部存储空间已经分配了10个,但实际上只用了2个。 容量并不会影响当前元素的个数,所以len(a)返回2,cap(a)则返回该切片的容量 //判断切片是否为空 len(s) == 0 // append为切片动态添加元素 var s []int append(s, 1) //go中没有删除切片元素的方法,需利用切片的特性来删除 func main() { a := []int{1,2,3,4} // 删除索引为2的元素 a = append(a[:2], a[3:]...) fmt.Println(a) // {1,2,4} } //从切片a中删除索引为index的元素,操作方法是 a = append(a[:index], a[index+1:]...) // 删除切片中的元素其实是把删除元素后面的元素向前一位复制一份 // 把长度修改为一样后,原来的值 s := []int{1, 2, 3} fmt.Println(s) // [1 2 3] fmt.Printf("%p \n",s) //0xc00009e140 s = append(s[:1], s[2:]...) fmt.Println(s) // [1 3] fmt.Printf("%p \n",s) //0xc00009e140 s = s[:3] fmt.Println(s) // [1 3 3] fmt.Printf("%p \n",s) //0xc00009e140
map
map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。map是无序的。
// 定义 map[KeyType]ValueType map 默认值为nil // 定义完成后需要进行初始化,cap表示容量 make(map[KeyType]ValueType, [cap]) //也可以在声明的时候填充元素 user := [string]string{ "a" : "1" "b" : "2" } // 判断某个key是否存在 func main() { scoreMap := make(map[string]int, 8) scoreMap["a"] = 10 scoreMap["b"] = 20 fmt.Println(scoreMap) fmt.Println(scoreMap["a"]) fmt.Printf("%T \n", scoreMap) v, ok := scoreMap["a"] if ok { fmt.Println(v) } else { fmt.Println("nonono") } } // map的遍历 func main() { scoreMap := make(map[string]int, 8) scoreMap["a"] = 10 scoreMap["b"] = 20 for k, v := range scoreMap { fmt.Println(k, v) } } //只需要key时 func main() { scoreMap := make(map[string]int, 8) scoreMap["a"] = 10 scoreMap["b"] = 20 for k := range scoreMap { fmt.Println(k) } } //只需要value时 func main() { scoreMap := make(map[string]int, 8) scoreMap["a"] = 10 scoreMap["b"] = 20 for _, v := range scoreMap { fmt.Println(v) } } // 删除键值对 func main() { scoreMap := make(map[string]int, 8) scoreMap["a"] = 10 scoreMap["b"] = 20 delete(scoreMap, "a") for k, v := range scoreMap { fmt.Println(k, v) } } // 按指定顺序遍历map func main() { var scoreMap = make(map[string]int, 10) for i := 0; i < 5; i++{ key := fmt.Sprintf("stu%02d", i) //生产str开头的字符串 value := rand.Intn(10) // 0-99的随机整数 scoreMap[key] = value } for k, v := range scoreMap { fmt.Println(k, v) } //stu01 7 //stu03 9 //stu04 1 //stu00 1 //stu02 7 // 取出map中的key存入切片中 var keys = make([]string, 0, 10) for key := range scoreMap{ keys = append(keys, key) } fmt.Println(keys) // [stu00 stu02 stu01 stu03 stu04] //对切片进行排序,用sort sort.Strings(keys) fmt.Println(keys) //[stu00 stu01 stu02 stu03 stu04] for _, key := range keys { fmt.Println(key, scoreMap[key]) } //stu00 1 //stu01 7 //stu02 7 //stu03 9 //stu04 1 }
元素类型为map的切片
func main() { // 元素类型为map的切片 var mapSlice = make([]map[string]int, 8 ,8) //只是完成了切片的初始化 fmt.Println(mapSlice[0] == nil) // true // 还需要完成map元素的初始化 mapSlice[0] = make(map[string]int, 8) mapSlice[0]["a"] = 1 fmt.Println(mapSlice) // [map[a:1] map[] map[] map[] map[] map[] map[] map[]] fmt.Printf("%T \n", mapSlice) //[]map[string]int }
值为切片的map
func main() { var sliceMap = make(map[string][]int, 8) //只初始化了map v, ok := sliceMap["haha"] if ok { fmt.Println(v) } else { sliceMap["haha"] = make([]int, 8) //完成切片的初始化 sliceMap["haha"][0] = 1 sliceMap["haha"][2] = 3 } fmt.Println(sliceMap) //map[haha:[1 0 3 0 0 0 0 0]] for k, v :=range sliceMap{ fmt.Println(k, v) } // haha [1 0 3 0 0 0 0 0] }
练习
// 写出结果
func main() { type Map map[string][]int m := make(Map) s := []int{1, 2} s = append(s, 3) // s={1,2,3} fmt.Printf("%+v\n", s) m["q1mi"] = s s = append(s[:1], s[2:]...) // 删除了s中索引为2的值,索引s={1,3} fmt.Printf("%+v\n", s) // s={1,3}
fmt.Printf("%+v\n", m["q1mi"]) // s{1,3,3} m["q1mi"]的长度是3,删除切片中的元素就是把后面的元素往前复制了一个,所以第三个还是3
}
//参考https://blog.csdn.net/qq_41580831/article/details/104055663
// 统计字符中单词出现的次数
func main() {
var s = "how do you do"
var wordCount = make(map[string]int, 10)
words := strings.Split(s, " ")
// 将s中的字符根据空格为区分,隔开写入words
fmt.Println(words)
for _, word := range words {
v, ok := wordCount[word]
if ok {
wordCount[word] = v + 1
} else {
wordCount[word] = 1
}
}
for k, v := range wordCount {
fmt.Println(k, v)
}
}
参考 https://www.liwenzhou.com/posts/Go/go_menu/ 整理记录