英文:
How to serialize slice of fixed length data structure in Go
问题
以下代码生成了panic: binary.Write: invalid type main.test的错误:
type (
config struct {
Key uint16
Val uint16
}
test struct {
Mode uint32
Data []config
}
)
func main() {
t := test{
Mode: 5,
Data: []config{
{1, 2},
{3, 4},
},
}
var bs bytes.Buffer
assert(binary.Write(&bs, binary.LittleEndian, t))
}
关键点是:
config
数据结构的长度是固定的,但test
结构包含一个可变数量的config
切片。- 我需要与用 C 编写的其他程序进行交互,所以不能使用类似 GOB 的东西。
除了手动操作之外,是否有其他方法可以对这样的数据结构进行二进制编码?
英文:
The following code generates panic: binary.Write: invalid type main.test:
type (
config struct {
Key uint16
Val uint16
}
test struct {
Mode uint32
Data []config
}
)
func main() {
t := test{
Mode: 5,
Data: []config{
{1, 2},
{3, 4},
},
}
var bs bytes.Buffer
assert(binary.Write(&bs, binary.LittleEndian, t))
}
The key point is:
- length of the
config
data structure is fixed, but thetest
structure contains a slice ofconfig
, whose number varies. - I need to interact with other program written in C, so cannot use things like GOB.
Is there anyway to binary-encode such data structure, apart from do it manually?
答案1
得分: 3
问题不在于写出一个切片,因为切片是支持的。引用自binary.Write()
:
> Write将数据的二进制表示写入w。数据必须是固定大小的值或固定大小值的切片,或者是指向这种数据的指针。
问题在于config
的大小不是固定的。它的大小不是固定的,因为它包含一个切片类型的字段,而切片的二进制表示不是固定的(取决于其长度)。
因此,虽然支持写入切片值,但不支持写入包含切片的复合类型值(例如结构体),原因如上所述。
你可以将该字段更改为数组类型(例如[2]config
),但我假设这对你来说不够。
你可以使用encoding/binary
逐个写入字段,这样你就可以写入切片值。
例如:
var bs bytes.Buffer
fmt.Println(binary.Write(&bs, binary.LittleEndian, t.Mode))
fmt.Println(binary.Write(&bs, binary.LittleEndian, t.Data))
这将输出(在Go Playground上尝试):
<nil>
<nil>
曾经有一个提案扩展encoding/binary
以支持类似的情况(参见这里),但被拒绝了。encoding/binary
适用于简单的情况。
如果你需要更多的灵活性,可以使用encoding/gob
(虽然是Go特定的),或者使用encoding/json
(被所有语言支持)。
英文:
The problem is not writing out a slice, as slices are supported. Quoting from binary.Write()
:
> Write writes the binary representation of data into w. Data must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
The problem is that the size of config
is not fixed. It is not fixed because it contains a field of slice type, and the binary representation of the slice is not fixed (depends on its length).
So writing a slice value is supported, writing a value of composite type (e.g. struct) holding a slice is not supported for the above mentioned reason.
You may change the field to an array type (e.g. [2]config
) but I assume this isn't sufficient to you.
You may write the fields using encoding/binary
individually, in which case you can write a slice value.
For example:
var bs bytes.Buffer
fmt.Println(binary.Write(&bs, binary.LittleEndian, t.Mode))
fmt.Println(binary.Write(&bs, binary.LittleEndian, t.Data))
This will output (try it on the Go Playground):
<nil>
<nil>
There was a proposal to extend encoding/binary
to support similar cases (see here), but was rejected. encoding/binary
is for simple things.
If you need more flexibility, use encoding/gob
(although Go specific), or use encoding/json
(supported by all languages).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论