builder

package module
v0.0.0-...-47ae307 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2018 License: MIT Imports: 4 Imported by: 179

README

Builder - fluent immutable builders for Go

GoDoc Build Status

Builder was originally written for Squirrel, a fluent SQL generator. It is probably the best example of Builder in action.

Builder helps you write fluent DSLs for your libraries with method chaining:

resp := ReqBuilder.
    Url("http://golang.org").
    Header("User-Agent", "Builder").
    Get()

Builder uses immutable persistent data structures (these, specifically) so that each step in your method chain can be reused:

build := WordBuilder.AddLetters("Build")
builder := build.AddLetters("er")
building := build.AddLetters("ing")

Builder makes it easy to build structs using the builder pattern (surprise!):

import "github.com/lann/builder"

type Muppet struct {
    Name string
    Friends []string
}

type muppetBuilder builder.Builder

func (b muppetBuilder) Name(name string) muppetBuilder {
    return builder.Set(b, "Name", name).(muppetBuilder)
}

func (b muppetBuilder) AddFriend(friend string) muppetBuilder {
    return builder.Append(b, "Friends", friend).(muppetBuilder)
}

func (b muppetBuilder) Build() Muppet {
    return builder.GetStruct(b).(Muppet)
}

var MuppetBuilder = builder.Register(muppetBuilder{}, Muppet{}).(muppetBuilder)
MuppetBuilder.
    Name("Beaker").
    AddFriend("Dr. Honeydew").
    Build()

=> Muppet{Name:"Beaker", Friends:[]string{"Dr. Honeydew"}}

License

Builder is released under the MIT License.

Documentation

Overview

Package builder provides a method for writing fluent immutable builders.

Example (Basic)
package main

import (
	"fmt"
	"github.com/lann/builder"
)

// Simple math expression allowing multiple adds/subtracts and a single
// (optional) multiply.
type simpleExpr struct {
	Multiplier int
	Adds       []int
	Subtracts  []int
}

func (e simpleExpr) Equals() (total int) {
	for _, i := range e.Adds {
		total += i
	}
	for _, i := range e.Subtracts {
		total -= i
	}
	if e.Multiplier != 0 {
		total *= e.Multiplier
	}
	return
}

// Start builder definition

type simpleExprBuilder builder.Builder

func (b simpleExprBuilder) Multiplier(i int) simpleExprBuilder {
	return builder.Set(b, "Multiplier", i).(simpleExprBuilder)
}

func (b simpleExprBuilder) Add(i int) simpleExprBuilder {
	return builder.Append(b, "Adds", i).(simpleExprBuilder)
}

func (b simpleExprBuilder) Subtract(i int) simpleExprBuilder {
	return builder.Append(b, "Subtracts", i).(simpleExprBuilder)
}

func (b simpleExprBuilder) Equals() int {
	return builder.GetStruct(b).(simpleExpr).Equals()
}

// SimpleExprBuilder is an empty builder
var SimpleExprBuilder = builder.Register(simpleExprBuilder{}, simpleExpr{}).(simpleExprBuilder)

// End builder definition

func main() {
	b := SimpleExprBuilder.Add(10).Subtract(3)

	// Intermediate values can be reused
	b2 := b.Multiplier(2)
	b3 := b.Multiplier(3)

	fmt.Println(b.Equals(), b2.Equals(), b3.Equals())

}
Output:

7 14 21

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	EmptyBuilder = Builder{ps.NewMap()}
)

Functions

func Append

func Append(builder interface{}, name string, vs ...interface{}) interface{}

Append returns a copy of the given builder with new value(s) appended to the named list. If the value was previously unset or set with Set (even to a e.g. slice values), the new value(s) will be appended to an empty list.

func Delete

func Delete(builder interface{}, name string) interface{}

Delete returns a copy of the given builder with the given named value unset.

func Extend

func Extend(builder interface{}, name string, vs interface{}) interface{}

Extend behaves like Append, except it takes a single slice or array value which will be concatenated to the named list.

Unlike a variadic call to Append - which requires a []interface{} value - Extend accepts slices or arrays of any type.

Extend will panic if the given value is not a slice, array, or nil.

func Get

func Get(builder interface{}, name string) (interface{}, bool)

Get retrieves a single named value from the given builder. If the value has not been set, it returns (nil, false). Otherwise, it will return (value, true).

If the named value was last set with Append or Extend, the returned value will be a slice. If the given Builder has been registered with Register or RegisterType and the given name is an exported field of the registered struct, the returned slice will have the same type as that field. Otherwise the slice will have type []interface{}. It will panic if the given name is a registered struct's exported field and the value set on the Builder is not assignable to the field.

func GetMap

func GetMap(builder interface{}) map[string]interface{}

GetMap returns a map[string]interface{} of the values set in the given builder.

See notes on Get regarding returned slices.

func GetStruct

func GetStruct(builder interface{}) interface{}

GetStruct builds a new struct from the given registered builder. It will return nil if the given builder's type has not been registered with Register or RegisterValue.

All values set on the builder with names that start with an uppercase letter (i.e. which would be exported if they were identifiers) are assigned to the corresponding exported fields of the struct.

GetStruct will panic if any of these "exported" values are not assignable to their corresponding struct fields.

func GetStructLike

func GetStructLike(builder interface{}, strct interface{}) interface{}

GetStructLike builds a new struct from the given builder with the same type as the given struct.

All values set on the builder with names that start with an uppercase letter (i.e. which would be exported if they were identifiers) are assigned to the corresponding exported fields of the struct.

ScanStruct will panic if any of these "exported" values are not assignable to their corresponding struct fields.

func Register

func Register(builderProto, structProto interface{}) interface{}

Register wraps RegisterType, taking instances instead of Types.

Returns an empty instance of the registered builder type which can be used as the initial value for builder expressions. See example.

func RegisterType

func RegisterType(builderType reflect.Type, structType reflect.Type) *reflect.Value

RegisterType maps the given builderType to a structType. This mapping affects the type of slices returned by Get and is required for GetStruct to work.

Returns a Value containing an empty instance of the registered builderType.

RegisterType will panic if builderType's underlying type is not Builder or if structType's Kind is not Struct.

func Set

func Set(builder interface{}, name string, v interface{}) interface{}

Set returns a copy of the given builder with a new value set for the given name.

Set (and all other functions taking a builder in this package) will panic if the given builder's underlying type is not Builder.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder stores a set of named values.

New types can be declared with underlying type Builder and used with the functions in this package. See example.

Instances of Builder should be treated as immutable. It is up to the implementor to ensure mutable values set on a Builder are not mutated while the Builder is in use.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL