数组
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
声明的空变长数组,其值arr
为nil
。
我们也可以直接在声明时指定变长数组的初始值。
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
必须有个初始长度,否则是无法复制的,如果arr2
比arr
短,只会按顺序复制len(arr2)
个元素。
var arr = []string{"1", "2", "3"}
var arr2 = make([]string, 3)
copy(arr2, arr)