Skip to content

tarantool/go-option

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go Reference Actions Status Code Coverage Telegram EN Telegram RU

go-option: library to work with optional types

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

Table of contents

Installation

go install github.com/tarantool/go-option@latest

Documentation

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

Quick start

Using pre-generated optional types

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)

Usage with go-tarantool

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),
        )
    }
}

Gentype Utility

A Go code generator for creating optional types with MessagePack serialization support.

Overview

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.

Features

  • 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 value
    • NoneXxx() - Create an empty optional
    • Unwrap(), UnwrapOr(), UnwrapOrElse() - Value extraction
    • IsSome(), IsNone() - Presence checking
  • Full MessagePack CustomEncoder and CustomDecoder implementation
  • Type-safe operations

Gentype installation

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

Generating Optional Types

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 is MarshalMsgpack method). Helpful for types from third-party modules. Should be func of type func(v T) ([]byte, error) and should be located in the same dir or should be imported.
  • -unmarshal-func: func that should do unmarshalling (default is UnmarshalMsgpack method). Helpful for types from third-party modules. Should be func of type func(v *T, data []byte) error and should be located in the same dir or should be imported.

Generating Optional Types for Third-Party Modules

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:

  1. 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
    }
  2. 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

Using Generated Types

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)

Development

You could use our Makefile targets:

make codespell
make test
make testrace
make coveralls-deps
make coveralls
make coverage

Run tests

To run default set of tests directly:

go test ./... -count=1

License

BSD 2-Clause License

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •