数组是指一系列同一类型数据的集合。 数组中包含的每个数据被称为数组元素(element), 一个数组包含的元素个数被称为数组的长度。
数组的长度必须是常量, 且是类型的组成部分。[2]int 和 [3]int 是不同类型
var n int = 10;
var a [n]int //err, non-constant array bound n
var 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 main
import (
"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 main
import (
"fmt"
)
var arr0 [5][3]int
var 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 main
import (
"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 main
import (
"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]int
n := 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 main
import (
"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 main
import (
"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]
}