《go 学习笔记之数组还是切片都没什么不一样.docx》由会员分享,可在线阅读,更多相关《go 学习笔记之数组还是切片都没什么不一样.docx(19页珍藏版)》请在金锄头文库上搜索。
1、go 学习笔记之数组还是切片都没什么不一样上篇文章中详细介绍了 Go 的基础语言,指出了 Go 和其他主流的编程语言的差异性,比较侧重于语法细节,相信只要稍加记忆就能轻松从已有的编程语言切换到 Go 语言的编程习惯中,尽管这种切换可能并不是特别顺畅,但多加练习尤其是多多试错,总是可以慢慢感受 Go 语言之美!在学习 Go 的内建容器前,同样的,我们先简单回顾一下 Go 的基本语言,温度而知新可以为师矣!上节知识回顾如需了解详情,请于微信公众号雪之梦技术驿站内查看 go 学习笔记之值得特别关注的基础语法有哪些 文章,觉得有用的话,顺手转发一下呗!内建类型种类 bool布尔类型,可选 true|f
2、alse,默认初始化零值 false . (u)int ,(u)int8 , (u)int16, (u)int32,(u)int64,uintptr20=1,21=2 ,22=4 个字节长度的整型,包括有符号整型和无符号整型以及 uintptr 类型的指针类型,默认初始化零值 0 . byte(uint8) ,rune(int32),stringbyte 是最基础字节类型,是 uint8 类型的别名,而 rune 是 Go 中的字符类型,是 int32 的别名.最常用的字符串类型 string 应该不用介绍了吧? float32 ,float64 ,complex64 ,complex128只
3、有 float 类型的浮点型,没有 double 类型,同样是以字节长度来区分,complex64 是复数类型,实部和虚部由 float32 类型复合而成,因此写作 complex64 这种形式.内建类型特点 类型转换只有显示转换,不存在任何形式的隐式类型转换不同变量类型之间不会自动进行隐式类型转换,Go 语言的类型转换只有强制的,只能显示转换. 虽然提供指针类型,但指针本身不能进行任何形式的计算.指针类型的变量不能进行计算,但是可以重新改变内存地址的指向. 变量声明后有默认初始化零值,变量零值视具体类型而定int 类型的变量的初始化零值是 0,string 类型的初始化零值是空字符串,并不是
4、 nil基本运算符 算术运算符没有 +i 和-i只有 i+ 和 i- 这种自增操作,再也不用担心两种方式的差异性了! 比较运算符 = 可以比较数组是否相等当两个数组的维度和数组长度相等时,两个数组可以进行比较,顺序完全一致时,结果为 true,其他情况则是 false . 位运算符新增按位清零运算符 &其他主流的编程语言虽然没有这种操作符,通过组合命令也可以实现类似功能,但既然提供了按位清零运算符,再也不用自己进行组合使用了!流程控制语句 if 条件表达式不需要小括号并支持变量赋值操作先定义临时变量并根据该变量进行逻辑判断,然后按照不同情况进行分类处理,Go 处理这种临时变量的情况,直接对条件
5、表达式进行增强,这种情况以后会很常见! if 条件表达式内定义的变量作用域仅限于当前语句块条件表达式内定义的变量是为了方便处理不同分支的逻辑,既然是临时变量,出了当前的 if 语句块就无法使用,也变得可以理解. switch 语句可以没有 break,除非使用了 fallthroughswitch 语句的多个 case 结尾处可以没有 break,系统会自动进行 break 处理. switch 条件表达式不限制为常数或整数和其他主流的编程语言相比,Go 语言的 switch 条件表达式更加强大,类型也较为宽松. switch 条件表达式可以省略,分支逻辑转向 case 语言实现.省略 swi
6、tch 条件表达式,多个 case 语言进行分支流程控制,功能效果和多重 if else 一样. 省略 switch 条件表达式后,每个 case 条件可以有多个条件,用逗号分隔.swicth 语句本质上是根据不同条件进行相应的流程控制,每个 case 的条件表达式支持多个,更是增强了流程控制的能力. for 循环的条件表达式也不需要小括号,且没有其他形式的循环.Go 语言只有 for 循环,没有 while 等其他形式的循环. for 循环的初始条件,终止条件和自增表达式都可以省略或者同时省略条件表达式进行省略后可以实现 while 循环的效果,全部省略则是死循环.函数和参数传递 函数声明按
7、照函数名,入参,出参顺序定义,并支持多返回值不论是变量定义还是函数定义,Go 总是和其他主流的编程语言反着来,如果按照输入输出的顺序思考就会发现,这种定义方式其实挺有道理的. 函数有多个返回值时可以给返回值命名,但对调用者而言没有差别函数返回多个值时可以有变量名,见名知意方便调用者快速熟悉函数声明,但调用者并非一定要按照返回值名称接收调用结果. 函数的入参没有必填参数,可选参数等复杂概念,只支持可变参数列表可变参数列表和其他主流的编程语言一样,必须是入参的最后一个. 函数参数传递只有值传递,没有引用传递,即全部需要重新拷贝变量参数传递只有值传递,逻辑上更加简单,但是处理复杂情况时可以传递指针实
8、现引用传递的效果.内建容器有哪些复习了 Go 语言的基础语法后,开始继续学习变量类型的承载者也就是容器的相关知识.承载一类变量最基础的底层容器就是数组了,大多数高级的容器底层都可以依靠数组进行封装,所以先来了解一下 Go 的数组有何不同?数组和切片 数组的声明和初始化数组的明显特点就是一组特定长度的连续存储空间,声明数组时必须指定数组的长度,声明的同时可以进行初始化,当然不指定数组长度时也可以使用 . 语法让编译器帮我们确定数组的长度.func TestArray(t *testing.T) var arr1 3int arr2 := 5int1, 2, 3, 4, 5 arr3 := .in
9、t2, 4, 6, 8, 10 / 0 0 0 1 2 3 4 5 2 4 6 8 10 t.Log(arr1, arr2, arr3) var grid 34int / 0 0 0 0 0 0 0 0 0 0 0 0 t.Log(grid)3int 指定数组长度为 3,元素类型为 int,当然也可以声明时直接赋值 5int1, 2, 3, 4, 5 ,如果懒得指定数组长度,可以用 .int2, 4, 6, 8, 10 表示. 数组的遍历和元素访问最常见的 for 循环进行遍历就是根据数组的索引进行访问,range arr 方式提供了简化遍历的便捷方法.func TestArrayTraver
10、se(t *testing.T) arr := .int2, 4, 6, 8, 10 for i := 0; i len(arr); i+ t.Log(arri) for i := range arr t.Log(arri) for i, v := range arr t.Log(i, v) for _, v := range arr t.Log(v) range arr 可以返回索引值和索引项,如果仅仅关心索引项而不在乎索引值的话,可以使用 _ 占位符表示忽略索引值,如果只关心索引值,那么可以不写索引项.这种处理逻辑也就是函数的多返回值顺序接收,不可以出现未使用的变量. 数组是值类型可以进行
11、比较数组是值类型,这一点和其他主流的编程语言有所不同,因此相同纬度且相同元素个数的数组可以比较,关于这方面的内容前面也已经强调过,这里再次简单回顾一下.func printArray(arr 5int) arr0 = 666 for i, v := range arr fmt.Println(i, v) func TestPrintArray(t *testing.T) var arr1 3int arr2 := 5int1, 2, 3, 4, 5 arr3 := .int2, 4, 6, 8, 10 / 0 0 0 1 2 3 4 5 2 4 6 8 10 t.Log(arr1, arr2,
12、 arr3) / cannot use arr1 (type 3int) as type 5int in argument to printArray /printArray(arr1) fmt.Println(printArray(arr2) printArray(arr2) fmt.Println(printArray(arr3) printArray(arr3) / 1 2 3 4 5 2 4 6 8 10 t.Log(arr2, arr3)因为参数传递是值传递,所以 printArray 函数无法更改调用者传递的外部函数值,如果想要在函数 printArray 内部更改传递过来的数组内
13、容,可以通过指针来实现,但是有没有更简单的做法?想要在 printArrayByPointer 函数内部修改参数数组,可以通过数组指针的方式,如果有不熟悉的地方,可以翻看上一篇文章回顾查看.func printArrayByPointer(arr *5int) arr0 = 666 for i, v := range arr fmt.Println(i, v) func TestPrintArrayByPointer(t *testing.T) var arr1 3int arr2 := 5int1, 2, 3, 4, 5 arr3 := .int2, 4, 6, 8, 10 / 0 0 0
14、1 2 3 4 5 2 4 6 8 10 t.Log(arr1, arr2, arr3) fmt.Println(printArrayByPointer(arr2) printArrayByPointer(&arr2) fmt.Println(printArrayByPointer(arr3) printArrayByPointer(&arr3) / 666 2 3 4 5 666 4 6 8 10 t.Log(arr2, arr3)修改数组的元素可以通过传递数组指针来实现,除此之外,Go 语言中数组还有一个近亲 slice,也就是切片,它可以实现类似的效果. 切片的声明和初始化切片和数组非常类似,创建数组时如果没有指定数组的长度,那么最终创建的其实是切片并不是数组.func TestSliceInit(t *testing.T) var s1 5int /