1)
对于下面的切片声明,
var a [][3]string
创建一个切片(a
),指向3个字符串的数组,len(a) = 3
和cap(a) =3
但不是cap(a) >= 3
a = make([][3]string, 5)
创建5个切片,其中每个切片(比如a[0]
)指向3个字符串的数组,len(a[0]) = 3
和cap(a[0]) = 3
2)
对于切片声明,
var b [][3][6]string
创建一个切片(b
),指向3个数组,每个数组包含6个字符串,其中len(b) = 3
和cap(b) =3
b = make([][3][6]string, 5)
创建5个切片,其中每个切片(比如b[0]
)指向3个数组,每个数组包含6个字符串
在这两种情况下,在制作切片后,我说,创建了5个切片,
考虑到语法,下面是我的两个问题,
a = make([][3]string, 5)
我的问题:
1)
是5个切片,每个切片(a[0]
)是3个字符串的数组吗?
或
是一个单个切片(a
)指向5个每个3个字符串的数组吗?
2)
我如何知道元素的类型?切片还是数组?
1)在这种情况下,必须谨慎使用“数组”术语。
2)与C
不同,GO中没有隐式指针答案 0 :(得分:3)
切片和数组是两种不同的类型:内存中的数组是相同类型的连续值序列。在Go中,类型具有固定大小。例如,在C ++和
中存在相同的概念int x[5]; // C and C++
x [5]int // Go
基本上是相同的(不是100%相同,因为C和C ++中的数组是"第二类公民"并且在一些地方表现得很奇怪,Go在这方面更加统一)。
Go中的切片是" view"一个数组的一部分,并且或多或少等同于一个C ++结构,其中包含指向第一个元素的指针,一些使用过的元素(相对于第一个)和一些可用元素(相对于第一个)
// C++
template<typename T>
struct Slice {
T *first;
int size, capacity;
};
Slice<int> x{nullptr, 0, 0};
// Go
var x []int
Make
特殊功能能够创建与新创建的阵列相关的切片,给定大小和可选容量:
// C++
template<typename T>
Slice<T> make(int size, int capacity=-1) {
if (capacity == -1) capacity = size;
return Slice<T>{new T[capacity], size, capacity};
}
// Go
x := Make([]int, size, capacity)
切片可以在O(1)中有效传递(独立于大小/容量),你也可以在O(1)中获取切片的子切片...注意Go是垃圾收集,在C ++中也需要一些额外的工作(例如,还要保留指向原始数组对象的指针及其在切片中的大小)。
您当然可以拥有切片数组,切片切片,数组切片和数组数组。但请注意,Go Make
仅用于创建切片(和贴图)而不是数组...
x := Make([][2]int, 3) // a slice of 3 arrays of 2 ints each
// Same thing (except for content)
y := [][2]int{[2]int{1, 2},
[2]int{3, 4},
[2]int{5, 6}}
// An array of 3 slices of two ints each
z := [3][]int{[]int{1, 2},
[]int{3, 4},
[]int{5, 6}}
虽然例如y
和z
in the playground在使用[[1, 2], [3, 4], [5, 6]]
时看起来相同fmt.Println
,但它们的类型非常不同,例如你可以使用
y
y = append(y, [2]int{7, 8}) // now [[1, 2], [3, 4], [5, 6], [7, 8]]
您可以使用
增加z
的第一个元素的长度
z[0] = append(z[0], 99) // now [[1, 2, 99], [3, 4], [5, 6]]
但你无法向z
添加新元素(它是一个数组),你不能扩展y
的元素(因为元素是数组)
答案 1 :(得分:2)
1)考虑语法,
a = make([][3]string, 5)
是5个切片,每个切片(a [0])是3个字符串的数组吗?
或
是单个切片(a)指向5个每个3个字符串的数组吗?
它是一个包含5个元素的单个切片,其中每个元素是一个包含3个字符串的数组。
2)
我如何知道元素的类型?切片还是数组?
切片和数组是不同的类型。您不能互换地将数组和切片分配给同一个变量,因此如果声明将其声明为数组,则将其声明为数组(如果它将其声明为切片),则为切片。如果括号([5]string
)中的数字是一个数组,如果括号为空([]string
)则为一个切片。
2)对于切片声明,
var b [][3][6]string
创建一个切片(b),指向每个包含6个字符串的3个数组, 其中len(b)= 3且cap(b)= 3
b = make([][3][6]string, 5)
创建5个切片,其中每个切片(比如b [0])指向3个数组,每个数组包含6个字符串
没有。以前的代码只是声明一个变量,它还没有一个切片。后代码使用五个元素创建一个切片。