Package option
implements effective and useful instruments to work
with optional types in Go. It eliminates code doubling and provides
high performance due to:
- no memory allocations
- serialization without reflection (at least for pre-generated types)
- support for basic and custom types
go install github.com/tarantool/go-option@latest
You could run the godoc
server on localhost:6060
with the command:
make godoc_run
And open the generated documentation in another terminal or use the link:
make godoc_open
Generated types follow the pattern Optional and provide methods for working with optional values:
// Create an optional with a value.
opt := SomeOptionalString("hello")
// Check if a value is present.
if opt.IsSome() {
value := opt.Unwrap()
fmt.Println(value)
}
// Use a default value if none.
value := opt.UnwrapOr("default")
// Encode to MessagePack.
err := opt.EncodeMsgpack(encoder)
It may be necessary to use an optional type in a structure. For example, to distinguish between a nil value and a missing one.
package main
import (
"github.com/tarantool/go-option"
tarantool "github.com/tarantool/go-tarantool/v2"
)
type User struct {
// may be used in conjunciton with 'msgpack:",omitempty"' directive to skip fields
_msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused
Name string
Phone option.String
}
func main() {
var conn *tarantool.Doer
// Initialize tarantool connection
// Imagine you get a slice of users from Tarantool.
users := []User{
{
Name: "Nosipho Nnenne",
Phone: option.SomeString("+15056463408"),
},
{
Name: "Maryamu Efe",
Phone: option.NoneString(),
},
{
Name: "Venera Okafor",
},
}
for id, user := range users {
conn.Do(
tarantool.NewInsertRequest("users").Tuple(user),
)
}
}
A Go code generator for creating optional types with MessagePack serialization support.
Gentype generates wrapper types for various Go primitives and custom types that implement optional (some/none) semantics with full MessagePack serialization capabilities. These generated types are useful for representing values that may or may not be present, while ensuring proper encoding and decoding when using MessagePack.
- Generates optional types for built-in types (bool, int, float, string, etc.)
- Supports custom types with MessagePack extension serialization
- Provides common optional type operations:
SomeXxx(value)
- Create an optional with a valueNoneXxx()
- Create an empty optionalUnwrap()
,UnwrapOr()
,UnwrapOrElse()
- Value extractionIsSome()
,IsNone()
- Presence checking
- Full MessagePack
CustomEncoder
andCustomDecoder
implementation - Type-safe operations
go install github.com/tarantool/go-option/cmd/gentypes@latest
# OR (for go version 1.24+)
go get -tool github.com/tarantool/go-option/cmd/gentypes@latest
To generate optional types for existing types in a package:
gentypes -package ./path/to/package -ext-code 123
# OR (for go version 1.24+)
go tool gentypes -package ./path/to/package -ext-code 123
Or you can use it to generate file from go:
//go:generate go run github.com/tarantool/go-option/cmd/gentypes@latest -ext-code 123
// OR (for go version 1.24+)
//go:generate go tool gentypes -ext-code 123
Flags:
-package
: Path to the Go package containing types to wrap (default:"."
)-ext-code
: MessagePack extension code to use for custom types (must be between -128 and 127, no default value)-verbose
: Enable verbose output (default:false
)-force
: Ignore absence of marshal/unmarshal methods on type (default:false
). Helpful for types from third-party modules.-imports
: Add imports to generated file (default is empty). Helpful for types from third-party modules.-marshal-func
: func that should do marshaling (default isMarshalMsgpack
method). Helpful for types from third-party modules. Should be func of typefunc(v T) ([]byte, error)
and should be located in the same dir or should be imported.-unmarshal-func
: func that should do unmarshalling (default isUnmarshalMsgpack
method). Helpful for types from third-party modules. Should be func of typefunc(v *T, data []byte) error
and should be located in the same dir or should be imported.
Sometimes you need to generate an optional type for a type from a third-party module,
and you can't add MarshalMsgpack
/UnmarshalMsgpack
methods to it.
In this case, you can use the -force
, -imports
, -marshal-func
, and -unmarshal-func
flags.
For example, to generate an optional type for github.com/google/uuid.UUID
:
-
Create a file with marshal and unmarshal functions for the third-party type. For example,
uuid.go
:package main import ( "errors" "github.com/google/uuid" ) func encodeUUID(uuid uuid.UUID) ([]byte, error) { return uuid[:], nil } var ( ErrInvalidLength = errors.New("invalid length") ) func decodeUUID(uuid *uuid.UUID, data []byte) error { if len(data) != len(uuid) { return ErrInvalidLength } copy(uuid[:], data) return nil }
-
Use the following
go:generate
command://go:generate go run github.com/tarantool/go-option/cmd/gentypes@latest -package . -imports "github.com/google/uuid" -type UUID -marshal-func "encodeUUID" -unmarshal-func "decodeUUID" -force -ext-code 100
Generated types follow the pattern Optional and provide methods for working with optional values:
// Create an optional with a value.
opt := SomeOptionalString("hello")
// Check if a value is present.
if opt.IsSome() {
value := opt.Unwrap()
fmt.Println(value)
}
// Use a default value if none.
value := opt.UnwrapOr("default")
// Encode to MessagePack.
err := opt.EncodeMsgpack(encoder)
You could use our Makefile targets:
make codespell
make test
make testrace
make coveralls-deps
make coveralls
make coverage
To run default set of tests directly:
go test ./... -count=1
BSD 2-Clause License