Go 多維 array 與 slice

Array types are always one-dimensional but may be composed to form multi-dimensional types.

from spec Array types

A slice is a descriptor for a contiguous segment of an underlying array and provides access to a numbered sequence of elements from that array.

Like arrays, slices are always one-dimensional but may be composed to construct higher-dimensional objects.

from spec Slice types

Initialization

Slice

在多維的情況下,inner slice 只能一個個初始化,像這樣:

1
2
3
4
x := make([][]byte, 2)
for i := range x {
x[i] = make([]byte, 1000)
}

上面例子沒有迴圈直接去 access x[0][0] 的話會 index out of range

或者用 literal 直接寫:

1
2
3
4
a := [][]uint8{
{0, 1, 2, 3},
{4, 5, 6, 7},
}

Array

初始化成零值比較簡單:

1
2
c := [5][5]uint8{}
// [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

Memory Size

多維 array 的 size 是 type size * element 數量

多維 slice 的 size 則要看多維 slice 是怎麼組成的。slice 由指向 underlying array 的 pointer、length、capacity 組成,多維 slice 不同的組合方式會造成有不同數量的 slice header 而有不同的 size,來個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
// x 是 2 x 1000 的 slice
x := make([][]byte, 2)
for i := range x {
x[i] = make([]byte, 1000)
}
fmt.Println(len(x), len(x)*len(x[0]))

// y 是 1000 x 2 的 slice
y := make([][]byte, 1000)
for i := range y {
y[i] = make([]byte, 2)
}
fmt.Println(len(y), len(y)*len(y[0]))

output 是:

1
2
2 2000
1000 2000

x 跟 y 都是多維 slice 而且都有 2000 個 element。x 只有兩個 slice、每個 slice 有 1000 個 element byte,y 有 1000 個 slice、每個 slice 只有兩個 element。

slice header 長這樣:

1
2
3
4
5
type SliceHeader struct {
Data uintptr
Len int
Cap int
}

from SliceHeader

在 64-bit 平台上,一個 slice header 的 size 是 24 bytes。那麼 x 的總 size 是 2000 + 2 * 24 = 2048 bytes。而 y 的總 size 則是 2000 + 1000 * 24 = 26000 bytes。

所以啦,考量 memory 使用的時候,需要注意多維 slice 是怎麼組的,像上面的 y,slice header 的 size 遠超過全部 element 的 size。

Inner array/slice length

With arrays of arrays, the inner arrays are, by construction, always the same length; however with slices of slices (or arrays of slices), the inner lengths may vary dynamically. Moreover, the inner slices must be initialized individually.

多維 array 的 inner array 都是相同 length 的。

多維 slice 的 inner slice 可以是不同 length。另外,inner slice 必須要各自 initialize。

Ref