Optional is a library of optional Go types
Switch branches/tags
Nothing to show
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cmd/optional Marshal empty as null (#9) Dec 7, 2018
vendor/github.com Update dependencies/prune; change to golangci-lint for linter Sep 21, 2018
.gitignore vendor folder Jul 25, 2017
.golangci.yml Update dependencies/prune; change to golangci-lint for linter Sep 21, 2018
.travis.yml Try go 1.11 on travis Nov 14, 2018
CONTRIBUTING.md Update goldenfiles cmd Nov 15, 2018
Gopkg.lock Update dependencies/prune; change to golangci-lint for linter Sep 21, 2018
Gopkg.toml Update dependencies/prune; change to golangci-lint for linter Sep 21, 2018
LICENSE.md Initial commit Jul 15, 2017
Makefile Update Makefile and Contributing guide Nov 15, 2018
README.md Add section on test coverage and cleanup README Dec 10, 2018
bool.go Marshal empty as null (#9) Dec 7, 2018
byte.go Marshal empty as null (#9) Dec 7, 2018
complex128.go Marshal empty as null (#9) Dec 7, 2018
complex64.go Marshal empty as null (#9) Dec 7, 2018
error.go Marshal empty as null (#9) Dec 7, 2018
example_test.go Add example test Dec 7, 2018
float32.go Marshal empty as null (#9) Dec 7, 2018
float64.go Marshal empty as null (#9) Dec 7, 2018
generate.go Alphabetizing files to generate [ci skip] Mar 25, 2018
int.go Marshal empty as null (#9) Dec 7, 2018
int16.go Marshal empty as null (#9) Dec 7, 2018
int32.go Marshal empty as null (#9) Dec 7, 2018
int64.go Marshal empty as null (#9) Dec 7, 2018
int8.go Marshal empty as null (#9) Dec 7, 2018
int_test.go Unit tests (#10) Dec 10, 2018
rune.go Marshal empty as null (#9) Dec 7, 2018
string.go Marshal empty as null (#9) Dec 7, 2018
string_test.go Unit tests (#10) Dec 10, 2018
uint.go Marshal empty as null (#9) Dec 7, 2018
uint16.go Marshal empty as null (#9) Dec 7, 2018
uint32.go Marshal empty as null (#9) Dec 7, 2018
uint64.go Marshal empty as null (#9) Dec 7, 2018
uint8.go Marshal empty as null (#9) Dec 7, 2018
uintptr.go Marshal empty as null (#9) Dec 7, 2018

README.md

Optional

Build Status Release Software License Go Doc Go Report Card SayThanks.io

Optional is a library that provides option types for the primitive Go types.

It can also be used as a tool to generate option type wrappers around your own types.

Motivation

In Go, variables declared without an explicit initial value are given their zero value. Most of the time this is what you want, but sometimes you want to be able to tell if a variable was set or if it's just a zero value. That's where option types come in handy.

Marshalling/Unmarshalling JSON

Note: v0.6.0 introduces a potential breaking change to anyone depending on marshalling non-present values to their zero values instead of null. See: #9 for more context.

Option types marshal to/from JSON as you would expect:

Marshalling

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var value = struct {
		Field optional.String `json:"field,omitempty"`
	}{
		Field: optional.NewString("bar"),
	}

	out, _ := json.Marshal(value)

	fmt.Println(string(out))
	// outputs: {"field":"bar"}
}

Unmarshalling

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var value = &struct {
		Field optional.String `json:"field,omitempty"`
	}{}

	_ = json.Unmarshal([]byte(`{"field":"bar"}`), value)

	value.Field.If(func(s string) {
		fmt.Println(s)
	})
	// outputs: bar
}

See example_test.go for more examples.

Inspiration

Tool

Install

go get -u github.com/markphelps/optional/cmd/optional

Usage

Typically this process would be run using go generate, like this:

//go:generate optional -type=Foo

running this command:

optional -type=Foo

in the same directory will create the file optional_foo.go containing a definition of:

type OptionalFoo struct {
  ...
}

The default type is OptionalT or optionalT (depending on if the type is exported) and output file is optional_t.go. This can be overridden with the -output flag.

Library

Usage

package main

import (
	"fmt"

	"github.com/markphelps/optional"
)

func main() {
	s := optional.NewString("foo")

	value, err := s.Get()
	if err != nil {
		// handle error!
	} else {
		fmt.Println(value)
	}

	t := optional.String{}
	fmt.Println(t.OrElse("bar"))
}

See example_test.go and the documentation for more usage.

Test Coverage

As you can see test coverage is a bit lacking for the library. This is simply because testing generated code is not super easy. I'm currently working on improving test coverage for the generated types, but in the meantime checkout string_test.go and int_test.go for examples.

Also checkout:

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Golden Files

If changing the API you may need to update the golden files for your tests to pass by running:

go test ./cmd/optional/... -update.