切片数组 - GO
Array of slices - GO
1)
对于下面的切片声明,
var a [][3]string
创建一个指向 3 个字符串数组的切片 (a
),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) 在这种情况下,必须谨慎使用 "array of" 术语。
2) 与 C
不同,GO 中没有涉及隐式指针
1) Considering the syntax,
a = make([][3]string, 5)
Is it 5 slices, where each slice(a[0]) is array of 3 strings?
or
Is it a single slice(a) pointing to 5 arrays of 3 strings each?
它是一个包含 5 个元素的切片,其中每个元素是一个包含 3 个字符串的数组。
2)
How do I know the type of an element? slice or array?
切片和数组是不同的类型。您不能将数组和切片互换地分配给同一个变量,因此,如果声明将其声明为数组,则它是一个数组;如果将其声明为切片,则它是切片。如果它在括号中有一个 number ([5]string
) 它是一个数组,如果括号是空的 ([]string
) 它是一个切片。
2) For slice declaration,
var b [][3][6]string
creates a single slice(b) that points to 3 arrays of 6 strings each,
where len(b) = 3 and cap(b) =3
b = make([][3][6]string, 5)
creates 5 slices, where each slice(say b[0]) points to 3 arrays of 6 strings each
没有。以前的代码只是声明一个变量,它还没有保存切片。后面的代码创建 one 切片,其中包含 five 个元素。
切片和数组是两种不同的类型:内存中的数组是相同类型值的连续序列。在 Go 中,类型具有固定大小。例如在 C++ 和
中存在非常相同的概念
int x[5]; // C and C++
x [5]int // Go
基本上是相同的东西(不是 100% 相同,因为 C 和 C++ 中的数组是 "second class citizens" 并且在一些地方表现得很奇怪,Go 在这方面更统一)。
Go 中的切片是数组一部分的 "view",并且或多或少等同于具有指向第一个元素的指针的 C++ 结构,一些使用的元素(相对于first) 和一些可用元素(相对于 first)
// 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) 中高效传递(独立于 size/capacity),您也可以在 O(1) 中获取切片的 sub-slice...请注意 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 在使用 fmt.Println
时看起来是一样的 [[1, 2], [3, 4], [5, 6]]
,但它们是非常不同的类型,例如你可以用
添加一对新的 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)
对于下面的切片声明,
var a [][3]string
创建一个指向 3 个字符串数组的切片 (a
),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) 在这种情况下,必须谨慎使用 "array of" 术语。
2) 与 C
不同,GO 中没有涉及隐式指针1) Considering the syntax,
a = make([][3]string, 5)
Is it 5 slices, where each slice(a[0]) is array of 3 strings?
or
Is it a single slice(a) pointing to 5 arrays of 3 strings each?
它是一个包含 5 个元素的切片,其中每个元素是一个包含 3 个字符串的数组。
2)
How do I know the type of an element? slice or array?
切片和数组是不同的类型。您不能将数组和切片互换地分配给同一个变量,因此,如果声明将其声明为数组,则它是一个数组;如果将其声明为切片,则它是切片。如果它在括号中有一个 number ([5]string
) 它是一个数组,如果括号是空的 ([]string
) 它是一个切片。
2) For slice declaration,
var b [][3][6]string
creates a single slice(b) that points to 3 arrays of 6 strings each, where len(b) = 3 and cap(b) =3
b = make([][3][6]string, 5)
creates 5 slices, where each slice(say b[0]) points to 3 arrays of 6 strings each
没有。以前的代码只是声明一个变量,它还没有保存切片。后面的代码创建 one 切片,其中包含 five 个元素。
切片和数组是两种不同的类型:内存中的数组是相同类型值的连续序列。在 Go 中,类型具有固定大小。例如在 C++ 和
中存在非常相同的概念int x[5]; // C and C++
x [5]int // Go
基本上是相同的东西(不是 100% 相同,因为 C 和 C++ 中的数组是 "second class citizens" 并且在一些地方表现得很奇怪,Go 在这方面更统一)。
Go 中的切片是数组一部分的 "view",并且或多或少等同于具有指向第一个元素的指针的 C++ 结构,一些使用的元素(相对于first) 和一些可用元素(相对于 first)
// 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) 中高效传递(独立于 size/capacity),您也可以在 O(1) 中获取切片的 sub-slice...请注意 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 在使用 fmt.Println
时看起来是一样的 [[1, 2], [3, 4], [5, 6]]
,但它们是非常不同的类型,例如你可以用
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
的元素(因为元素是数组)