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?
CodePudding user response:
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).