Convert Figma logo to code with AI

tinylib logomsgp

A Go code generator for MessagePack / msgpack.org[Go]

1,853
196
1,853
42

Top Related Projects

1,895

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]

2,979

faster JSON serialization for Go

Fast JSON serializer for golang.

Quick Overview

tinylib/msgp is a Go library for MessagePack serialization. It provides a code generation tool that creates highly optimized MessagePack encoding and decoding functions for Go struct types, offering significant performance improvements over reflection-based serialization methods.

Pros

  • High performance: Generated code is typically much faster than reflection-based alternatives
  • Type safety: Compile-time type checking ensures correct serialization and deserialization
  • Low memory allocation: Generated code minimizes heap allocations for better performance
  • Easy integration: Works seamlessly with existing Go types and structures

Cons

  • Requires code generation: Extra step in the build process
  • Limited flexibility: Generated code is specific to defined structures
  • Learning curve: Understanding and using code generation may be new for some developers
  • Maintenance overhead: Generated code needs to be updated when struct definitions change

Code Examples

  1. Defining a struct with msgp tags:
//go:generate msgp
type Person struct {
    Name    string `msg:"name"`
    Age     int    `msg:"age"`
    Address string `msg:"address,omitempty"`
}
  1. Encoding a struct to MessagePack:
person := Person{Name: "Alice", Age: 30}
bytes, err := person.MarshalMsg(nil)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Encoded: %x\n", bytes)
  1. Decoding MessagePack data to a struct:
var decodedPerson Person
_, err = decodedPerson.UnmarshalMsg(bytes)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Decoded: %+v\n", decodedPerson)

Getting Started

  1. Install msgp:

    go get github.com/tinylib/msgp
    
  2. Add msgp tags to your structs and use the //go:generate msgp comment:

    //go:generate msgp
    type MyStruct struct {
        Field1 string `msg:"field1"`
        Field2 int    `msg:"field2"`
    }
    
  3. Generate code:

    go generate ./...
    
  4. Use the generated methods in your code:

    data := MyStruct{Field1: "Hello", Field2: 42}
    bytes, err := data.MarshalMsg(nil)
    // Use bytes for transmission or storage
    

Competitor Comparisons

1,895

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]

Pros of go

  • Supports a wider range of data formats, including JSON, MessagePack, CBOR, and more
  • Offers more flexibility in customization and configuration options
  • Provides better support for complex data structures and interfaces

Cons of go

  • Generally slower performance compared to msgp
  • More complex API and usage, requiring more setup and configuration
  • Larger codebase and dependencies, potentially increasing build times and binary sizes

Code Comparison

msgp:

//go:generate msgp
type Person struct {
    Name string
    Age  int
}

go:

type Person struct {
    Name string `json:"name" codec:"name"`
    Age  int    `json:"age" codec:"age"`
}

var codec = codec.New()

Both libraries aim to provide efficient serialization and deserialization for Go applications. msgp focuses specifically on MessagePack format and generates code for optimal performance. It's simpler to use but limited to MessagePack.

go offers a more versatile solution, supporting multiple formats and providing greater flexibility. However, this comes at the cost of slightly lower performance and increased complexity.

Choose msgp for MessagePack-specific, high-performance needs with simple setup. Opt for go when requiring support for multiple formats or more advanced customization options.

2,979

faster JSON serialization for Go

Pros of ffjson

  • Supports more complex Go types, including maps and interfaces
  • Provides a command-line tool for generating serialization code
  • Offers better performance for large, complex JSON structures

Cons of ffjson

  • Generates larger code files compared to msgp
  • May have slower performance for simpler data structures
  • Requires manual regeneration of code when struct definitions change

Code Comparison

msgp:

//go:generate msgp
type Person struct {
    Name string `msg:"name"`
    Age  int    `msg:"age"`
}

ffjson:

//go:generate ffjson $GOFILE
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

Both libraries use code generation to create efficient serialization methods. msgp focuses on MessagePack encoding, while ffjson targets JSON specifically. msgp generally produces more compact code and faster serialization for simple structures, but ffjson offers more flexibility for complex JSON handling.

The choice between these libraries depends on the specific requirements of your project, such as the complexity of your data structures, performance needs, and whether you're working exclusively with JSON or need support for other formats like MessagePack.

Fast JSON serializer for golang.

Pros of easyjson

  • Supports more flexible struct tags for customizing JSON output
  • Provides an option for lexicographical sorting of map keys
  • Offers better performance for large, complex JSON structures

Cons of easyjson

  • Requires manual code generation, unlike msgp's runtime reflection
  • Has a more complex API and usage compared to msgp's simplicity
  • May produce larger binary sizes due to generated code

Code Comparison

easyjson:

//easyjson:json
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

msgp:

