目录
数组、切片
- 由于太长(存在习题)放到了文章最后
- ps: 这一章主要都花在了练习题上Orz, 熟悉又陌生的编程语言, 果然不能想当然的去认为一些事情…
1.数组
1.1如何定义数组
数组是具有相同类型且长度固定的一组连续数据。在go语言中我们可以使用如下几种方式来定义数组。
func part1() {
// 定义
var arr1 = [5]int{
}
var arr2 = [5]int{
1,2,3,4,5}
var arr3 = [5]int{
3:10}
fmt.Println(arr1) // [0 0 0 0 0] 在声明时没有为其指定初值,所以数组内的值被初始化为类型的零值。
fmt.Println(arr2) // [1 2 3 4 5] 使用显示的方式为数组定义初值。
fmt.Println(arr3) // [0 0 0 10 0] 通过下标的方式为下标为3的位置赋上了初值10
// 数组的定义是包含其长度的,也就是说[3]int与[4]int是两种不同的数据类型。
var test1 = [3]int{
}
var test2 = [4]int{
}
fmt.Printf("%T %T", test1, test2) // [3]int [4]int
}
1.2如何操作数据
在上面的arr1我们没有为其指定初值,那么之后我们可以通过循环的方式为其赋予初值
func part2() {
var arr1 =[5]int{
}
fmt.Println("before: ", arr1)
// 通过下标赋值 -> for循环遍历 // before: [0 0 0 0 0]
for i := 0; i < len(arr1); i++ {
arr1[i] = i * 10
}
fmt.Println("after: ", arr1) // after: [0 10 20 30 40]
// for循环输出
for index, value := range arr1 {
// index 可用 _ 省略
fmt.Println("index: ", index, " value: ", value)
}
/*
index: 0 value: 0
index: 1 value: 10
index: 2 value: 20
index: 3 value: 30
index: 4 value: 40
*/
}
1.3多维数组
与其他语言一样,go语言也可以定义多维数组,可以选择的定义方式如下:
func part3() {
// 多维数组
var arr4 = [9][9]int {
}
// 赋值
for i:=1; i<=9; i++ {
for j:=1; j<=9; j++ {
arr4[i-1][j-1] = i * j
}
}
// 输出
for i:=1; i<=9; i++ {
fmt.Println(arr4[i-1])
}
/*
[1 2 3 4 5 6 7 8 9]
[2 4 6 8 10 12 14 16 18]
[3 6 9 12 15 18 21 24 27]
[4 8 12 16 20 24 28 32 36]
[5 10 15 20 25 30 35 40 45]
[6 12 18 24 30 36 42 48 54]
[7 14 21 28 35 42 49 56 63]
[8 16 24 32 40 48 56 64 72]
[9 18 27 36 45 54 63 72 81]
*/
}
1.3数组作为函数参数
go语言在传递数组时会对其进行拷贝,所以如果传递的是大数组的话会非常占内存,所以一般情况下很少直接传递一个数组,避免这种情况我们可以使用以下两种方式:
- 传递数组的指针
- 传递切片(具体内容见下一小节)
// 直接传递
调用:
var arr5 = [2]int{
1, 2}
fmt.Println("调用前", arr5) //调用前 [1 2]
part5(arr5)
fmt.Println("调用后", arr5) //调用后 [1 2]
func part5(arr [2]int){
fmt.Println("进入part5") //进入part5
fmt.Println(arr) //[1 2]
arr[0] = arr[1]
fmt.Println(arr) //[2 2]
fmt.Println("退出part5") //退出part5
}
//传递数组指针
调用:
var arr5 = [2]int{
1, 2}
fmt.Println("调用前", arr5) //调用前 [1 2]
part6(&arr5)
fmt.Println("调用后", arr5) //调用后 [2 2]
func part6(arr *[2]int){
fmt.Println("进入part6") //进入part6
fmt.Println(arr) //[1 2]
arr[0] = arr[1]
fmt.Println(arr) //[2 2]
fmt.Println("退出part6") //退出part6
}
- 可以看出用指针传就可以避免拷贝
1.4指针数组与数组指针
对于指针数组和数组指针在c或c++中也经常被讨论,尤其对于初学者来说会分辨不清楚。其实在每个词中间添加一个“的“就很好理解了,指针的数组,数组的指针。
1.指针数组
对于指针数组来说,就是:一个数组里面装的都是指针,在go语言中数组默认是值传递的,所以如果我们在函数中修改传递过来的数组对原来的数组是没有影响的。
func main() {
var a [5]int
fmt.Println(a)
test(a)
fmt.Println(a)
}
func test(a [5]int) {
a[1] = 2
fmt.Println(a)
}
输出
[0 0 0 0 0]
[0 2 0 0 0]
[0 0 0 0 0]
但是如果我们一个函数传递的是指针数组,情况会有什么不一样呢?
func main() {
var a [5]*