//数组:数组是同一类型元素的集合,在内存中连续存放 package main import "fmt" func main() { //1 基本使用:定义 //定义了一个大小为3的int类型数组 //数组在定义阶段,大小和类型就固定了 //var a [3]int //只定义,没有初始化 //fmt.Println(a) //2 使用数组(从0开始) //var a [3]int //a[2]=100 //fmt.Println(a) //fmt.Println(a[0]) //3 定义并赋初值 //var a [3]int=[3]int{1,2,3} //var a =[3]int{1,2,3} //a := [3]int{1, 2, 3} //只给第2个位置设为99 //a := [3]int{2:99} ////进阶版 //a := [3]int{2:99,1:88} //fmt.Println(a) //4 数组的大小是类型的一部分 //这两个不是一个类型 //var a [2]int //var b [3]int //a=b //fmt.Println(a>b) //5 数组是值类型(当参数传递到函数中,修改不会改变原来的值) // go语言中,都是copy传递 /* python中都是引用传递,一切皆对象,就是地址,当做参数传递是把地址传过去了 python中比较特殊:可变类型和不可变类型 */ a :=[3]int{5,6,7} fmt.Println(a) test1(a) fmt.Println(a) func test1(a [3]int){ // 值类型传参为copy,内部修改不会改变原来的 a[0] = 999 fmt.Println(a) } //6 数组长度(len) //var a [3]int=[3]int{5,6,7} //fmt.Println(len(a)) //7 循环数组 //方式一 //var a [3]int=[3]int{5,6,7} //for i:=0;i<len(a);i++{ // fmt.Println(a[i]) //} //方式二 //range:是一个关键字 //var a [3]int=[3]int{5,6,7} //for i,v:=range a{ // fmt.Println(i) //索引 // fmt.Println(v) //数组的值 //} //函数如果返回两个值,必须用两个值来接收 //range是关键字,可以用一个值来接收,如果用一个值来接收,就是索引 //for i:=range a{ // fmt.Println(i) //索引 //} //只取值,不取索引 //for _,v:=range a{ // fmt.Println(v) //值 //} //8 多维数组 //定义一个二维数组 //var a [3][2]int //定义并初始化 var a [3][2]int=[3][2]int{{1,2},{4,5},{9,70}} //a[1][0]=999 fmt.Println(a) //两种方式循环出二维数组 } func test1(a [3]int) { a[0]=999 fmt.Println(a) }
//切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用。 //切片底层依附于数组,无法删除元素 package main import "fmt" func main() { //1 创建切片(基于一个数组创建) //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9} ////2 基于数组,切出一部分成为切片 //// []int 中括号中没有东西,就是切片 //var b []int //// 没有-1 没有步长 // //b=a[0:3] //前闭后开 ////b=a[3:6] //前闭后开 ////b=a[:] //前闭后开 从头切到尾 ////b=a[3:] //前闭后开 //fmt.Println(b) // ////2 使用切片 //fmt.Println(b[0]) //3 切片的修改会影响底层数组,数组的修个也会影响切片 //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9} //var b []int=a[0:3] //前闭后开 // //fmt.Println(a) // [1 2 3 4 5 6 7 8 9] //fmt.Println(b) // [1 2 3] //a[0]=999 //b[2]=888 //fmt.Println(a) // [999 2 888 4 5 6 7 8 9] //fmt.Println(b) // [999 2 888] // 4 切片的长度和容量 //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9} // //var b []int=a[2:3] //前闭后开 //fmt.Println(len(b)) ////切片容量是9,意思是,可以往里追加值,追加成9个 //fmt.Println(cap(b)) // ////容量就是原数组的长度呗?对不对?不太对。。 //b[0]=9999 //fmt.Println(a) //fmt.Println(b) //5 追加值 //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9} //var b []int=a[2:3] //前闭后开 //b=append(b,1) //b=append(b,11,22,33,44,55) //fmt.Println(len(b)) //fmt.Println(cap(b)) // 容量是7 //fmt.Println(b) //fmt.Println(a) //到了数组的尾部,继续追加值 //b=append(b,999) //fmt.Println(len(b)) //fmt.Println(cap(b)) //容量是14 ////总结1:当切片追加值,超过了切片容量,切片容量会翻倍,在原来容量基础上乘以2 ////b=append(b,222,333,444,555,666,7,8) ////fmt.Println(len(b)) ////fmt.Println(cap(b)) //容量是14 // ////总结2:一旦超过了原数组, 就会重新申请数组,把数据copy到新数组,切片和原数组就没有关系了 //fmt.Println(a) //fmt.Println(b) //a[8]=7777 // 不会影响b数组 //fmt.Println(a) //fmt.Println(b) //6 通过make创建切片(底层也依附于数组) 只能定义,不能赋初值 //var a []int //切片零值是什么? nil类型:是所有引用类型的空值 //fmt.Println(a) //if a==nil{ // fmt.Println("我是空的") //} //3是长度,4是容量 //var a []int=make([]int,3,4) //3是长度,3是容量 //var a []int=make([]int,3) //fmt.Println(a) //if a==nil{ // fmt.Println("我是空的") //} // //fmt.Println(len(a)) //fmt.Println(cap(a)) // //a=append(a,55) //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //6 切片定义并赋初值 //var a []int=[]int{1,2,3} //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //7 切片是引用类型,当参数传递,会修改掉原来的值 //var a []int=[]int{1,2,3} //fmt.Println(a) //test3(a) //fmt.Println(a) //8 多维切片 //var a [][]int=make([][]int,2,3) // 创建出第一层切片实例化,第二层并未实例化 //fmt.Println(a) //fmt.Println(a[0]==nil) ////会报错 ////a[0][0]=999 //// 如何做?(for循环完成初始化) // //a[0]=make([]int,2,3) //a[0][1]=999 //fmt.Println(a) //a[1][0]=99999 //定义并赋初值用的多 //var a [][]int=[][]int{{1,2,3},{4,5,6,7,7,8}} ////跟上面不一样 切片为 个数为3的int类型数组 //var a [][3]int=[][3]int{{1,2,3},{4,5,6}} //fmt.Println(a) //9 切片的copy //var a []int=make([]int,3,4) //var b []int=make([]int,2,6) //a[0]=11 //a[1]=22 //a[2]=33 //b[0]=999 //fmt.Println(a) //fmt.Println(b) // //copy(b,a) // 目标 源 a中部分会覆盖b //fmt.Println(b) // [11,22] 因为长度限制,取前两个 //10 切片越界 //var a []int=make([]int,3,4) //a[0]=11 //a[1]=22 //a[2]=33 // //a=append(a,999) ////中括号取值,只能取到长度值,不能取到容联大小 //fmt.Println(a[3]) // 11 切片循环 // 方式一 var a []int=make([]int,3,4) //for i:=0;i<len(a);i++ { // fmt.Println(a[i]) //} // 方式二 for i,v:=range a{ fmt.Println(i) fmt.Println(v) } } func test3(a []int) { a[0]=999 fmt.Println(a) }
//maps:hash,字典, key:value存储 package main import "fmt" func main() { //1 map的定义和使用 //map[key类型]value类型:key的类型必须可hash,key值:数字,字符串 //map的零值:nil 它是一个引用类型 //var a map[int]string //fmt.Println(a) //if a==nil{ // fmt.Println("我是空的") //} //2 定义了,没有初始化,使用 //var a map[int]string //初始化用make //var a map[int]string=make(map[int]string) ////如果有,会修改,如果没有,会放入 //a[1]="lqz" //a[1]="egon" //a[2]="99" // ////a["xx"] key值不能乱写 // //fmt.Println(a) //3 获取元素 //var a map[int]string=make(map[int]string) ////var a map[int]int=make(map[int]int) //fmt.Println(a[0]) //取出value值的空值 "" //fmt.Println(a) //统一的方案来判断value值是否存在 //a[0] 可以返回两个值,一个是value值(可能为空),另一个是true或false(未赋值为false) //var a map[int]int=make(map[int]int) //a[0]=0 //v,ok:=a[0] // 因为已赋值,所以ok为true //fmt.Println(v) //fmt.Println(ok) //4 map 删除元素 //var a map[int]int=make(map[int]int) //a[1]=11 //a[2]=22 //fmt.Println(a) ////根据key删(内置函数) //delete(a,1) //fmt.Println(a) //5 map 长度 //var a map[int]int=make(map[int]int) //fmt.Println(len(a)) //a[1]=11 //a[2]=22 //fmt.Println(len(a)) //6 map 是引用类型 //var a map[int]int=make(map[int]int) //a[1]=11 // //test4(a) //fmt.Println(a) //7 Map 的相等性 //var a map[string]string=make(map[string]string) //a["name"]="lqz" //var b map[string]string=make(map[string]string) //b["name"]="lqz" // ////不能这样判断,map只能跟nil比较 //// if a==b{} // 因为map是引用类型,这样相当于比较两个地址,不支持直接这样比 //if a==nil { // //} //8 循环map var a map[string]string=map[string]string{"name":"lqz","age":"19","sex":"男"} // 赋初值 //搞不了 //for i:=0;i<len(a) ; i++ { // fmt.Println(a[i]) // //} //range循环 只能借助range for k,v:=range a{ fmt.Println(k) fmt.Println(v) } // 9 map是无序的(python中字典从3.6以后有序了,3.6之前无序,底层如何实现的,看博客) // https://www.cnblogs.com/xiaoyuanqujing/articles/12008689.html } func test4(a map[int]int) { a[1]=999 fmt.Println(a) }
切片当参数传递问题
//切片传递问题 package main import "fmt" func main() { //var a[]int=[]int{1,2,3} var a []int = make([]int, 2, 4) a[0] = 1 a[1] = 2 fmt.Println(a) fmt.Println(cap(a)) test(a) fmt.Println(a) // [999 2] } func test(a []int) { a[0] = 999 fmt.Println(a) a = append(a, 66) fmt.Println(a) // [999 2 66] } // 在go语言中素有参数传递都是copy传递 /* 切片{ Length int 切片长度 Capacity int 切片容量 ZerothElement *byte 指向底层数组的指针 } copy了一份,append追加 两个切片引用的地址相同,但是是两个切片 切片{ Length int 长度+1 // 至此,两个切边不同了 Capacity int 切片容量 ZerothElement *byte 指向底层数组的指针 } */
总结:
// 1 前后端混合开发项目(DTL),在后端通过模板语言渲染成用户看到的html页面 // 2 前后端分离(restful规范),xml格式,json //3 数组切片maps //4 数组:连续存储,同一种元素的集合 -var a [4]int=[4]int{1,2,3,4} -a[4] 报错 -数组是值类型(默认值:数组类型的0值) -循环数组 两种方式 range -多维数组:var a [3][4]string 取值,赋值 a[][] -这种定义方式 a:=[...]int{1,2,3} // ...数组元素可以任意定义,但是定义完长度是固定的 //5 切片:本身不存储数据,是对底层数组的引用(数组和切片变化会相互影响) -基于数组切出来 a[:] -容量和长度 len cap -切片追加 append(切片,切片存储类型的元素) -超出容量,重写申请一个两倍容量的数组,依附于这个数组(容量翻倍) -引用类型(空值:nil) -切片当做参数传递到函数中,在函数中调用append,会怎么样? -循环 -多维切片 -make创建切片 -定义并初始化,创建切片 var a []int =[]int{1,2,3,4,5,5,6,7,8,8,9} //6 map:字典,hash -var a map[key类型]value的类型 -空值:nil类型,引用类型 -初始化: -make(map[key类型]value的类型) // var a map[int]string=make(map[int]string,10) 定义初始长度,提高性能 -var a map[key类型]value的类型 =map[key类型]value的类型{key:value,key:value} -取值,赋值 -取值如果没有 v,ok:=a[key] -长度 len -循环 for k,v:=range map{} -map比较,只能跟nil比较 -删除:内置函数delete