go中slice与array的区别

205 阅读2分钟

由于个人最近在进行go的学习,想了解一下slice与array的区别。打开百度进行搜索以后结果如下。

我们很难在度里找到一篇比较优质的相关文章。所以才有了今天的这篇译文,原文地址:Arrays vs Slices


数组是固定长度的、拥有相同类型的一组序列。在GO中,可以使用以下方式创建数组。

[N]Type
[N]Type{value1, value2, ..., valueN}
[...]Type{value1, value2, ..., valueN}

不像C/C++(数组实际是指针)和java(数组是对象的引用),在GO中,数组是值类型。这种特性会带来以下几种影响。

  1. 将一个数组赋值到另一个数组,会对数组中所有元素进行复制。
  2. 加入你传递一个数组给一个函数,这个函数接受的是这个数组的拷贝。

你可能会说,这种操作代价太高了。尤其当你使用的数组里面有很多元素的时候。

相对的,slice就非常的灵活了。slice可以使用内置的append函数调整大小。同时slice是引用类型。同时,在go所有的标准库函数中,使用的都是slice。

创建slice的方式如下

make([]Type, length, capacity)
make([]Type, length)
[]Type{}
[]Type{value1, value2, ..., valueN}

综上:slice更加灵活,干净。所以建议更多的使用slice。


一些有助于帮助理解的例子

package main

import "fmt"

func main() {
	// Array
	array := [3]int{1, 2, 3}
	arrayCopy := array
	fmt.Printf("&array[0]: %p\n", &array[0]) //&array[0]: 0xc000016078
	fmt.Printf("&arrayCopy[0]: %p\n", &arrayCopy[0])//&arrayCopy[0]:0xc000016090

	fmt.Println("---------------------------")

	// Slice
	slice := []int{1, 2, 3}
	sliceRef := slice
	fmt.Printf("&slice[0]: %p\n", &slice[0]) //&slice[0]: 0xc0000160a8
	fmt.Printf("&sliceRef[0]: %p\n", &sliceRef[0]) //&sliceRef[0]: 0xc0000160a8
	slice = append(slice, 4, 5)
	fmt.Printf("&slice[0]: %p\n", &slice[0]) //&slice[0]: 0xc00001c0f0
	fmt.Printf("&sliceRef[0]: %p\n", &sliceRef[0]) //&sliceRef[0]: 0xc0000160a8

	slice[0] = 999
}