Skip to content

Instantly share code, notes, and snippets.

@justinschuldt
Created October 27, 2022 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinschuldt/d8a4a639bedf5ee80b99703fe0f1bb4a to your computer and use it in GitHub Desktop.
Save justinschuldt/d8a4a639bedf5ee80b99703fe0f1bb4a to your computer and use it in GitHub Desktop.
Golang implement encoding.BinaryMarshaler & encoding.BinaryUnmarshaler example
// Golang program to illustrate the implementation of
// a encoding.BinaryMarshaler interface, and
// a encoding.BinaryUnmarshaler interface for a struct.
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
type DemoStruct struct {
name string
}
// MustWrite calls binary.Write and panics on errors
func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
if err := binary.Write(w, order, data); err != nil {
panic(fmt.Errorf("failed to write binary data: %v", data).Error())
}
}
// implement encoding.BinaryMarshaler interface for DemoStruct
func (b DemoStruct) MarshalBinary() ([]byte, error) {
buf := new(bytes.Buffer)
nameBytes := []byte(b.name)
bytesLen := len(nameBytes)
MustWrite(buf, binary.BigEndian, uint8(bytesLen))
buf.Write(nameBytes)
return buf.Bytes(), nil
}
// implement encoding.BinaryUnmarshaler interface for DemoStruct
func (s *DemoStruct) UnmarshalBinary(data []byte) error {
d := &DemoStruct{}
bytesLen := data[0]
reader := bytes.NewReader(data[1:])
nameBytes := make([]byte, uint8(bytesLen))
if n, err := reader.Read(nameBytes[:]); err != nil {
return fmt.Errorf("failed to read nameBytes [%d]: %w", n, err)
}
d.name = string(nameBytes)
fmt.Printf("d.name after unmarshal %v\n", d.name)
// dereference the newly created struct and assign its value to the context of the method
*s = *d
return nil
}
func main() {
p := DemoStruct{name: "Struct1"}
// Calling MarshalBinary() method
encoding, encodeErr := p.MarshalBinary()
if encodeErr != nil {
fmt.Printf("failed encoding, err: %w\n", encodeErr)
}
// Defining ds for UnmarshalBinary() method
var ds DemoStruct
decodeErr := ds.UnmarshalBinary(encoding)
fmt.Printf("Error: %v\n", decodeErr)
// check the value came out the other end
fmt.Printf("ds.name at the end: %v", ds.name)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment