数组是指一系列同一类型数据的集合。 数组中包含的每个数据被称为数组元素(element), 一个数组包含的元素个数被称为数组的长度。
数组的长度必须是常量, 且是类型的组成部分。[2]int 和 [3]int 是不同类型
var n int = 10;var a [n]int //err, non-constant array bound nvar b [10]int
注意: 数组的长度不能使用变量, 但可以使用常量;
操作数组
数组的每个元素可以通过索引下标来访问, 索引下标的范围是从0开始到数组长度减1的位置。
package main //必须有个main包import ( "fmt")func main() { var a [10]int //数组遍历赋值 for i := 0; i < 10; i++ { a[i] = i + 1 fmt.Printf("a[%d] = %d\n", i, a[i]) } //数组的遍历:for for i := 0; i < len(a); i++ { fmt.Println("a[", i, "] = ", a[i]) } //数组的遍历:for ... range for i, v := range a { fmt.Println("a[", i, "] = ", v) }}
内置函数len(长度), cap(容量)都返回数组长度(元素数量)
package main //必须有个main包import( "fmt")func main(){ a := [10]int{} //简短模式声明数组 {} 不能省略 fmt.Println(len(a), cap(a)) // 10 10}
初始化数组使用方法:
package main //必须有个main包import( "fmt")func main(){ a := [3]int{1, 2} //初始化数组 b := [...]int{1, 2, 3} //通过初始化值确定数组长度 c := [5]int{2: 100, 4: 200} //通过索引号初始化元素, 未初始化元素值为0 d := [3]int{} //未初始化元素值为0, 注意: 简短声明数组 {} 括号不能省略 var f [3]int //未初始化元素值为0 fmt.Println(a, b, c, d, f) //[1 2 0] [1 2 3] [0 0 100 0 200] [0 0 0] [0 0 0] //支持多维数组 g := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}} h := [...][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}} //第二位数组不能写成"...", 只能写一个[...] j := [4][2]int{1:{20, 21}, 3:{40, 41}} k := [4][2]int{1:{0: 20}, 3:{1: 41}} fmt.Println(g, h, j, k) //[[10 11] [20 21] [30 31] [40 41]] [[10 11] [20 21] [30 31] [40 41]] [[0 0] [20 21] [0 0] [40 41]] [[0 0] [20 0] [0 0] [0 41]] var m [5]int = [5]int{1, 2, 3, 4, 5} fmt.Println(m) //[1 2 3 4 5] var n [5]int = [5]int{1, 2, 3, 4} fmt.Println(n) //[1 2 3 4 0] //var x [5]int = [5]int{1, 2, 3, 4, 5, 6} //fmt.Println(x) //err, array index 5 out of bounds [0:5] }
注意: 定义的数组元素的数量不能超过数组的长度
相同类型的数组之间可以使用 == 或 != 进行比较, 也可以相互赋值, 但不可以使用 < 或 >。
package main //必须有个main包import( "fmt")func main(){ a := [3]int{1, 2, 3} b := [3]int{1, 2, 3} c := [3]int{1, 3} //数组进行比较 fmt.Println(a == b, b == c) //true false var d [3]int //数组进行赋值操作 d = a fmt.Println(d) //[1, 2, 3] //不同类型(包括长度不同)的数组, 不能进行赋值 var f [4]int //f = a //err, cannot use a (type [3]int) as type [4]int in assignment fmt.Println(f) //数组进行比较 fmt.Println(c == d) //err, invalid operation: c == d (mismatched types [3]int and [4]int)}
注意: 数组进行赋值或者比较时, 数组的长度和类型要相同
package main //必须有个main包import( "fmt")func main(){ a := [5]int{1, 2, 3, 4, 5} b := [5]int{1, 3, 2, 4, 5} fmt.Println("a == b", a == b) //false 数组的顺序不相同返回的结果值: false}
在函数间传递数组
根据内存和性能来看, 在函数间传递数组是一个开销很大的操作。在函数之间传递变量时, 总是以值的方式传递的。
如果这个变量是一个数组, 意味着整个数组, 不管有多长, 都会完成赋值, 并传递给函数。
package main //必须有个main包import( "fmt")func modify(array [5]int){ array[0] = 10 //试图修改数组的第一个元素 fmt.Println("In modify(), array values:", array)}func main(){ array := [5]int{1, 2, 3, 4, 5} //定义并初始化一个数组 modify(array) //In modify(), array values: [10 2 3 4 5] fmt.Println("In modify(), array values:", array) //In modify(), array values: [1 2 3 4 5]}
数组指针作为函数的参数
package main //必须有个main包import( "fmt")func modify(array *[5]int){ (*array)[0] = 10 //试图修改数组的第一个元素 fmt.Println("In modify(), array values:", *array)}func main(){ array := [5]int{1, 2, 3, 4, 5} //定义并初始化一个数组 modify(&array) //In modify(), array values: [10 2 3 4 5] fmt.Println("In modify(), array values:", array) //In modify(), array values: [10 2 3 4 5]}
总结:
1. 数组:是同一种数据类型的固定长度的序列。
2. 数组定义:var a [len]int, 比如:var a [5]int, 数组长度必须是常量, 且是类型的组成部分。一旦定义, 长度不能变。
3. 长度是数组类型的一部分, 因此,var a[5] int和var a[10]int是不同的类型。
4. 数组可以通过下标进行访问, 下标是从0开始, 最后一个元素下标是:len-1
for i := 0; i < len(a); i++ {}for index, v := range a {}
5. 访问越界, 如果下标在数组合法范围之外, 则触发访问越界, 会panic
6. 数组是值类型, 赋值和传参会复制整个数组, 而不是指针。因此改变副本的值, 不会改变本身的值。
7. 支持 "=="、"!=" 操作符, 因为内存总是被初始化过的。
8. 指针数组 [n]*T, 数组指针 *[n]T。
【实例】:一维数组初始化和定义
package mainimport ( "fmt")var arr0 [5]int = [5]int{1, 2, 3}var arr1 = [5]int{1, 2, 3, 4, 5}var arr2 = [...]int{1, 2, 3, 4, 5, 6}var str = [5]string{3: "hello world", 4: "tom"}func main() { a := [3]int{1, 2} // 未初始化元素值为 0。 b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。 c := [5]int{2: 100, 4: 200} // 使用引号初始化元素。 d := [...]struct { name string age uint8 }{ {"user1", 10}, // 可省略元素类型。 {"user2", 20}, // 别忘了最后一行的逗号。 } fmt.Println(arr0, arr1, arr2, str) fmt.Println(a, b, c, d)}
【实例】: 二维数组初始化和定义
package mainimport ( "fmt")var arr0 [5][3]intvar arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}func main() { a := [2][3]int{{1, 2, 3}, {4, 5, 6}} b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 维度不能用 "..."。 fmt.Println(arr0, arr1) fmt.Println(a, b)}
【实例】
[10]int 和 [20]int是不同类型([...]int 和 [5]int 是不同的数组类型)
package mainimport ("fmt")func printArray(arr *[5]int) { arr[0] = 100 for i, v := range arr { fmt.Println(i, v) }}func main() { var arr1 [5]int arr2 := [3]int{1, 3, 5} arr3 := [...]int{2, 4, 6, 8, 10} var grid [4][5]int fmt.Println(arr1, arr2, arr3) fmt.Println(grid) for i := 0; i < len(arr3); i++ { //i++ 后面的要留有空 fmt.Println(arr3[i]) } for i, v := range arr3 { //fmt.Println(arr3[i]) fmt.Println(i, v) } for _, v := range arr3 { fmt.Println(v) } //fmt.Printf(&arr3) //[...]int 和 [5]int 是不同的数组类型 fmt.Println(&arr1)}
解决方法: 使用切片传递变长的数据
package mainimport ( "fmt")func printArray(arr []int) { arr[0] = 100 for i, v := range arr { fmt.Println(i, v) }}func main() { var arr1 [5]int arr2 := [3]int{1, 3, 5} arr3 := [...]int{2, 4, 6, 8, 10} var grid [4][5]int fmt.Println(arr1, arr2, arr3) fmt.Println(grid) for i := 0; i < len(arr3); i++ { //i++ 后面的要留有空 fmt.Println(arr3[i]) } for i, v := range arr3 { //fmt.Println(arr3[i]) fmt.Println(i, v) } for _, v := range arr3 { fmt.Println(v) } s := arr3[:] //使用切片的方法,解决变长的数据 printArray(s)}
【实例】
冒泡排序算法:
package main //必须有个main包import("fmt""math/rand""time")func main(){//设置种子, 只需一次//如果种子参数一样, 每次运行程序产生的随机数都一样rand.Seed(time.Now().UnixNano()) //以当前系统时间作为种子参数 nano: 纳米var a [10]intn := len(a)for i := 0; i < n; i++ {//产生随机数a[i] = rand.Intn(100) //100以内的随机数fmt.Printf("%d, ", a[i])}fmt.Printf("\n")//冒泡排序, 挨着的2个元素比较, 升序(大于则交换)for i := 0; i < n-1; i++ {for j := 0; j < n-1-i; j++ {if a[j] > a[j+1] {a[j], a[j+1] = a[j+1], a[j]}}}fmt.Printf("\n排序后:\n")for i := 0; i < n; i++ {fmt.Printf("%d, ", a[i])}fmt.Printf("\n")}/*6, 12, 6, 84, 32, 32, 80, 8, 38, 4,排序后:4, 6, 6, 8, 12, 32, 32, 38, 80, 84,*/
实例: 计算数组的个数
package mainimport ("fmt")func main() { arr := []string{"apple", "orange", "apple", "banana", "orange", "banana", "apple", "apple", "orange", "apple", "banana", "orange", "banana", "apple", "apple", "orange", "apple", "banana", "orange", "banana", "apple"} var num int = 0 for _, _ = range arr { num++ } fmt.Println(num) // 21, 与 cap()内建函数有着本质的区别 fmt.Println(len(arr)) // 21}
实例: 计算数组中元素的个数
package mainimport ("fmt")func main() { arr := []string{"apple", "orange", "apple", "banana", "orange", "banana", "apple", "apple", "orange", "apple", "banana", "orange", "banana", "apple", "apple", "orange", "apple", "banana", "orange", "banana", "apple"} m := make(map[string]int) for _, v := range arr { if m[v] == 0 { m[v] = 1 } else { m[v]++ } } fmt.Println(m) //map[apple:9 orange:6 banana:6]}