5-数组
数组是同一种数据类型元素的集合。
在 Go 中 数组从声明时就确定,使用时可以修改数组成员,但不能修改数组大小。
数组定义
idn
:数组名、len
:数组长度、T
:数组类型
数组长度必须是常量,且一旦定义就不能更改。
[5]int
和[10]int
是不同的类型。
var arr1 [ 5 ] int
var arr2 [ 8 ] int
arr1 = arr2 // 禁止这样做,因为此时 arr1 和 arr2 是不同的类型
arr2 不可以赋值给 arr2,因为它俩类型不同。
如果换成 var arr1 [5]int
和 var arr2 [5]int
这样就可以。
func main () {
var arr1 = [ 3 ] int { 12 , 3 }
var arr2 [ 3 ] int
arr2 = arr1
for _ , e := range arr2 {
fmt . Println ( e )
}
}
// ----------------------------------------
// Output:
12
3
0
数组初始化
初始化方式有很多种
方法1
使用初始化列表设置数组元素的值
var idn [ len ] T
var idn = [ len ] T { initial list }
eg:
var a [ 3 ] int
var b = [ 3 ] int { 1 , 2 }
var c = [ 3 ] string { "Alice" , "Boii" }
fmt . Println ( a ) // [0 0 0]
fmt . Println ( b ) // [1 2 0]
fmt . Println ( c ) // [Alice Boii]
方法2
让编译器根据初始值个数自行推断数组长度
var idn = [ ... ] T { initial list }
eg:
var b = [ ... ] int { 1 , 2 , 3 , 4 }
fmt . Println ( b ) // [1 2 3 4]
fmt . Printf ( "Type of b: %T \n" , b ) // Type of b: [4]int
方法3
通过指定索引值来初始化数组,数组长度为 最大的下标+1
。
通过这种方式的可以不指定数组长度,如果指定了数组长度且没有更大的下标,则以指定长度为最大长度。
var idn = [ ... ] T { idx : elem , idx : elem }
eg:
func main () {
a := [ ... ] rune { 1 : 'i' , 5 : 'v' }
b := [ 7 ] int { 0 : 2 , 4 : 5 }
fmt . Println ( a ) // [0 i 0 0 0 v]
fmt . Println ( b ) // [2 0 0 0 5 0 0]
fmt . Printf ( "Type of a: %T \n" , a ) // Type of a: [6]rune
fmt . Printf ( "Type of b: %T \n" , b ) // Type of b: [7]int
// b := [3]int{0: 2, 4: 5}
// 上面这句会报错,指定长度3,却又指定了索引4
}
数组遍历
数组遍历可以通过 for
循环,也可以通过 for...range
,比较推荐 for...range
func main () {
str := [ ... ] string { "广州" , "深圳" , "东莞" }
for i := 0 ; i < len ( str ); i ++ {
fmt . Println ( str [ i ])
}
for idx , value := range str {
fmt . Println ( idx , value )
}
}
多维数组
Go 中支持多维数组,这里以二维数组为例。
定义
func main () {
a := [ 3 ][ 2 ] string {
{ "广东" , "广州" },
{ "浙江" , "杭州" },
{ "四川" , "成都" },
}
fmt . Println ( a ) // [[广东 广州] [浙江 杭州] [四川 成都]]
fmt . Println ( a [ 1 ][ 1 ]) // 支持索引取值: 杭州
}
遍历
func main () {
a := [ 3 ][ 2 ] string {
{ "广东" , "广州" },
{ "浙江" , "杭州" },
{ "四川" , "成都" },
}
for _ , v1 := range a {
for _ , v2 := range v1 {
fmt . Printf ( "%s \t" , v2 )
}
fmt . Println ()
}
}
// ----------------------------------------
// Output:
广东 广州
浙江 杭州
四川 成都
eg:
// 合法写法
a := [ ... ][ 2 ] string {
{ "广东" , "广州" },
{ "浙江" , "杭州" },
{ "四川" , "成都" },
}
// 非法写法
a := [ ... ][ ... ] string {
{ "广东" , "广州" },
{ "浙江" , "杭州" },
{ "四川" , "成都" },
}
数组是值类型
数组是值类型,赋值和传参会赋值整个数组。因此改变副本的值,不会改变本身的值。
func modifyArray ( x [ 3 ] int ) {
x [ 0 ] = 100
}
func modifyArray2 ( x [ 3 ][ 2 ] int ) {
x [ 2 ][ 0 ] = 100
}
func main () {
a := [ 3 ] int { 10 , 20 , 30 }
modifyArray ( a ) //在modify中修改的是a的副本x
fmt . Println ( a ) //[10 20 30]
b := [ 3 ][ 2 ] int {
{ 1 , 1 },
{ 1 , 1 },
{ 1 , 1 },
}
modifyArray2 ( b ) //在modify中修改的是b的副本x
fmt . Println ( b ) //[[1 1] [1 1] [1 1]]
}
注意:
数组支持 ==
、!=
操作符,因为内存总是被初始化过的。
[len]*T
表示指针数组,本质是 数组 ,存放指针的数组
*[len]T
表示数组指针,本质是 指针 ,指向数组的指针