使用make或默认初始化创建不同大小的数组

huangapple go评论82阅读模式
英文:

Different sizes of arrays using make or default initialization

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言,想要理解这门语言以编写高效的代码。在下面的代码中,两个数组的大小相差140%,有人可以解释一下这是为什么吗?

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    ind1 := make([]bool, 10)
    var ind2 [10]bool
    fmt.Println(unsafe.Sizeof(ind1)) // 24
    fmt.Println(len(ind1)) // 10
    fmt.Println(unsafe.Sizeof(ind2)) // 10
    fmt.Println(len(ind2)) // 10
}

第一个数组的大小仍然是10,即使容量被显式设置为:

ind1 := make([]bool, 10, 10)

有人可以解释一下这是为什么吗?在使用make时是否有额外的开销?如果有,为什么推荐使用make而不是默认初始化?

英文:

I'm new to Go and try to understand the language in order to write efficient code. In the following code, sizes of the two arrays differ by 140%, can someone explain this?

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    ind1 := make([]bool, 10)
    var ind2 [10]bool
    fmt.Println(unsafe.Sizeof(ind1)) // 24
    fmt.Println(len(ind1)) // 10
    fmt.Println(unsafe.Sizeof(ind2)) // 10
    fmt.Println(len(ind2)) // 10
}

The size of the first array remains 10, even in case the capacity is set explicitly:

    ind1 := make([]bool, 10, 10)

Can someone explain this? Is there any additional overhead in using make? If yes, why is it recommended to use make over default initialization?

答案1

得分: 5

在Go语言中,数组(Arrays)和切片(Slices)是不同的概念。

你的ind1是一个切片,而ind2是一个数组。数组的长度是类型的一部分,所以例如[2]bool[3]bool是两种不同的数组类型。

在Go语言中,切片是对底层数组的一个连续片段的描述符,并提供对该数组中一系列编号的元素的访问。切片头部是一个类似结构体的数据结构,由类型reflect.SliceHeader表示:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

它包含一个数据指针(指向所表示片段的第一个元素)、长度和容量。

unsafe.SizeOf()函数返回一个假设变量所占用的字节数。它不包括可能被该变量引用的任何内存。

因此,如果你传递一个切片值(ind1),它将告诉你上述切片头部的大小。请注意,SliceHeader的字段大小是与架构相关的,例如int在一个平台上可能是4个字节,在另一个平台上可能是8个字节。大小24适用于64位架构。

Go Playground运行在32位架构上。让我们看看这个例子:

fmt.Println(unsafe.Sizeof(make([]bool, 10)))
fmt.Println(unsafe.Sizeof(make([]bool, 20)))

fmt.Println(unsafe.Sizeof([10]bool{}))
fmt.Println(unsafe.Sizeof([20]bool{}))

输出结果(在Go Playground上尝试):

12
12
10
20

如你所见,无论你传递给unsafe.SizeOf()的切片长度是多少,它在Go Playground上始终返回12(在64位架构上返回24)。

另一方面,数组值包含所有的元素,因此它的大小取决于它的长度。[10]bool的大小是10,[20]bool的大小是20。

请参阅相关问题和答案,了解更多关于切片、数组以及它们之间的差异和关系的信息:

必读的博文:

英文:

Arrays and slices in Go are different things.

Your ind1 is a slice, and ind2 is an array. The length of an array is part of the type, so for example [2]bool and [3]bool are 2 different array types.

A slice in Go is a descriptor for a contiguous segment of an underlying array and provides access to a numbered sequence of elements from that array. This slice header is a struct-like data structure represented by the type reflect.SliceHeader:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

It contains a data pointer (to the first element of the represented segment), a length and a capacity.

The unsafe.SizeOf() function returns the size in bytes of the hypothetical variable as if it would hold the passed value. It does not include any memory possibly referenced by it.

So if you pass a slice value (ind1), it will tell you the size of the above mentioned slice header. Note that the size of the fields of SliceHeader are architecture dependent, e.g. int may be 4 bytes on one platform and it may be 8 bytes on another. The size 24 applies to 64-bit architectures.

The Go Playground runs on a 32-bit architecture. Let's see this example:

fmt.Println(unsafe.Sizeof(make([]bool, 10)))
fmt.Println(unsafe.Sizeof(make([]bool, 20)))

fmt.Println(unsafe.Sizeof([10]bool{}))
fmt.Println(unsafe.Sizeof([20]bool{}))

Output (try it on the Go Playground):

12
12
10
20

As you can see, no matter the length of the slice you pass to unsafe.SizeOf(), it always returns 12 on the Go Playground (and 24 on 64-bit architectures).

On the other hand, an array value includes all its elements, and as such, its size depends on its length. Size of [10]bool is 10, and size of [20]bool is 20.

See related questions+answers to learn more about slices, arrays and the difference and relation between them:

https://stackoverflow.com/questions/35937828/how-do-i-find-the-size-of-the-array-in-go/35939008#35939008

https://stackoverflow.com/questions/38645175/why-have-arrays-in-go/38645895#38645895

https://stackoverflow.com/questions/30694652/why-use-arrays-instead-of-slices

Must read blog posts:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

答案2

得分: 1

ind1 是一个切片(类型为 []bool)。

ind2 是一个数组(类型为 [10]bool)。

它们的类型不同。

unsafe.Sizeof(ind1) 的结果可能与传递给 make 的参数无关。

英文:

ind1 is a slice (the type is []bool).

ind2 is an array (the type is [10]bool).

They are not of the same type.

The result of unsafe.Sizeof(ind1) probably has nothing to do with the arguments passed to make.

huangapple
  • 本文由 发表于 2017年2月13日 18:27:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/42201804.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定