0. 引言
既然在Go语言中数组和切片同时存在并且是两个不同的类型,那当他们是二维时又会产生什么样的问题?
因为数组和切片同时存在,在Go语言中二维的使用就会显得和别的语言很不一样了,这也是其中需要注意的地方,下面理清一下其中的关系。
1. 二维数组
1.1 定义二维数组
二位数组很简单,举个例子var a [2][3]int
这就是定义一个二位数组。
关键在于二维数组的两维都是固定的,你可以显式的知道他可以存储2*3个元素。此时下面式子:[a][b]int
中的a和b一定、一定、一定是常量(const的正整数变量 或 某一个确定的正整数)。
const m = 100 // 定义一个常量
a := 100 // 定义一个变量
var arr1 [a][m]int // 报错××
var arr2 [a][100]int // 报错××
var arr3 [100][m]int // 正常√√
1.2 使用二维数组
二维数组必须要在两个维度(长宽)都确定的情况下才能够定义。但使用起来就显得方便很多了。
package main
func main() {
var arr [2][2]int
for i := 0; i < 2; i++ {
for j := 0; j < 2; j++ {
arr[i][j] = i + j
}
}
}
2. 二维切片
一开始我以为用arr[i][j]
调用的就是二维数组,很显然我当时忽略了Go语言不只是有数组,同样还有切片,并且两者大不相同。
2.1 定义二维切片
定义一个二维切片就很简单了var a [][]int
,可以看得出来,切片保持了一贯的作风,二维都不设置限制。
2.2 使用二维切片※
二维切片的使用就有说法了,因为你不能直接通过a[i][j]
来给他赋值啊,直接用你是要越界啊,需要用append来进行操作。
可是问题又来了我怎么能把数存放在某个特定的位置啊。
其实二维切片就是切片的一个切片,也就是说二维切片存放的内容是一个一维的切片,我们每次需要append的内容是一个一维的切片:
package main
import "fmt"
func main() {
var a [][]int // 二维切片
for i := 0; i < 2; i++ {
var tmp []int // 一维切片
tmp = append(tmp, i) // 在一维切片内添加元素
a = append(a, tmp) // 在二维切片内添加一维切片
}
fmt.Println(a) // 查看一下二维切片的内容
}
/*
[[0] [1]]
*/
第二种方法就类似于二维数组的定义,但是二维数组不能用常量。
package main
import "fmt"
func main() {
a := make([][]int, 2)
for i := range a {
a[i] = make([]int, 2)
}
fmt.Println(a)
}
3. 切片的数组?数组的切片?
其实看得出来,上面两种情况一种是两维全固定,一种是两维全自由,那如果说一维固定一维自由是什么情况?
如果我按照以下方式定义会产生什么效果?
var a [2][]int
var b [][2]int
从底层角度出发,a是切片的数组,b是数组的切片:
type intS []int
var a [2]intS
就类似于这样,此时可以看得出来intS类型是定长的,那么从本质上说,这是一个数组。
同理var []type
本质上就是一个切片,因为他是不定长的。