Go from a PHP Perspective
and some other languages *cough* ruby *cough* too…but MOSTLY PHP
Go (or Golang) from Google
From golang.org
“Go is an open source
programming language
that makes it easy to build
simple, reliable, and
efficient software.”
Valiant attempt to balance
• Productivity
• Workflow
• Growth
• Portability
• Efficiency
• Concurrency
SURELY YOU’RE NOT SERIOUS…
Another server side language?
Can Go bring balance to the force?
IT IS A GREAT TOOL IN THE BOX
But it’s still not the answer to life, the universe and everything
Let’s talk PHP
• A few months back I gave a presentation
called:
What’s the “right” PHP framework?
• With the shocking conclusion that there isn’t
one
– It was very “meta” as the kids say
PHP gives 90% of needs
• Frameworks largely just arrange them
– While locking you into them
• The most successful PHP ecosystem is one
driven by Composer
– Lot’s of great parts
– Assemble them to your needs
– Skip the frameworks completely
My solution was going to be…
• Routes defined in PHP
– For development
– But generated as a file for nginx in production
– Framework routing is insanely expensive
• PHP is stupid fast when it’s lightweight
• Route direct to a PHP file
– Include only what you need for that file
– Share templates with straight PHP
• Because APC will hold that in RAM
• Use the power of the PostgreSQL
• Let PHP be the only real upgrade path
Random stats
Java takes the top 8 spots before
= 914,749 to 731,583
Go appears
= 348,555
Then more Java, jRuby, Go and Java
= 344,032 to 245,709
Before Node.js
= 228,887
Until we get to PHP at
= 180,147
Impact of frameworks
Understand how far things fall when
frameworks are added to the stack
Leaner is better with dynamics
More than raw requests
When requests have a database
involved things change
…a lot
Needed to learn Go for work
• Frameworks largely rejected (exist though)
• Code as interchangeable parts
– There are about 10 different URL routers
• Range from features to speed…
depending on your needs
• Even the frameworks are mostly
– “bring your own ORM…if you want”
So I started looking at trade offs
There’s a lot of trade offs with ALMOST
• Serves static files ALMOST as fast as nginx
– But better than just about everything else
• Composite objects ALMOST as good as Ruby
– But better than just about everything else
• Performance and garbage collection ALMOST as good as Java (portability
too)
– But better than just about everything else
• Concurrency model ALMOST as good as Erlang
– But better than just about everything else
• Save refresh workflow from a statically typed language ALMOST as
efficient as PHP
– But better than just about everything else
Other perks
• Default, programmatically enforced code style
– gofmt
• Compiler won’t allow includes/imports that aren’t used
– Avoids bloat
• Won’t even allow declaring VARIABLES that aren’t used
– Guardian of your RAM
• Other things to save your team from arguments
– Testing built in, standardized
– Templates built in, standardized
– HTTP and other protocol servers, built in, standardized
– Documentation built in, standardized
– Sort of a convention over configuration approach to standard
libraries
So…compared to my solution
PHP + nginx routing/static Go for static/routing/logic
• Same result, one binary
• Zero server config
• Assemble parts as needed
SO YOU’RE SAYING WE SHOULD
USE GO FOR EVERYTHING!?!
Wait…
NO
It’s not all gophers and rainbows
For “code heavy” projects
• Great performance
• Excellent for development
teams
• Code structure works great
for iterative development
• Concurrency, computation,
API, Services, encapsulation,
sharing code between
projects, portable scripts for
agents running reliably on
client machines
For “websites”
• Lot’s of assembly required
• HTML templates are tedious
– Rewriting lots of loading,
caching code
– Breaking large templates into
pieces is an exercise in pain
• CSS/JS minify/versioning
solutions are fairly clunky
• Better for refinement than
prototype or MVP dev
“Fortunes” Benchmark
Most closely mirrors read-heavy web requests
And PHP…well…dominates
Or at least it did last year…
Unofficial, preliminary, unpublished, disclaimer heavy Round 10 benchmarks
Where does Go “fit” for a
PHP dev?
• Services / APIs / JSON
• SPA Backend
• Background jobs
• Queue workers
• Portability
• Client installed agent code
• High concurrency workload
• Server level code
– Drop uploads after seeing
bad headers
• Long polling / websockets
Basically, Go is good at the things that
PHP is really bad at without the
development time requirement of
doing it in Java.
PHP is really good at the things that Go
is really bad at, efficiently developing
complete web sites
LET’S LOOK AT SOME GO EXAMPLES
It’s about dang time
* Most of the examples come directly from the free golang-book.com
Compile Time
This 1 minute video explains it best
https://youtu.be/wwoWei-GAPo
Data Types
• uint = uint8 (byte), uint16, uint32, uint64
• int = int8, int16, int32 (rune), int64
• float32, float64
• complex64, complex128 (for imaginaries)
• string (byte[])
• Use := to infer type automatically
– x := “some cool text”
– var x string = “some cool text”
Array, Map, Interface
• Array = Numerically indexed set of Type
• Map = Key of Type and Value of Type
private / Public
Starts with capital letter = Public
Starts with lower case letter = private
Yes. Really.
Functions
func methodName(argument type) returnType {
}
// From the Go doc’s template tutorial
func loadPage(title string) *Page {
filename := title + ".txt"
body, _ := ioutil.ReadFile(filename)
return &Page{Title: title, Body: body}
}
Structs
type Circle struct {
x float64
y float64
r float64
}
// OR
type Circle struct {
x, y, r float64
}
var c Circle
// OR
c := new(Circle)
// OR with values
c := Circle{x: 0, y: 0,
r: 5}
// OR by definition order
c := Circle{0, 0, 5}
Compositional Object
type Circle struct {
x, y, r float64
} //  Look…a closing bracket
func (c *Circle) area() float64 {
return math.Pi * c.r*c.r
}
• (c *Circle) means Circles can call this function.
• Meaning object data and methods are SEPARATE
• Data in the struct, methods on the type
• So you can keep adding methods as your application requires
without inheriting, extending, and reworking the entire
inheritance chain
• Similar to object Includes and Monkey Patching in Rails
– One of the strengths of the language for productivity
Interfaces
• Java / most Object Oriented languages
– Object defined to implement an interface
• Go
– Object just needs to match an interface
– Solves a big pain point of OO development
– Create interfaces for existing objects
• Without modifying or extending the objects
Interface Example
type Circle struct {
x, y, r float64
}
func (c *Circle) area() float64 {
return math.Pi * c.r*c.r
}
type Rectangle struct {
x1, y1, x2, y2 float64
}
func (r *Rectangle) area() float64 {
l := distance(r.x1, r.y1, r.x1, r.y2)
w := distance(r.x1, r.y1, r.x2, r.y1)
return l * w
}
// Any type with an area() float64 method is a Shape
type Shape interface {
area() float64
}
Interface Functions
type Shape interface {
area() float64
}
func totalArea(shapes ...Shape) float64 {
var area float64
for _, s := range shapes {
area += s.area()
}
return area
}
fmt.Println(totalArea(&c, &r))
Interfaces as Fields
type MultiShape struct {
shapes []Shape
}
// This actually makes MultiShape into a Shape
func (m *MultiShape) area() float64 {
var area float64
for _, s := range m.shapes {
area += s.area()
}
return area
}
Defer / Panic / Recover
func readFile(filename string) string {
f, _ := os.Open(filename)
defer f.Close() // Will always run before end
if filename == “SOME CONDITION” {
return f.getDataSpecialWay
} else {
return f.getDataNormalWay
}
} // Exception handling
defer func() {
str := recover()
fmt.Println(str)
}()
panic("PANIC”)
Goroutines
go methodName(argument)
Mo Concurrency Mo Problems
• Concurrent / threaded operations fight for
variables
– Mutex locks
– Halt threads and wait
• Go uses channels to avoid this
Channels
func pinger(c chan string) {
for i := 0; ; i++ {
c <- "ping"
}
}
func ponger(c chan string) {
for i := 0; ; i++ {
c <- "pong"
}
}
func printer(c chan string) {
for {
msg := <- c
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string = make(chan string)
go pinger(c)
go ponger(c)
go printer(c)
}
Send a message
c <- “ping”
Receive a message
msg := <- c
OR
fmt.Println(<-c)
Pinger and Ponger won’t send until
something is waiting to receive
- Unless it’s a buffered channel
- Only waits when buffer is full
Printer will wait to receive until
something sends it a message
More on Channels
// Send only
func pinger(c chan<- string)
// Receive only
func printer(c <-chan string)
// Listen to multiple
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
case <- time.After(time.Second):
fmt.Println("timeout")
default:
fmt.Println("nothing ready")
}
Define channel direction
- Send only
- Receive only
Listen to multiple with select/case
- Whichever is ready first
- OR random
- OR set a timeout
- OR default if neither are ready
Fake Real World Example
type Job interface {
process()
complete()
failure()
}
func redisListener(c chan<- Job) {
c <- RedisJob()
}
func postrgresListener(c chan<- Job) {
c <- PostgresJob()
}
func awsSqsListener(c chan<- Job) {
c <- SqsJob()
}
func jobRunner(c <-chan Job) {
job := <- c
go job.process()
}
func main() {
// channel of Jobs with a buffer of 50
var c chan Job = make(chan Job, 50)
go redisListener(c)
go postrgresListener(c)
go awsSqsListener(c)
go jobRunner(c)
}
Multi-Queue Worker
- This is purely for insanity sake
- Create infinite job go routines
- Listen on 1 connection per queue
- Use an interface to define
common execution needs
Example could continue by
- Create a result channel per queue
- Use a single connection per to
report ALL job results in their own
way
TCP Servers and Routing
package main
import ("net/http" ; "io")
func hello(res http.ResponseWriter, req *http.Request) {
res.Header().Set(
"Content-Type",
"text/html",
)
io.WriteString(
res,
`<doctype html><html>
<head><title>Hello World</title></head>
<body>Hello World!</body>
</html>`,
)
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":9000", nil)
}
Gorilla Mux Router
func main() {
r := mux.NewRouter()
r.HandleFunc("/", HomeHandler)
r.HandleFunc("/products", ProductsHandler)
r.HandleFunc("/articles", ArticlesHandler)
r.HandleFunc("/products/{key}", ProductHandler)
r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
// You could use multiple routers too
http.Handle("/", r)
}
Dependency Management
go get github.com/myname/mypackage
• Copies it locally
• Bundles it with your deployed binary
• Sits right next to your local packages
• Single “src” directory with all packages
• Makes code sharing between multiple packages
very simple
• Never depend on “remote library host” being
down to deploy again
Gopher It!
References / Credits
• Go
– http://golang.org/
• Golang Book
– http://www.golang-book.com/
• Gorilla Web Toolkit
– http://www.gorillatoolkit.org/
• Techempower Benchmarks
– Official Round 9
• http://www.techempower.com/benchmarks/#section=data-r9
– Preview Round 10
• http://www.techempower.com/benchmarks/previews/round10/
*Hulkbuster written in Go
Additional Resources
Who’s using Go?
• Sendgrid
– Convice Your Company
– Intro and Love
• IronMQ
– From 30 Servers to 2
– Go after 2 Years in Prod
• Heroku
– Go at Heroku
• Digital Ocean
– Super Fast Console. Thanks Go!
• Others
– Dropbox, StatHat, Hailo,
Soundcloud, TimeHop
Other good reading
• Concurrency is not Parallelism
• Scaling VividCortex
• Stability at Timehop
• Simplicity and Maintenance
• Worker Queues in Go
• A RESTful Microframework
• Monte Carlo Benchmarks
• Taking Cloud Dev by Storm
• Structuring Applications in Go
• Go by Example
• Let’s Learn Go!
• Going Go – Playground
• GopherCasts
Thanks to James, Josh and ACS Technologies

