切片
# 定义 切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用 数组定长,长度不能改变---》python中列表----》go切片 # 知识点 1 创建一个切片(通过数组创建) 2 使用 make 创建一个切片 3 切片的修改 4 切片的长度和容量 5 追加切片元素 6 切片的函数传递 7 多维切片 8 内存优化 —————————————————————————————————— package main import "fmt" // 切片 func main() { // 1 创建一个切片(通过数组创建) var a [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 切片--->从a数组上,从0到结尾,切片赋值给s //var s = a[:] var s []int = a[:] fmt.Println(s) // 查看类型--->中括号中没有数字-->就是切片,有数字就是数组 // 区分数组(值)和切片(引用)类型 fmt.Printf("s的类型是:%T\n", s) // []int // 2 使用 make 创建一个切片-->必须通过make或通过数组切出来,否则是空的 var s1 []string = make([]string, 4) fmt.Println(s1) // 3 切片零值 // 3.1 通过数组切出来,不会为 空 // 3.2 如果只定义,没有初始化--》零值---》空---》nil var s2 []string fmt.Println(s2) // [] // 4 操作切片---》取值,赋值---》使用 [数字] s1[0] = "lqz" s1[1] = "彭于晏" fmt.Println(s1) s1[0] = "ssdfasdf" fmt.Println(s1) // 5 如果切片为 空,nil--》没有初始化 不能使用(取值赋值) s2 = make([]string, 1) // 不是nil了,但是长度为0 if s2 == nil { // python 的None fmt.Println("s2不能初始化,不能使用") return } s2[0] = "lqz" // s2没有初始化,报错 index out of range [0] with length 0 fmt.Println(s2) // 使用切片 s1[0]---》报index out of range [0] with length 0--》两个原因:1 nil 2 长度不够 // 6 切片的长度和容量 // 长度:切片放了几个值 // 容量:切片总共能放几个值 var a1 [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} var s3 []int = a1[2:3] fmt.Println(s3) // [6 7] 前闭后开区间 fmt.Println(len(s3)) // len 长度 2 fmt.Println(cap(s3)) // cap 容量 5 切片基于底层数组,容量取决于底层数组--》从切片起始位置到数组最后 var s4 = make([]int, 2, 4) fmt.Println(len(s4)) // 2 fmt.Println(cap(s4)) // 4 // 7 追加切片元素 // s4 长度是2,容量是4,还能追加俩值 s4 = append(s4, 99) // 内置函数追加--->s4不是对象 fmt.Println(s4) fmt.Println(len(s4)) // 3 fmt.Println(cap(s4)) // 4 s4 = append(s4, 88) // 内置函数追加--->s4不是对象 fmt.Println(s4) fmt.Println(len(s4)) // 4 fmt.Println(cap(s4)) // 4 // 超过容量,再追加---》不会报错---》 s4 = append(s4, 77) // 内置函数追加--->s4不是对象 fmt.Println(s4) fmt.Println(len(s4)) // 5 fmt.Println(cap(s4)) // 8---》翻倍扩容 s4 = append(s4, 66, 55, 44, 33) // fmt.Println(s4) fmt.Println(len(s4)) // 9 fmt.Println(cap(s4)) // 16---》翻倍扩容 s4 = append(s4, 22, 11, 12, 13, 11, 12) // fmt.Println(s4) fmt.Println(len(s4)) // 16 fmt.Println(cap(s4)) // 16---》翻倍扩容-->32 //8 切片的函数传递 切片是引用类型 test001(s4) // [0 0 99 88 77 66 55 44 33 22 11 12 13 11 12 13] fmt.Println("外部:", s4) // 函数内修改,会影响原来的值 // 很深的坑: s4 长度和容量 都是16 当参数传到函数中,修改,会不会影响原来的? test002(s4) fmt.Println("外部:", s4) // 函数内修改,会影响原来的值 /* 1 因为切片依赖于底层数组 2 底层数组的改变会影响切片,切片的改变也会影响底层数组 3 当使用append追加上,如果超过了切片容量--》切片会扩容--》重新创建一个数组--》把原来的值复制过去--》容量翻倍了--》切片指向新的数组 4 如果当参数传递,再函数中,使用append 1 超过容量,只要超过后,再修改某个位置的值,就不会相互影响了 2 如果没有超过容量,再修改某个位置的值,会相互影响了 */ // 9 多维切片 var s5 [][]int = make([][]int, 2, 3) //s5[0]=1 s5[0] = make([]int, 3) // 内层切片使用,也要初始化 s5[0][0] = 99 // 报错了---》内层的切片,没有通过make初始化出来,不能用 fmt.Println(s5) var s6 [][3]int = make([][3]int, 2, 3) fmt.Println(s6[0]) s6[0][0] = 99 fmt.Println(s6) // 多维切片,第n层,要不要初始化,取决于第n层是什么类型 // 定义并赋初值 var s7 [][]string = [][]string{{"lqz", "小红"}, {"asfd"}, {"111", "22", "333", "444"}} //var s7 [][4]string = [][4]string{{"lqz", "小红"}, {"asfd"}, {"111", "22", "333", "444"}} fmt.Println(s7[0][1]) fmt.Println(len(s7[2])) // 1 fmt.Println(cap(s7[2])) // 1 //fmt.Println(s7[2][4]) // 越界了 //fmt.Println(s7[0][2]) // 数组不会越界,切片就会越界 s7[0] = append(s7[0], "中") fmt.Println(len(s7[0])) // 3 fmt.Println(cap(s7[0])) // 4 // 10 内存优化 copy函数 var a3 [100]int fmt.Println(a3) var s8 []int = a3[0:3] fmt.Println(s8) s8[0] = 88 fmt.Println(s8) fmt.Println(a3) a3[1] = 66 fmt.Println(s8) fmt.Println(a3) //s8 拷贝到小一点的切片上(底层数组小) ---》可以大可以小 var s9 = make([]int, 5, 5) copy(s9, s8) fmt.Println(s9) // 长度和容量,都是3--》以后操作s9-->传参,修改---》底层数组只有3的大小---》内存空间占用小 } func test001(s []int) { s[0] = 999 fmt.Println(s) } func test002(s []int) { s[0] = 999 fmt.Println(s) // 如果,再内部,append--——》追加--》超过容量--》放弃掉底层数组---》新创建一个新数组--》指向新数组 s = append(s, 666) fmt.Println("内部", s) s[0] = 888 fmt.Println("内部", s) }
可变长参数
package main import "fmt" // 可变长参数 func main() { // * ** 放在形参上 // *:接收任意长度的位置参数 // ** 接收任意长度的关键字参数 // * ** 放在实参上--》* 只能放在列表上, ** 只能放在字典上 // go 只有按位置传参数---》没有按关键字这种用法 test003(33, 44, "9") // 传任意长度参数 //fmt.Println(1,2,3,4,5,"dafas") test004("11", "22", "14", "15", "16", "17", "18", "19") var ss1 [5]string = [5]string{"lqz", "彭于晏", "刘亦菲"} test004(ss1[:]...) // 打散了传入 // 思考题 welcome := []string{"hello", "world"} // 长度是2,容量是2 //welcome := make([]string,3,4) // change(welcome...) // 内部本质就是把 welcome 给了 s fmt.Println(welcome) // {"Go", "world"} } func test003(a, b int, c string) { fmt.Println(a, b, c) } func test004(a ...string) { fmt.Println(a) // 可以传任意长度字符串===>a是什么类型?字符串类型? 字符串切片类型 []string fmt.Printf("a的类型是:%T", a) //for i := 0; i < len(a); i++ { // fmt.Println(a[i]) //} for _, value := range a { fmt.Println(value) } } func change(s ...string) { s[0] = "Go" s = append(s, "playground") fmt.Println(s) // [Go world playground] s[0] = "lqz" fmt.Println(s) // [lqz world playground] }
map
# 数组,切片,map 容器类型 # map 是在 Go 中将值(value)与键(key)关联的内置类型。通过相应的键可以获取到值 如何创建 map 给 map 添加元素 获取 map 中的元素 删除 map 中的元素 获取 map 的长度 Map 是引用类型 Map 的相等性
hash冲突
# python中的字典 # go中得map # redis中得 hash # java中得 HashMap,TreeMap # 1 就是根据key即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经有人先来了 就是相当于你在蹲坑,又有人进来了,但是只有一个坑,就产生了冲突,需要开辟新的空间去让另一个人有地方上厕所 # 2 解决hash冲突 1 开放寻址法 1.1 线性探测 按顺序决定值时,如果某数据的值已经存在,则在原来值的基础上往后加一个单位,直至不发生哈希冲突。 就是在此空间不足时,直接放入此空间的后一个空的空间 1.2 伪随机探测 2 再哈希法(Rehashing): 使用另一个哈希函数处理冲突 3 链地址法(java的hashmap): - 对于相同的值,使用链表进行连接。使用数组存储每一个链表 4 建立公共溢出区
标签:---,--,fmt,s4,切片,Println,go From: https://www.cnblogs.com/wzh366/p/18119679