how to structure go applications - paul bellamy - codemotion milan 2016

Post on 16-Apr-2017

213 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

TRANSCRIPT

How To Structure Go ApplicationsPaul Bellamy

MILAN 25-26 NOVEMBER 2016

HOW BIG IS YOUR APPLICATION?

GO DIFFERENCES

META

package privacy

type private struct{}

type Public struct {

PublicField string

privateField string

}

IS GO AN OBJECT-ORIENTED LANGUAGE?

Go FAQ

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

Go FAQ

CAR

FIAT

FIAT

CAR type Fiat struct {

Car

w Warranty

}

type Fiat struct {

Car

w Warranty

}

type Car struct{}

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

}

~/GOPATH

FRAMEWORKS

# 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

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

WHAT WEAVE TRIED

MVC

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

myapp/ App root

app/ App sources

controllers/ App controllers

models/ App domain models

views/ Templates

public/ Public assets

lib/ Other stuff ???

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

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

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

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

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

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

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

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

u := NewUUID()

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

myapp/ App root

app/ App sources

controllers/ App controllers

users_controller.go

models/ App domain models

views/ Templates

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

controllers.UsersController

GROUP-BY-MODULE

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

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

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

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

BEST PRACTICE

DOMAIN

DOMAIN

ADAPTERS

DOMAIN

ADAPTERS

BINARY

DOMAIN

ADAPTERS

BINARY

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)

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)

// Without src/ directory

import "github.com/paulbellamy/users"

t := users.Organization{}

// Without src/ directory

import "github.com/paulbellamy/users"

t := users.Organization{}

// With src/ directory

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

t := users.Organization{}

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)

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)

// 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)

}

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

}

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)

package emailer

type SMTP struct {

server string

}

package emailer

import "github.com/paulbellamy/users"

type SMTP struct {

server string

}

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”)

}

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)

package api

import "github.com/paulbellamy/users"

import "net/http"

type HTTP struct {

DB users.DB

Emailer users.Emailer

}

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”),

)

}

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”),

)

}

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”),

)

}

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”),

)

}

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)

# 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

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)

// cmd/users/main.go

package main

func main() {

// cmd/users/main.go

package main

import “net/http”

func main() {

http.ListenAndServe(“:8080”, a)

// 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)

// 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)

// 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)

// 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)

# Build our binary ready for deployment

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

# Run our app

$ ./users

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

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)

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)

MORE READING

MEDIUM.COM/@BENBJOHNSON

SOCIALS

TWITTER: @PYRHHO GITHUB: PAULBELLAMY

top related