数组

Go语言中有定长数组和变长数组,其中变长数组也叫切片(slice),含义和操作方法与Python中切片函数的操作形式类似。

定长数组

定长数组使用[n]T的形式定义,其中n为数组的长度,T为数据类型。

var arr [2]string
arr[0] = "hello"
arr[1] = "world"

这里要特别注意,Go语言中数组的类型包括其内部的数据类型和长度,[2]string[3]string是不同的类型,类型不同的情况下进行赋值、参数传递等操作编译会报错。

此外,Go语言中对定长数组进行赋值、函数参数传递等操作,传递的都是整个数组,也就是说是值传递的,这可能产生较大的内存拷贝开销,此时可以使用指针。

package main

import "fmt"

func foo(arr *[2]string) {
    fmt.Printf("%v\n", *arr)
}

func main() {
    var arr [2]string
    arr[0] = "hello"
    arr[1] = "world"

    foo(&arr)
}

变长数组

Go语言中变长数组也叫切片(slice)。实际上,开发中使用变长数组更多,当然由于底层实现不同,在某些情况下其性能肯定不如定长数组。

变长数组初始化

定义时不指定数组长度就是变长数组了,如下方式创建了一个空的变长数组,我们可以使用append()函数为其添加元素,返回值是添加元素后的变长数组。

var arr []string
arr = append(arr, "hello")
arr = append(arr, "go", "language")

注:var arr []string声明的空变长数组,其值arrnil

我们也可以直接在声明时指定变长数组的初始值。

var arr = []string{"hello", "world"}

或者可以使用make关键字初始化一个有一定长度的空变长数组。

var arr = make([]string, 3)

注意:该种写法由于已经初始化了几个元素,只不过它们是默认的空值,而append()只是在变长数组末尾添加,不要搞混了。

变长数组和数组虽然写法差不多,但内部差别可是很大。变长数组为了实现动态增长,需要额外的存储空间实现一个用作索引的指针,对应真正的数据区域。正因如此,变长数组虽然也是值传递,但复制的仅是一堆指针,真正底层的数据区域并没有发生复制,我们可以将其理解为引用传递,因此需要考虑深浅拷贝的问题。

变长数组组合和切分

变长数组实现删除和Python中切片函数很像,下面代码实现了删除数组中的arr[1]元素。

arr = append(arr[:1], arr[2:]...)

注:...是Go语言的一个语法糖,作用是将一个数组打散传递,我们可完全可以用一个循环取出arr[2:]中的所有元素然后挨个append(),但是写起来就比较麻烦了。

同理,如果想在数组中间插入,也是完全可以用切片实现的,这里就不多介绍了。

变长数组拷贝

切片复制可以使用遍历或append()...语法联用实现,更简单的办法是使用copy()函数。下面代码将arr的内容复制给arr2,注意arr2必须有个初始长度,否则是无法复制的,如果arr2arr短,只会按顺序复制len(arr2)个元素。

var arr = []string{"1", "2", "3"}
var arr2  = make([]string, 3)
copy(arr2, arr)
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。