Skip to content

Instantly share code, notes, and snippets.

@vaskoz
Last active January 22, 2024 10:54
Show Gist options
  • Save vaskoz/10073335 to your computer and use it in GitHub Desktop.
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
Copy link

kenenbek commented Nov 1, 2018

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

@antonholmberg
Copy link

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

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

@gocs
Copy link

gocs commented Aug 18, 2019

how do you format long builders?

gofmt doesn't allow oop-style multiline builder

@vaskoz
Copy link
Author

vaskoz commented Aug 18, 2019

@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
Copy link

syronz commented Nov 19, 2019

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
Copy link

leonj1 commented Jan 19, 2020

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

@mazznoer
Copy link

mazznoer commented Aug 14, 2020

@gocs @vaskoz

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

Playground

@marcelloh
Copy link

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