How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

79
How To Structure Go Applications Paul Bellamy MILAN 25-26 NOVEMBER 2016

Transcript of How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

Page 1: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

How To Structure Go ApplicationsPaul Bellamy

MILAN 25-26 NOVEMBER 2016

Page 2: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 3: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

HOW BIG IS YOUR APPLICATION?

Page 4: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

GO DIFFERENCES

Page 5: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

META

Page 6: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package privacy

type private struct{}

type Public struct {

PublicField string

privateField string

}

Page 7: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

IS GO AN OBJECT-ORIENTED LANGUAGE?

Go FAQ

Page 8: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

IS GO AN OBJECT-ORIENTED LANGUAGE? YES AND NO.

Go FAQ

Page 9: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

CAR

FIAT

Page 10: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

FIAT

CAR type Fiat struct {

Car

w Warranty

}

Page 11: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 12: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

type Fiat struct {

Car

w Warranty

}

type Car struct{}

func (c Car) MarshalJSON() ([]byte, error) {

}

Page 13: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 14: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 15: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

~/GOPATH

Page 16: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 17: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

FRAMEWORKS

Page 18: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 19: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

# Get 'revel' framework and command

$ go get github.com/revel/cmd/revel

# Create a new app

$ revel new github.com/paulbellamy/myapp

# Run revel application

$ revel run github.com/paulbellamy/myapp

Page 20: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

init.go Interceptor registration

models/ App domain models

routes/ Reverse routes (generated code)

views/ Templates

tests/ Test suites

conf/ Configuration files

app.conf Main configuration file

routes Routes definition

messages/ Message files

Page 21: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

WHAT WEAVE TRIED

Page 22: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

MVC

Page 23: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

Page 24: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

Page 25: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

Page 26: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

Page 27: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

Page 28: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

max_bytes_reader.go

Page 29: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

max_bytes_reader.go

time.go

Page 30: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

myapp.go App binary

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

max_bytes_reader.go

Page 31: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

myapp.go App binary

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

max_bytes_reader.go

Page 32: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

import . "github.com/myaccount/myapp/lib"

u := NewUUID()

Page 33: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

myapp.go App binary

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

generate_certificates_tool.go

uuid.go

conn_with_read_timeout.go

max_bytes_reader.go

Page 34: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

myapp/ App root

app/ App sources

controllers/ App controllers

users_controller.go

models/ App domain models

views/ Templates

Page 35: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

import "github.com/myaccount/myapp/app/controllers"

controllers.UsersController

Page 36: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

GROUP-BY-MODULE

Page 37: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Page 38: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

scope/ App root

app/ Runs “in the cloud”

probe/ Runs in the users’s cluster

common/ Shared code between app and probe

xfer/ Defines the communication protocol

Page 39: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

scope/ App root

app/ Runs “in the cloud”

probe/ Runs in the users’s cluster

common/ Shared code between app and probe

xfer/ Defines the communication protocol

Page 40: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

scope/ App root

app/ Runs “in the cloud”

probe/ Runs in the users’s cluster

common/ Shared code between app and probe

xfer/ Defines the communication protocol

Page 41: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

scope/ App root

app/ Runs “in the cloud”

probe/ Runs in the users’s cluster

common/ Shared code between app and probe

xfer/ Defines the communication protocol

Page 42: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

BEST PRACTICE

Page 43: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

DOMAIN

Page 44: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

DOMAIN

ADAPTERS

Page 45: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

DOMAIN

ADAPTERS

BINARY

Page 46: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

DOMAIN

ADAPTERS

BINARY

Page 47: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 48: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

README.md

Dockerfile

src/ Top-level container for go files

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 49: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// Without src/ directory

import "github.com/paulbellamy/users"

t := users.Organization{}

Page 50: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// Without src/ directory

import "github.com/paulbellamy/users"

t := users.Organization{}

// With src/ directory

import users “github.com/paulbellamy/users/src"

t := users.Organization{}

Page 51: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 52: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 53: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// add_user_to_organization.go

package users

func AddUserToOrg(

db DB, email Emailer, userID, orgID string,

) error {

u, err := db.FindUser(userID) // make sure they exist

o, err := db.FindOrg(orgID)

db.AddUserToOrg(userID, orgID)

email.SendWelcomeEmail(u, o)

}

Page 54: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package users

type DB interface {

FindUser(userID string) (User, error)

FindOrg(orgID string) (Organization, error)

AddUserToOrg(userID, orgID string) error

}

