为什么 binary.Size() 返回 (-1)?

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

Why the binary.Size() return (-1)?

问题

代码片段如下:

package main
import (
    "fmt"
    "encoding/binary"
    "reflect"
)

const (
    commandLen = 1
    bufLen int = 4
)

func main(){
    fmt.Printf("%v %v\n", reflect.TypeOf(commandLen), reflect.TypeOf(bufLen))
    fmt.Printf("%d %d", binary.Size(commandLen), binary.Size(bufLen))
}

输出结果为:

int int
-1 -1

我认为由于commandLenbufLen的类型是int,根据《Go语言编程》一书,int的具体大小取决于实现,可能是int32int64。因此,我认为binary.Size()应该返回一个值,而不是-1

为什么binary.Size()返回-1呢?

英文:

The code snippet likes this:

package main
import (
    "fmt"
    "encoding/binary"
    "reflect"
)

const (
    commandLen = 1
    bufLen int = 4
)

func main(){
    fmt.Printf("%v %v\n", reflect.TypeOf(commandLen), reflect.TypeOf(bufLen))
    fmt.Printf("%d %d", binary.Size(commandLen), binary.Size(bufLen))
}

And the output is:

int int
-1 -1

I think since the types of commandLen and bufLen are int, and from "Programming in golang",
the int should be int32 or int64 which depending on the implementation, so I think the binary.Size() should return a value, not (-1).

Why the binary.Size() return (-1)?

答案1

得分: 3

tl;dr

int不是固定长度的类型,所以它不起作用。使用具有固定长度的类型,例如int32

解释

这看起来可能像是一个bug,但实际上并不是bug。Size()的文档中写道:

> Size返回编码值v所需生成的字节数,v必须是固定大小的值或固定大小值的切片,或指向这些数据的指针。

固定大小的值是指不依赖于架构且大小事先已知的值。这适用于int32int64,但不适用于int,因为它取决于环境的架构。请参阅int的文档

如果你想知道为什么Size()要强制执行这个规定,考虑在64位机器上对int进行编码,然后在远程的32位机器上解码数据。只有当你有长度编码类型时,这才是可能的,而int不是长度编码类型。所以你要么将大小与类型一起存储,要么强制使用固定长度的类型,这是开发人员所做的。

这反映在encoding/binary包的sizeof()函数中计算大小的方式:

case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
       reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
       reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
       return int(t.Size()), nil

如你所见,所有的数值类型都列在其中,但没有reflect.Int

英文:

tl;dr

int is not a fixed-length type, so it won't work. Use something that has a fixed length, for example int32.

Explanation

This might look like a bug but it is actually not a bug. The documentation of Size() says:

> Size returns how many bytes Write would generate to encode the value v, which must be a
> fixed-size value or a slice of fixed-size values, or a pointer to such data.

A fixed-size value is a value that is not dependent on the architecture and the size is known
beforehand. This is the case for int32 or int64 but not for int as it depends on the
environment's architecture. See the documentation of int.

If you're asking yourself why Size() enforces this, consider encoding an int on your
64 bit machine and decoding the data on a remote 32 bit machine. This is only possible if you have length encoded types, which int is not. So you either have to store the size along with the type or enforce fixed-length types which the developers did.

This is reflected in the sizeof() function of encoding/binary that computes the size:

case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
       reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
       reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
       return int(t.Size()), nil

As you can see, there are all number types listed but reflect.Int.

huangapple
  • 本文由 发表于 2013年10月25日 09:50:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/19579812.html
匿名

发表评论

匿名网友

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

确定