构造空数组的最佳实践

kpi*_*pie 6 initialization go

我想知道初始化空数组时的最佳实践。

即arr1,arr2和arr3之间有什么区别吗?

myArr1 := []int{}
myArr2 := make([]int,0)
var myArr3 []int
Run Code Online (Sandbox Code Playgroud)

我知道它们为空,[]int但是我想知道,一种语法比其他语法更可取吗?就我个人而言,我发现第一个最易读,但这与本文无关。争用的关键点之一可能是阵列容量,这三个之间的默认容量可能是相同的,因为未指定。声明未指定容量的数组是否“不好”?我可以假设它会带来一些性能成本,但是它到底有多“糟糕”呢?

/ tldr

  1. 生成空数组的三种方法之间有什么区别吗?
  2. 未指定时,阵列的默认容量是多少?
  3. 使用未指定容量的阵列的性能成本是多少?

Mil*_*sen 5

首先,它是一个切片而不是一个数组。Go 中的数组和切片非常不同,数组具有固定的大小,是类型的一部分。一开始我也遇到了这个问题:)

  1. 并不真地。任何如果三个都正确,任何差异都应该太小而不必担心。在我自己的代码中,我通常使用在特定情况下最简单的方法。
  2. 0
  3. 什么都没有,直到您需要添加一个项目,然后不惜一切代价分配所需的存储空间。

  • 数组的一个很好的例子是`crypto/md5`。一个 md5 校验和总是 16 个字节,所以使用 `[16]byte` 来存储一个是非常有意义的。 (2认同)

Aka*_*all 5

使用具有未指定容量的阵列的性能成本是多少?

当您开始填充切片时肯定会产生成本。如果您知道切片应该增长多大,您可以从非常请求中分配底层数组的容量,而不是在每次底层数组填满时重新分配。

这是一个带有计时的简单示例:

package main

import "fmt"

func main() {

    limit := 500 * 1000 * 1000
    mySlice := make([]int, 0, limit) //vs mySlice := make([]int, 0)

    for i := 0; i < limit; i++ {
        mySlice = append(mySlice, i)
    }

    fmt.Println(len(mySlice))
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上:

time go run my_file.go
Run Code Online (Sandbox Code Playgroud)

预分配:

real    0m2.129s
user    0m2.073s
sys     0m1.357s
Run Code Online (Sandbox Code Playgroud)

没有预分配

real    0m7.673s
user    0m9.095s
sys     0m3.462s
Run Code Online (Sandbox Code Playgroud)