type Emailer interface {

SendWelcomeEmail(User, Organization) error

}

Page 55: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

smtp.go SMTP email provider

oauth/ OAuth Providers

db/ App database(s)

Page 56: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package emailer

type SMTP struct {

server string

}

Page 57: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package emailer

import "github.com/paulbellamy/users"

type SMTP struct {

server string

}

Page 58: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package emailer

import "github.com/paulbellamy/users"

type SMTP struct {

server string

}

func (s SMTP) SendWelcomeEmail(

u users.User, o users.Organization,

) error {

return errors.New(“TODO”)

}

Page 59: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

http.go

emailer/ Email providers

smtp.go SMTP email provider

oauth/ OAuth Providers

db/ App database(s)

Page 60: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

package api

import "github.com/paulbellamy/users"

import "net/http"

type HTTP struct {

DB users.DB

Emailer users.Emailer

}

Page 61: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

func (h HTTP) ServeHTTP(

w http.ResponseWriter, r *http.Request,

) {

err := users.AddUserToOrganization(

h.DB, h.Emailer,

r.FormValue(“user_id”), r.FormValue(“org_id”),

)

}

Page 62: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

func (h HTTP) ServeHTTP(

w http.ResponseWriter, r *http.Request,

) {

err := users.AddUserToOrganization(

h.DB, h.Emailer,

r.FormValue(“user_id”), r.FormValue(“org_id”),

)

}

Page 63: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

func (h HTTP) ServeHTTP(

w http.ResponseWriter, r *http.Request,

) {

err := users.AddUserToOrganization(

h.DB, h.Emailer,

r.FormValue(“user_id”), r.FormValue(“org_id”),

)

}

Page 64: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

func (h HTTP) ServeHTTP(

w http.ResponseWriter, r *http.Request,

) {

err := users.AddUserToOrganization(

h.DB, h.Emailer,

r.FormValue(“user_id”), r.FormValue(“org_id”),

)

}

Page 65: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

users/

main.go

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 66: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

# Get 'revel' framework and command

$ go get github.com/revel/cmd/revel

# Create a new app

$ revel new github.com/paulbellamy/myapp

# Run revel application

$ revel run github.com/paulbellamy/myapp

Page 67: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

users/

main.go

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 68: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

func main() {

Page 69: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

import “net/http”

func main() {

http.ListenAndServe(“:8080”, a)

Page 70: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

import “github.com/paulbellamy/users/api”

import “net/http”

func main() {

a := api.HTTP{Emailer: e, DB: d}

http.ListenAndServe(“:8080”, a)

Page 71: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

import “github.com/paulbellamy/users/emailer”

import “github.com/paulbellamy/users/api”

import “net/http”

func main() {

e := emailer.SMTP{server: “smtp://mailcatcher.local”}

a := api.HTTP{db: d, emailer: e}

http.ListenAndServe(“:8080”, a)

Page 72: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

import “github.com/paulbellamy/users/emailer”

import “github.com/paulbellamy/users/db”

import “github.com/paulbellamy/users/api”

import “net/http”

func main() {

e := emailer.SMTP{server: “smtp://mailcatcher.local”}

d := db.New(databaseURL)

a := api.HTTP{db: d, emailer: e}

http.ListenAndServe(“:8080”, a)

Page 73: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

// cmd/users/main.go

package main

import “github.com/paulbellamy/users/emailer”

import “github.com/paulbellamy/users/db”

import “github.com/paulbellamy/users/api”

import “net/http”

func main() {

e := emailer.SMTP{server: “smtp://mailcatcher.local”}

d := db.New(databaseURL)

a := api.HTTP{db: d, emailer: e}

http.ListenAndServe(“:8080”, a)

Page 74: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

# Build our binary ready for deployment

$ go build github.com/paulbellamy/users/cmd/users

# Run our app

$ ./users

Page 75: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

mocks/ Testing mocks

emailer.go Mock emailer

db.go Mock db

Page 76: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

users-server/ Server binary

users-client/ Client binary

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 77: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

users/ App root

add_user_to_organization.go

user.go

organization.go

errors.go

cmd/ App binaries

api/ HTTP API

emailer/ Email providers

oauth/ OAuth Providers

db/ App database(s)

Page 78: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

MORE READING

MEDIUM.COM/@BENBJOHNSON

Page 79: How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016

SOCIALS

TWITTER: @PYRHHO GITHUB: PAULBELLAMY