goland 语言--数组
一、数组的基本概念数组是固定长度、相同类型元素的有序集合。特点长度固定声明时必须指定长度之后不能改变元素类型相同所有元素必须是同一类型内存连续元素在内存中是连续存储的零值初始化声明后自动用零值初始化值类型赋值或传参会复制整个数组二、数组的声明和初始化2.1 基本声明方式package main import fmt func main() { // 方式1声明后赋值默认零值 var arr1 [5]int // 长度为5的int数组 fmt.Println(arr1:, arr1) // [0 0 0 0 0] // 方式2声明并初始化 var arr2 [3]int [3]int{1, 2, 3} fmt.Println(arr2:, arr2) // [1 2 3] // 方式3使用短变量声明 arr3 : [4]string{Go, Java, Python, C} fmt.Println(arr3:, arr3) // [Go Java Python C] // 方式4让编译器计算长度 arr4 : [...]int{1, 2, 3, 4, 5, 6} fmt.Println(arr4:, arr4) // [1 2 3 4 5 6] fmt.Println(arr4长度:, len(arr4)) // 6 // 方式5指定索引初始化 arr5 : [5]int{1: 20, 3: 40} fmt.Println(arr5:, arr5) // [0 20 0 40 0] // 方式6部分初始化其余为默认值 arr6 : [5]int{1, 2} fmt.Println(arr6:, arr6) // [1 2 0 0 0] }2.2 不同类型数组示例func arrayTypes() { // 整数数组 var intArr [3]int32 intArr[0] 100 intArr[1] 200 intArr[2] 300 // 浮点数数组 floatArr : [3]float64{3.14, 2.71, 1.618} // 字符串数组 stringArr : [3]string{Apple, Banana, Cherry} // 布尔数组 boolArr : [3]bool{true, false, true} // 结构体数组 type Point struct { X, Y int } structArr : [2]Point{ {X: 1, Y: 2}, {X: 3, Y: 4}, } fmt.Printf(intArr: %v\n, intArr) fmt.Printf(floatArr: %v\n, floatArr) fmt.Printf(stringArr: %v\n, stringArr) fmt.Printf(boolArr: %v\n, boolArr) fmt.Printf(structArr: %v\n, structArr) }三、数组的基本操作3.1 访问和修改元素func arrayOperations() { arr : [5]int{10, 20, 30, 40, 50} // 访问元素索引从0开始 fmt.Println(第一个元素:, arr[0]) // 10 fmt.Println(第三个元素:, arr[2]) // 30 fmt.Println(最后一个元素:, arr[len(arr)-1]) // 50 // 修改元素 arr[1] 99 fmt.Println(修改后:, arr) // [10 99 30 40 50] // 遍历数组 fmt.Println(\n 遍历数组 ) // 方式1for循环 for i : 0; i len(arr); i { fmt.Printf(arr[%d] %d\n, i, arr[i]) } // 方式2for-range循环推荐 for index, value : range arr { fmt.Printf(索引:%d, 值:%d\n, index, value) } // 方式3只获取值 for _, value : range arr { fmt.Printf(值:%d , value) } fmt.Println() // 方式4只获取索引 for index : range arr { fmt.Printf(索引:%d , index) } fmt.Println() }3.2 数组的属性和方法func arrayProperties() { arr : [5]int{1, 2, 3, 4, 5} // 获取长度 length : len(arr) fmt.Println(数组长度:, length) // 5 // 获取容量数组的容量等于长度 capacity : cap(arr) fmt.Println(数组容量:, capacity) // 5 // 数组类型包含长度信息 fmt.Printf(数组类型: %T\n, arr) // [5]int }四、多维数组4.1 二维数组func twoDimensionalArray() { // 声明二维数组 var matrix1 [3][3]int // 初始化二维数组 matrix2 : [3][3]int{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, } // 访问元素 fmt.Println(matrix2[1][2]:, matrix2[1][2]) // 6 // 修改元素 matrix2[0][0] 100 // 遍历二维数组 fmt.Println(\n 遍历二维数组 ) for i : 0; i len(matrix2); i { for j : 0; j len(matrix2[i]); j { fmt.Printf(%3d , matrix2[i][j]) } fmt.Println() } // 使用for-range遍历 fmt.Println(\n for-range遍历 ) for i, row : range matrix2 { for j, val : range row { fmt.Printf(matrix[%d][%d]%d , i, j, val) } fmt.Println() } }4.2 更多维度的数组func multiDimensionalArray() { // 三维数组 cube : [2][3][4]int{ { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, }, { {13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}, }, } fmt.Println(三维数组长度:) fmt.Println(第一维:, len(cube)) // 2 fmt.Println(第二维:, len(cube[0])) // 3 fmt.Println(第三维:, len(cube[0][0])) // 4 // 访问三维数组元素 fmt.Println(cube[1][2][3]:, cube[1][2][3]) // 24 }五、数组的内存特性5.1 数组是值类型func arrayValueType() { // 数组是值类型赋值会复制整个数组 arr1 : [3]int{1, 2, 3} arr2 : arr1 // 这里会发生数组的复制 fmt.Println(赋值前:) fmt.Println(arr1:, arr1) // [1 2 3] fmt.Println(arr2:, arr2) // [1 2 3] // 修改arr2不会影响arr1 arr2[0] 100 fmt.Println(\n修改arr2后:) fmt.Println(arr1:, arr1) // [1 2 3] 不变 fmt.Println(arr2:, arr2) // [100 2 3] // 比较数组只有相同长度和类型的数组才能比较 arr3 : [3]int{1, 2, 3} arr4 : [3]int{1, 2, 3} arr5 : [3]int{1, 2, 4} fmt.Println(\n数组比较:) fmt.Println(arr3 arr4:, arr3 arr4) // true fmt.Println(arr3 arr5:, arr3 arr5) // false fmt.Println(arr3 ! arr5:, arr3 ! arr5) // true }5.2 数组作为函数参数// 数组作为函数参数值传递会复制整个数组 func modifyArray(arr [5]int) { fmt.Println(函数内修改前:, arr) arr[0] 999 fmt.Println(函数内修改后:, arr) } // 使用指针传递数组避免复制 func modifyArrayByPointer(arr *[5]int) { fmt.Println(指针函数内修改前:, *arr) arr[0] 888 // 可以直接使用arr[0]不需要(*arr)[0] fmt.Println(指针函数内修改后:, *arr) } func testArrayFunctions() { arr : [5]int{1, 2, 3, 4, 5} fmt.Println(原始数组:, arr) // 值传递 modifyArray(arr) fmt.Println(值传递后原数组:, arr) // 不变 // 指针传递 modifyArrayByPointer(arr) fmt.Println(指针传递后原数组:, arr) // 改变 }六、数组的实用技巧6.1 数组切片操作func arraySliceOperations() { arr : [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} // 将数组转换为切片常用技巧 slice1 : arr[:] // 全部元素 slice2 : arr[3:] // 从索引3开始 slice3 : arr[:5] // 到索引5不包括 slice4 : arr[2:7] // 从索引2到7 fmt.Println(原数组:, arr) fmt.Println(arr[:]:, slice1) // [0 1 2 3 4 5 6 7 8 9] fmt.Println(arr[3:]:, slice2) // [3 4 5 6 7 8 9] fmt.Println(arr[:5]:, slice3) // [0 1 2 3 4] fmt.Println(arr[2:7]:, slice4) // [2 3 4 5 6] // 修改切片会影响原数组 slice4[0] 100 fmt.Println(\n修改切片后原数组:, arr) // arr[2]变为100 }6.2 数组填充和复制func arrayFillAndCopy() { // 使用循环填充数组 var squares [10]int for i : 0; i len(squares); i { squares[i] i * i } fmt.Println(平方数组:, squares) // 数组复制 source : [5]int{1, 2, 3, 4, 5} var dest [5]int // 方法1直接赋值复制整个数组 dest source fmt.Println(复制后dest:, dest) // 方法2使用copy函数需要先转为切片 var dest2 [5]int copy(dest2[:], source[:]) fmt.Println(copy函数复制后dest2:, dest2) // 数组反转 reverseArr : [6]int{1, 2, 3, 4, 5, 6} for i, j : 0, len(reverseArr)-1; i j; i, j i1, j-1 { reverseArr[i], reverseArr[j] reverseArr[j], reverseArr[i] } fmt.Println(反转后数组:, reverseArr) }七、数组的局限性和替代方案7.1 数组的局限性func arrayLimitations() { // 局限性1长度固定无法动态扩展 // arr : [3]int{1, 2, 3} // arr[3] 4 // 编译错误索引越界 // 局限性2不同长度的数组是不同类型 arr1 : [3]int{1, 2, 3} arr2 : [4]int{1, 2, 3, 4} fmt.Printf(arr1类型: %T\n, arr1) // [3]int fmt.Printf(arr2类型: %T\n, arr2) // [4]int // 以下代码会编译错误 // arr1 arr2 // 不能将[4]int赋值给[3]int // if arr1 arr2 { } // 不能比较[3]int和[4]int }7.2 数组 vs 切片func arrayVsSlice() { fmt.Println( 数组 vs 切片 ) // 数组值类型长度固定 array : [3]int{1, 2, 3} // 切片引用类型长度可变 slice : []int{1, 2, 3} fmt.Println(数组:, array, 类型:, reflect.TypeOf(array)) fmt.Println(切片:, slice, 类型:, reflect.TypeOf(slice)) // 修改测试 modifyArrayFunc : func(a [3]int, s []int) { a[0] 100 s[0] 100 } fmt.Println(\n调用函数前:) fmt.Println(array:, array) // [1 2 3] fmt.Println(slice:, slice) // [1 2 3] modifyArrayFunc(array, slice) fmt.Println(\n调用函数后:) fmt.Println(array:, array) // [1 2 3] 不变 fmt.Println(slice:, slice) // [100 2 3] 改变 }八、总结要点数组特性固定长度声明时确定值类型赋值会复制内存连续访问速度快使用场景数据长度固定且已知需要高性能访问栈空间分配小数组作为切片的基础存储最佳实践小数组直接在栈上分配性能好大数组考虑使用切片函数参数传递大数组时使用指针优先使用for-range遍历常见错误访问越界编译时检查不同类型数组赋值忘记数组是值类型------------------------------------------数组常用的就是上面的了还想再学点东西可以看看这个https://blog.csdn.net/dusk_star/article/details/155576705?fromshareblogdetailsharetypeblogdetailsharerId155576705sharereferPCsharesourcedusk_starsharefromfrom_link