//msgp:encode msgp:decode
type Person struct {
    Name string `msg:"name"`
    Age  int    `msg:"age"`
}

Both libraries aim to improve JSON encoding/decoding performance in Go, but they take different approaches. easyjson focuses on JSON-specific optimizations and offers more customization options, while msgp provides a simpler API and supports multiple serialization formats.

easyjson generates marshalers and unmarshalers for specific structs, resulting in highly optimized code for each type. msgp, on the other hand, uses a more generic approach with runtime reflection, which can be faster for simpler structures but may lag behind for complex JSON data.

Ultimately, the choice between easyjson and msgp depends on the specific requirements of your project, such as performance needs, code complexity tolerance, and desired level of customization.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

MessagePack Code Generator

Go Reference test validate

This is a code generation tool and serialization library for MessagePack. You can read more about MessagePack in the wiki, or at msgpack.org.

Why?

Quickstart

First install the msgp generator command. Using Go this is done with go install github.com/tinylib/msgp@latest

In a source file, include the following directive:

//go:generate msgp

The msgp command will generate serialization methods for all exported type declarations in the file.

You can read more about the code generation options here.

Use

Field names can be set in much the same way as the encoding/json package. For example:

type Person struct {
	Name       string `msg:"name"`
	Address    string `msg:"address"`
	Age        int    `msg:"age"`
	Hidden     string `msg:"-"` // this field is ignored
	unexported bool             // this field is also ignored
}

By default, the code generator will satisfy msgp.Sizer, msgp.Encodable, msgp.Decodable, msgp.Marshaler, and msgp.Unmarshaler. Carefully-designed applications can use these methods to do marshalling/unmarshalling with zero heap allocations.

While msgp.Marshaler and msgp.Unmarshaler are quite similar to the standard library's json.Marshaler and json.Unmarshaler, msgp.Encodable and msgp.Decodable are useful for stream serialization. (*msgp.Writer and *msgp.Reader are essentially protocol-aware versions of *bufio.Writer and *bufio.Reader, respectively.)

An important thing to note is that msgp operates on individual files. This means if your structs include types defined in other files, these must be processed as well.

Features

  • Extremely fast generated code
  • Test and benchmark generation
  • JSON interoperability (see msgp.CopyToJSON() and msgp.UnmarshalAsJSON())
  • Support for complex type declarations
  • Native support for Go's time.Time, complex64, and complex128 types
  • Generation of both []byte-oriented and io.Reader/io.Writer-oriented methods
  • Support for arbitrary type system extensions
  • Preprocessor directives
  • File-based dependency model means fast codegen regardless of source tree size.

Consider the following:

const Eight = 8
type MyInt int
type Data []byte

type Struct struct {
	Which  map[string]*MyInt `msg:"which"`
	Other  Data              `msg:"other"`
	Nums   [Eight]float64    `msg:"nums"`
}

As long as the declarations of MyInt and Data are in the same file as Struct, the parser will determine that the type information for MyInt and Data can be passed into the definition of Struct before its methods are generated.

Extensions

MessagePack supports defining your own types through "extensions," which are just a tuple of the data "type" (int8) and the raw binary. You can see a worked example in the wiki.

Status

Mostly stable, in that no breaking changes have been made to the /msgp library in more than a year. Newer versions of the code may generate different code than older versions for performance reasons. I (@philhofer) am aware of a number of stability-critical commercial applications that use this code with good results. But, caveat emptor.

You can read more about how msgp maps MessagePack types onto Go types in the wiki.

Here some of the known limitations/restrictions:

  • Identifiers from outside the processed source file are assumed (optimistically) to satisfy the generator's interfaces. If this isn't the case, your code will fail to compile.
  • Like most serializers, chan and func fields are ignored, as well as non-exported fields.
  • Encoding of interface{} is limited to built-ins or types that have explicit encoding methods.
  • Maps must have string keys. This is intentional (as it preserves JSON interop.) Although non-string map keys are not forbidden by the MessagePack standard, many serializers impose this restriction. (It also means any well-formed struct can be de-serialized into a map[string]interface{}.) The only exception to this rule is that the deserializers will allow you to read map keys encoded as bin types, due to the fact that some legacy encodings permitted this. (However, those values will still be cast to Go strings, and they will be converted to str types when re-encoded. It is the responsibility of the user to ensure that map keys are UTF-8 safe in this case.) The same rules hold true for JSON translation.

If the output compiles, then there's a pretty good chance things are fine. (Plus, we generate tests for you.) Please, please, please file an issue if you think the generator is writing broken code.

Performance

If you like benchmarks, see here and here.

As one might expect, the generated methods that deal with []byte are faster for small objects, but the io.Reader/Writer methods are generally more memory-efficient (and, at some point, faster) for large (> 2KB) objects.