Skip to content

Instantly share code, notes, and snippets.

@vaskoz
Last active January 22, 2024 10:54
Show Gist options
  • Select an option

  • Save vaskoz/10073335 to your computer and use it in GitHub Desktop.

Select an option

Save vaskoz/10073335 to your computer and use it in GitHub Desktop.
Golang Builder pattern
package main
import "strconv"
import "fmt"
type Color string
type Make string
type Model string
const (
BLUE Color = "blue"
RED = "red"
)
type Car interface {
Drive() string
Stop() string
}
type CarBuilder interface {
TopSpeed(int) CarBuilder
Paint(Color) CarBuilder
Build() Car
}
type carBuilder struct {
speedOption int
color Color
}
func (cb *carBuilder) TopSpeed(speed int) CarBuilder {
cb.speedOption = speed
return cb
}
func (cb *carBuilder) Paint(color Color) CarBuilder {
cb.color = color
return cb
}
func (cb *carBuilder) Build() Car {
return &car{
topSpeed: cb.speedOption,
color: cb.color,
}
}
func New() CarBuilder {
return &carBuilder{}
}
type car struct {
topSpeed int
color Color
}
func (c *car) Drive() string {
return "Driving at speed: " + strconv.Itoa(c.topSpeed)
}
func (c *car) Stop() string {
return "Stopping a " + string(c.color) + " car"
}
func main() {
builder := New()
car := builder.TopSpeed(50).Paint(BLUE).Build()
fmt.Println(car.Drive())
fmt.Println(car.Stop())
}
@kenenbek

kenenbek commented Nov 1, 2018

Copy link
Copy Markdown

Why do you have two similar carBuilder and car structs? Is this an unesseseary overhead?

@antonholmberg

Copy link
Copy Markdown

The Car struct is in effectively immutable where the builder is not. One of the major reasons of the builder pattern of to simplify construction of complex types while all having those types be immutable.

@abhaymaniyar

Copy link
Copy Markdown

This is one of the simplest code snippets to understand builder pattern.

@gocs

gocs commented Aug 18, 2019

Copy link
Copy Markdown

how do you format long builders?

gofmt doesn't allow oop-style multiline builder

@vaskoz

vaskoz commented Aug 18, 2019

Copy link
Copy Markdown
Author

@gocs since each CarBuilder method except Build returns a CarBuilder type, the most straightforward (yet verbose) approach that comes to mind for multiline builders would be re-assigning to the variable builder at the desired line length.

Example:

builder := New()
builder = builder.TopSpeed(50).Paint(BLUE)
builder = builder.TheOtherThing().AndSoOn()
// ... more builder lines here if necessary
car := builder.Build() // actually build a type Car

@syronz

syronz commented Nov 19, 2019

Copy link
Copy Markdown

Best small example for explain builder design pattern in Go, good job. By the way! what is the purpose of Make in line 7?

@leonj1

leonj1 commented Jan 19, 2020

Copy link
Copy Markdown

Make is extra, probably left over from some previous refactor. Its not needed in the code atm.

@mazznoer

mazznoer commented Aug 14, 2020

Copy link
Copy Markdown

@gocs @vaskoz

mycar := New().
    TopSpeed(97).
    Paint(BLUE).
    Build()

Playground

@marcelloh

Copy link
Copy Markdown

multilines are possible:

	builder := New().TopSpeed(50).
		Paint(BLUE)
	car := builder.Build()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment