使用 make 或默认初始化的不同大小的数组
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 over default initialization?
ind1
是一个切片(类型是[]bool
)。
ind2
是一个数组(类型是[10]bool
)。
它们不是同一类型。
unsafe.Sizeof(ind1)
的结果可能与传递给 make
的参数无关。
Arrays and slices 在 Go 中是不同的东西。
你的ind1
是一个切片,ind2
是一个数组。数组的长度是类型的一部分,因此例如 [2]bool
和 [3]bool
是 2 种不同的数组类型。
Go 中的切片是底层数组的 连续段 的描述符,并提供对该数组中元素的编号序列的访问。这个切片头是一个 struct-like 数据结构,由 reflect.SliceHeader
:
类型表示
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
它包含一个数据指针(指向所表示段的第一个元素)、一个长度和一个容量。
unsafe.SizeOf()
函数 returns 假设变量的大小(以字节为单位),就好像它将保存传递的值一样。 它不包括它可能引用的任何内存。
所以如果你传递一个切片值(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 上它总是 returns 12(在 64 位架构上为 24)。
另一方面,数组值包括它的所有元素,因此,它的大小取决于它的长度。 [10]bool
的大小为10,[20]bool
的大小为20。
查看相关问答,了解切片、数组以及它们之间的区别和关系:
必读博文:
我是 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 over default initialization?
ind1
是一个切片(类型是[]bool
)。
ind2
是一个数组(类型是[10]bool
)。
它们不是同一类型。
unsafe.Sizeof(ind1)
的结果可能与传递给 make
的参数无关。
Arrays and slices 在 Go 中是不同的东西。
你的ind1
是一个切片,ind2
是一个数组。数组的长度是类型的一部分,因此例如 [2]bool
和 [3]bool
是 2 种不同的数组类型。
Go 中的切片是底层数组的 连续段 的描述符,并提供对该数组中元素的编号序列的访问。这个切片头是一个 struct-like 数据结构,由 reflect.SliceHeader
:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
它包含一个数据指针(指向所表示段的第一个元素)、一个长度和一个容量。
unsafe.SizeOf()
函数 returns 假设变量的大小(以字节为单位),就好像它将保存传递的值一样。 它不包括它可能引用的任何内存。
所以如果你传递一个切片值(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 上它总是 returns 12(在 64 位架构上为 24)。
另一方面,数组值包括它的所有元素,因此,它的大小取决于它的长度。 [10]bool
的大小为10,[20]bool
的大小为20。
查看相关问答,了解切片、数组以及它们之间的区别和关系:
必读博文: