Go第六课-复合类型:数组和切片

88 阅读2分钟

数组

  1. Go 编译器需要在编译阶段就知道数组类型的长度

  2. 如果两个数组类型的元素类型 T 与数组长度 N 都是一样的,那么这两个数组类型是等价的,如果有一个属性不同,它们就是两个不同的数组类型。

  3. 数组类型不仅是逻辑上的连续序列,而且在实际内存分配时也占据着一整块内存

  4. 预定义函数 len 可以用于获取一个数组类型变量的长度,通过 unsafe 包提供的 Sizeof 函数,我们可以获得一个数组变量的总大小(字节)

  5. 数组声明

    func TestArrayIni(t *testing.T) {
    	var arr1 [2]int64       // 声明并初始化为默认零值
    	arr1[0] = 1             // 赋值
    	arr2 := [3]int{1, 2, 3} // 声明同时初始化
    	arr3 := [...]string{"a", "b", "c", "d"}
    	arr4 := [2][2]int{{1, 2}, {3, 4}} // 多维数组初始化
    	t.Log(arr1, arr2, arr3, arr4)     // [1 0] [1 2 3] [a b c d] [[1 2] [3 4]]
    }
    
  6. 数组遍历:a[开始索引(包含), 结束索引(不包含)]

    func TestArrayTravel(t *testing.T) {
    	a := [...]string{"a", "b", "c", "d"}
    	for idx, elem := range a {
    		t.Log(idx, elem)
    	}
    	for _, elem := range a {
    		t.Log(elem)
    	}
    }
    
  7. 数组截取

    func Test_slit(t *testing.T) {
    	a := [...]int{1, 2, 3, 4, 5}
    	a1 := a[1:2] // [2]
    	a2 := a[1:3] // [2,3]
    	a3 := a[2:]  // [3,4,5]
    	a4 := a[:3]  // [1,2,3]
    	fmt.Println(
    		a1, a2, a3, a4,
    	)
    }
    

切片

  1. 切片声明仅仅是少了一个“长度”属性

    type slice struct {    
    		array unsafe.Pointer     //是指向底层数组的指针;
    		len   int    //是切片的长度,即切片中当前元素的个数;
    		cap   int //是底层数组的长度,也是切片的最大容量,cap 值永远大于等于 len 值。
    }
    
  2. 可以说,切片之于数组就像是文件描述符之于文件。

  3. 针对元素是 int 型的数组,新数组的容量是当前数组的 2 倍

  4. 切片内部结构:

image.png

```
func TestSliceInit(t *testing.T) {
	s0 := []int{}
	for i := 0; i < 10; i++ {
		s0 = append(s0, i)
		t.Log(len(s0), cap(s0))
	} // 10 16

	s1 := []int{}
	s2 := []int{1, 2, 3}
	t.Log(s1, len(s1), cap(s1)) // [] 0 0
	t.Log(s2, len(s2), cap(s2)) // [1 2 3] 3 3
}
```
  1. 切片共享存储结构

image.png

数组 vs. 切⽚

  1. 容量是否可伸缩
  2. 是否可以进⾏⽐较:数组可以比较,切片不可以
func TestSliceCompare(t *testing.T) {
	s1 := []int{1, 2, 3}
	s2 := []int{1, 2, 3}
	t.Log(s1 == s2)
}
// invalid operation: s1 == s2 (slice can only be compared to nil)