【问题标题】:Equivalent of sizeof(aType) in Go相当于 Go 中的 sizeof(aType)
【发布时间】:2014-02-25 23:33:52
【问题描述】:

C++ 和其他几种语言都有一个名为 sizeof(int)(或您需要的任何类型)的函数,它返回当前系统中特定数据类型消耗的字节数。

Go 中有没有等价的函数?这是什么?

【问题讨论】:

  • 请注意,在 Go 中,99.9% 的时间这些信息都是无用的(这就是为什么 Sizeof 内置在 unsafe 包中)所以如果你对这些东西感兴趣您可能正在考虑直接解释来自外部的某些字节序列(产生它们)。除非你是高手并且真的知道你将要做什么,那没关系,否则,请三思而后行。请参考this处理类似的谬误。
  • @kostix - 我有一个很久以前用 C++ 编写的内存数据集库 - 它使用字节缓冲区来保存其数据,我使用 sizeof() 来定义缓冲区偏移量。我正在用 Go 复制那个库——我想它会帮助我快速进入很多不同的领域。但随着我的学习,我在 C++ 中的做法可能不是 Go 的做事方式......
  • 我已经发布了我对此想法的总结作为答案(评论太短了)。希望它会以某种方式有用。

标签: c++ types go size sizeof


【解决方案1】:

如果您想找出特定的大小,有两种方法可以做到这一点 - 使用 unsafe 包,或使用反射包。以下代码演示了两者:

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func main() {
    var i int
    fmt.Printf("Size of var (reflect.TypeOf.Size): %d\n", reflect.TypeOf(i).Size())
    fmt.Printf("Size of var (unsafe.Sizeof): %d\n", unsafe.Sizeof(i))
}

但是,我不知道直接获取 type 大小的方法。但我想你会发现 sizeof 函数不像 C 语言那样经常需要。

【讨论】:

  • 我接受这个答案,因为您涵盖了 reflection 以及 unsafe。
【解决方案2】:

sizeof 在 go 中的等价物是 unsafe.Sizeof。它与 C 中的 sizeof 之间的一个区别是它仅在值上定义(而在 C 中,它适用于值和类型)。另一个主要区别是,在 Go 中几乎不需要它,而在 C 中它相当普遍。

一个例子是:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    fmt.Println(unsafe.Sizeof(int(0)))
}

【讨论】:

  • 并没有真正回答这个问题:不寻找特定值的大小,尽管可以通过使用所需类型的虚拟值来实现。
  • @ComeAndGo:没有任何等价物可以在不涉及值的情况下直接从类型定义转到大小。您在此处看到的答案确实与 C 功能最接近。
  • @JamesHenstridge - 是的,所以我开始看到 - 今天正在阅读它 - 在 int/uint 之外,大小在类型中明确定义,字符串是字符串。我想与我最相关的是日期/时间类型。必须学习更多。
【解决方案3】:

如果您只是想了解intuint 的大小,请使用strconv.IntSize

Package strconv

Constants

const IntSize = intSize

IntSizeintuint 值的位大小。

例如,

package main

import (
    "fmt"
    "runtime"
    "strconv"
)

func main() {
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

输出:

gc amd64 linux
64

【讨论】:

  • 好吧,我看到这只是为 int 或 uint 定义的。我想是因为 int32 和 int64 和 string 很明显......
【解决方案4】:

不是真正的答案,而是原始问题之后 cmets 线程的延续……

要实现内存数据集,我会采用以下方法之一:

  • (头脑简单):只需使用interface{} 的数组来存储行。

    接口类型的每个值都是两个指针的元组:指向封闭值的真实类型的指针和值本身。实现是gc(和gccgo,我相信)足够聪明,可以将值直接存储在该指针空间中,如果它的大小是≤目标平台上uintptr 类型的大小。

  • (据说更高级):将列的类型信息存储在单独的数据结构(数组或切片)中;可以使用reflect 包中的工具获取类型信息。然后将实际数据存储在unsafe.Pointer 数组的行中,并发挥与gc 中接口的实现相同的技巧,使用从/到unsafe.Pointer 的类型转换来处理值。

    这将允许您通过不将值的类型与每个包含的值一起存储来更节省空间。不确定真正的性能优势(如果有的话)。

【讨论】:

  • 方法 2 是我在 C++ 中所做的 - 然后我只是读取字节 @ 偏移量将它们写入具有适当类型的结构 - 所有预定义和分隔 @ 编译时间,非常 快速@运行时。它本质上是从 Delphi 的 TDataSet 模型中提取出来的——一个“fielddefs”数组和一个表示“rows”的通用字节数组,每一行的布局都符合“field defs”描述。
  • @ComeAndGo,这里的主要思想是存储unsafe.Pointers 的数组而不是bytes——这可能会浪费一些空间(但 Go 不是 Delphi,可能在平台上工作具有严格的对齐要求)但易于计算偏移量。
  • @ComeAndGo,看看实现会很有趣——请考虑发布它(并在 golang-nuts 上宣布)
  • unsafe.Pointers 数组而不是字节数组 - 是的,它就是这样做的。如果我的设计和工作令人满意,我的意图是发布它,但我希望它是 Go,而不是来自 C++ 或 Delphi 的移植。
  • @ComeAndGo,顺便说一句,您可能会发现查看 ql 包很有趣;特别是它的mem.go 文件。
猜你喜欢
  • 2019-09-19
  • 2017-04-10
  • 1970-01-01
  • 2022-01-23
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
相关资源
最近更新 更多