Skip to content

Preprocessor Directives

Philip Hofer edited this page Apr 7, 2015 · 4 revisions

You can make tweaks to how the code generator generates methods using directives in your source code comments. All directives take the form

//msgp:directive [arg1] [arg2] [arg3]...

much like the gc compiler directives.

There are two flavors of directives: global and pass-specific.

Global Directives

Ignore
//msgp:ignore Type1 Type2 Type3

Ignore tells the code generator not to generate methods for the list of types supplied.

Tuple
//msgp:tuple TypeA

type TypeA struct {
    Left  float64
    Right float64
}

The msgp:tuple directive tells the generator to generate code for the struct so that it is serialized as an array instead of a map. In other words, TypeA{1.0, 2.0} above would be encoded as

[1.0,2.0]

instead of

{"Left":1.0,"Right":2.0}

For smaller objects, tuple encoding can yield serious performance improvements.

Shim
//msgp:shim Enum as:string using:(Enum).String/parseString

type Enum byte

const(
    A Enum = iota
    B
    C
    D
    invalid
)

func (e Enum) String() string {
    switch e {
    case A:
        return "A"
    case B:
        return "B"
    case C:
        return "C"
    case D:
        return "D"
    default:
        return "<invalid>"
    }
}

func parseString(s string) Enum {
    switch s {
    case "A":
        return A
    case "B":
        return B
    case "C":
        return C
    case "D":
        return D
    default:
        return invalid
    }
}

The shim directive lets you inline a type-conversion function for a user-defined type in order to have it encode and decode differently than the default for its concrete type. In the example above, we're using the shim directive to translate a const-iota block into strings for encoding and decoding. Note that the as: argument must take a "base" type (a built-in, []byte, interface{}, msgp.Extension or a type already processed by the code generator.)

Pass-Specific Directives

A pass-specific directive operates on one particular code generation pass. They take the form

//msgp:passname directives [arg1] [arg2] ...

The valid pass names are as follows:

  • encode
  • decode
  • marshal
  • unmarshal
  • size
  • test
Ignore

The ignore directive can be applied to a particular combination of pass and type when invoked like:

//msgp:encode ignore Type1 Type2...

Methods that are ignored also do not produce test cases. (The code generator is aware of the dependency.)

Ignore can be particularly useful when you don't want the code generator to clobber an existing manually-written implementation of one of the methods.