Go from a PHP Perspective

  • 1.
    Go from aPHP Perspective and some other languages *cough* ruby *cough* too…but MOSTLY PHP
  • 2.
    Go (or Golang)from Google From golang.org “Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.” Valiant attempt to balance • Productivity • Workflow • Growth • Portability • Efficiency • Concurrency
  • 3.
    SURELY YOU’RE NOTSERIOUS… Another server side language?
  • 5.
    Can Go bringbalance to the force?
  • 6.
    IT IS AGREAT TOOL IN THE BOX But it’s still not the answer to life, the universe and everything
  • 7.
    Let’s talk PHP •A few months back I gave a presentation called: What’s the “right” PHP framework? • With the shocking conclusion that there isn’t one – It was very “meta” as the kids say
  • 8.
    PHP gives 90%of needs • Frameworks largely just arrange them – While locking you into them • The most successful PHP ecosystem is one driven by Composer – Lot’s of great parts – Assemble them to your needs – Skip the frameworks completely
  • 9.
    My solution wasgoing to be… • Routes defined in PHP – For development – But generated as a file for nginx in production – Framework routing is insanely expensive • PHP is stupid fast when it’s lightweight • Route direct to a PHP file – Include only what you need for that file – Share templates with straight PHP • Because APC will hold that in RAM • Use the power of the PostgreSQL • Let PHP be the only real upgrade path
  • 10.
    Random stats Java takesthe top 8 spots before = 914,749 to 731,583 Go appears = 348,555 Then more Java, jRuby, Go and Java = 344,032 to 245,709 Before Node.js = 228,887 Until we get to PHP at = 180,147
  • 11.
    Impact of frameworks Understandhow far things fall when frameworks are added to the stack Leaner is better with dynamics
  • 12.
    More than rawrequests When requests have a database involved things change …a lot
  • 13.
    Needed to learnGo for work • Frameworks largely rejected (exist though) • Code as interchangeable parts – There are about 10 different URL routers • Range from features to speed… depending on your needs • Even the frameworks are mostly – “bring your own ORM…if you want”
  • 14.
    So I startedlooking at trade offs There’s a lot of trade offs with ALMOST • Serves static files ALMOST as fast as nginx – But better than just about everything else • Composite objects ALMOST as good as Ruby – But better than just about everything else • Performance and garbage collection ALMOST as good as Java (portability too) – But better than just about everything else • Concurrency model ALMOST as good as Erlang – But better than just about everything else • Save refresh workflow from a statically typed language ALMOST as efficient as PHP – But better than just about everything else
  • 15.
    Other perks • Default,programmatically enforced code style – gofmt • Compiler won’t allow includes/imports that aren’t used – Avoids bloat • Won’t even allow declaring VARIABLES that aren’t used – Guardian of your RAM • Other things to save your team from arguments – Testing built in, standardized – Templates built in, standardized – HTTP and other protocol servers, built in, standardized – Documentation built in, standardized – Sort of a convention over configuration approach to standard libraries
  • 16.
    So…compared to mysolution PHP + nginx routing/static Go for static/routing/logic • Same result, one binary • Zero server config • Assemble parts as needed
  • 17.
    SO YOU’RE SAYINGWE SHOULD USE GO FOR EVERYTHING!?! Wait…
  • 18.
  • 19.
    It’s not allgophers and rainbows For “code heavy” projects • Great performance • Excellent for development teams • Code structure works great for iterative development • Concurrency, computation, API, Services, encapsulation, sharing code between projects, portable scripts for agents running reliably on client machines For “websites” • Lot’s of assembly required • HTML templates are tedious – Rewriting lots of loading, caching code – Breaking large templates into pieces is an exercise in pain • CSS/JS minify/versioning solutions are fairly clunky • Better for refinement than prototype or MVP dev
  • 20.
    “Fortunes” Benchmark Most closelymirrors read-heavy web requests And PHP…well…dominates
  • 21.
    Or at leastit did last year… Unofficial, preliminary, unpublished, disclaimer heavy Round 10 benchmarks
  • 22.
    Where does Go“fit” for a PHP dev? • Services / APIs / JSON • SPA Backend • Background jobs • Queue workers • Portability • Client installed agent code • High concurrency workload • Server level code – Drop uploads after seeing bad headers • Long polling / websockets Basically, Go is good at the things that PHP is really bad at without the development time requirement of doing it in Java. PHP is really good at the things that Go is really bad at, efficiently developing complete web sites
  • 23.
    LET’S LOOK ATSOME GO EXAMPLES It’s about dang time * Most of the examples come directly from the free golang-book.com
  • 24.
    Compile Time This 1minute video explains it best https://youtu.be/wwoWei-GAPo
  • 25.
    Data Types • uint= uint8 (byte), uint16, uint32, uint64 • int = int8, int16, int32 (rune), int64 • float32, float64 • complex64, complex128 (for imaginaries) • string (byte[]) • Use := to infer type automatically – x := “some cool text” – var x string = “some cool text”
  • 26.
    Array, Map, Interface •Array = Numerically indexed set of Type • Map = Key of Type and Value of Type
  • 27.
    private / Public Startswith capital letter = Public Starts with lower case letter = private Yes. Really.
  • 28.
    Functions func methodName(argument type)returnType { } // From the Go doc’s template tutorial func loadPage(title string) *Page { filename := title + ".txt" body, _ := ioutil.ReadFile(filename) return &Page{Title: title, Body: body} }
  • 29.
    Structs type Circle struct{ x float64 y float64 r float64 } // OR type Circle struct { x, y, r float64 } var c Circle // OR c := new(Circle) // OR with values c := Circle{x: 0, y: 0, r: 5} // OR by definition order c := Circle{0, 0, 5}
  • 30.
    Compositional Object type Circlestruct { x, y, r float64 } //  Look…a closing bracket func (c *Circle) area() float64 { return math.Pi * c.r*c.r } • (c *Circle) means Circles can call this function. • Meaning object data and methods are SEPARATE • Data in the struct, methods on the type • So you can keep adding methods as your application requires without inheriting, extending, and reworking the entire inheritance chain • Similar to object Includes and Monkey Patching in Rails – One of the strengths of the language for productivity
  • 31.
    Interfaces • Java /most Object Oriented languages – Object defined to implement an interface • Go – Object just needs to match an interface – Solves a big pain point of OO development – Create interfaces for existing objects • Without modifying or extending the objects
  • 32.
    Interface Example type Circlestruct { x, y, r float64 } func (c *Circle) area() float64 { return math.Pi * c.r*c.r } type Rectangle struct { x1, y1, x2, y2 float64 } func (r *Rectangle) area() float64 { l := distance(r.x1, r.y1, r.x1, r.y2) w := distance(r.x1, r.y1, r.x2, r.y1) return l * w } // Any type with an area() float64 method is a Shape type Shape interface { area() float64 }
  • 33.
    Interface Functions type Shapeinterface { area() float64 } func totalArea(shapes ...Shape) float64 { var area float64 for _, s := range shapes { area += s.area() } return area } fmt.Println(totalArea(&c, &r))
  • 34.
    Interfaces as Fields typeMultiShape struct { shapes []Shape } // This actually makes MultiShape into a Shape func (m *MultiShape) area() float64 { var area float64 for _, s := range m.shapes { area += s.area() } return area }
  • 35.
    Defer / Panic/ Recover func readFile(filename string) string { f, _ := os.Open(filename) defer f.Close() // Will always run before end if filename == “SOME CONDITION” { return f.getDataSpecialWay } else { return f.getDataNormalWay } } // Exception handling defer func() { str := recover() fmt.Println(str) }() panic("PANIC”)
  • 36.
  • 37.
    Mo Concurrency MoProblems • Concurrent / threaded operations fight for variables – Mutex locks – Halt threads and wait • Go uses channels to avoid this
  • 38.
    Channels func pinger(c chanstring) { for i := 0; ; i++ { c <- "ping" } } func ponger(c chan string) { for i := 0; ; i++ { c <- "pong" } } func printer(c chan string) { for { msg := <- c fmt.Println(msg) time.Sleep(time.Second * 1) } } func main() { var c chan string = make(chan string) go pinger(c) go ponger(c) go printer(c) } Send a message c <- “ping” Receive a message msg := <- c OR fmt.Println(<-c) Pinger and Ponger won’t send until something is waiting to receive - Unless it’s a buffered channel - Only waits when buffer is full Printer will wait to receive until something sends it a message
  • 39.
    More on Channels //Send only func pinger(c chan<- string) // Receive only func printer(c <-chan string) // Listen to multiple select { case msg1 := <- c1: fmt.Println(msg1) case msg2 := <- c2: fmt.Println(msg2) case <- time.After(time.Second): fmt.Println("timeout") default: fmt.Println("nothing ready") } Define channel direction - Send only - Receive only Listen to multiple with select/case - Whichever is ready first - OR random - OR set a timeout - OR default if neither are ready
  • 40.
    Fake Real WorldExample type Job interface { process() complete() failure() } func redisListener(c chan<- Job) { c <- RedisJob() } func postrgresListener(c chan<- Job) { c <- PostgresJob() } func awsSqsListener(c chan<- Job) { c <- SqsJob() } func jobRunner(c <-chan Job) { job := <- c go job.process() } func main() { // channel of Jobs with a buffer of 50 var c chan Job = make(chan Job, 50) go redisListener(c) go postrgresListener(c) go awsSqsListener(c) go jobRunner(c) } Multi-Queue Worker - This is purely for insanity sake - Create infinite job go routines - Listen on 1 connection per queue - Use an interface to define common execution needs Example could continue by - Create a result channel per queue - Use a single connection per to report ALL job results in their own way
  • 41.
    TCP Servers andRouting package main import ("net/http" ; "io") func hello(res http.ResponseWriter, req *http.Request) { res.Header().Set( "Content-Type", "text/html", ) io.WriteString( res, `<doctype html><html> <head><title>Hello World</title></head> <body>Hello World!</body> </html>`, ) } func main() { http.HandleFunc("/hello", hello) http.ListenAndServe(":9000", nil) }
  • 42.
    Gorilla Mux Router funcmain() { r := mux.NewRouter() r.HandleFunc("/", HomeHandler) r.HandleFunc("/products", ProductsHandler) r.HandleFunc("/articles", ArticlesHandler) r.HandleFunc("/products/{key}", ProductHandler) r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) // You could use multiple routers too http.Handle("/", r) }
  • 43.
    Dependency Management go getgithub.com/myname/mypackage • Copies it locally • Bundles it with your deployed binary • Sits right next to your local packages • Single “src” directory with all packages • Makes code sharing between multiple packages very simple • Never depend on “remote library host” being down to deploy again
  • 44.
    Gopher It! References /Credits • Go – http://golang.org/ • Golang Book – http://www.golang-book.com/ • Gorilla Web Toolkit – http://www.gorillatoolkit.org/ • Techempower Benchmarks – Official Round 9 • http://www.techempower.com/benchmarks/#section=data-r9 – Preview Round 10 • http://www.techempower.com/benchmarks/previews/round10/ *Hulkbuster written in Go
  • 45.
    Additional Resources Who’s usingGo? • Sendgrid – Convice Your Company – Intro and Love • IronMQ – From 30 Servers to 2 – Go after 2 Years in Prod • Heroku – Go at Heroku • Digital Ocean – Super Fast Console. Thanks Go! • Others – Dropbox, StatHat, Hailo, Soundcloud, TimeHop Other good reading • Concurrency is not Parallelism • Scaling VividCortex • Stability at Timehop • Simplicity and Maintenance • Worker Queues in Go • A RESTful Microframework • Monte Carlo Benchmarks • Taking Cloud Dev by Storm • Structuring Applications in Go • Go by Example • Let’s Learn Go! • Going Go – Playground • GopherCasts Thanks to James, Josh and ACS Technologies