Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go for PHP Developers

Go for PHP Developers

A short intro to Golang for PHP devs

Terrence Ryan

October 25, 2017
Tweet

More Decks by Terrence Ryan

Other Decks in Technology

Transcript

  1. ‹#›
    @tpryan
    Terry Ryan
    Developer Advocate
    Go for PHP
    Developers

    View Slide

  2. ‹#›
    @tpryan
    Who are you?

    View Slide

  3. ‹#›
    @tpryan
    Go is just
    another tool

    View Slide

  4. ‹#›
    @tpryan
    01 Introduction
    What is Go?

    View Slide

  5. ‹#›
    @tpryan
    • Developed at Google
    • Open Source
    • Compiled
    Go is a programming language

    View Slide

  6. ‹#›
    @tpryan
    Wait! What the hell is that thing?


    View Slide

  7. ‹#›
    @tpryan
    The Gopher
    https://blog.golang.org/gopher

    View Slide

  8. ‹#›
    @tpryan
    • Compiled
    • Garbage collected
    • Strongly typed
    • Statically typed
    • C syntax
    • Simple
    • Built to use multiple processors
    • Tools design for remote packages
    • Testing built in
    Language focused on Software engineering
    Go features

    View Slide

  9. ‹#›
    @tpryan
    02 Simple CLI
    Let’s see some code already.

    View Slide

  10. ‹#›
    @tpryan
    package main
    func main() {
    println("Hello World")
    }
    Hello World
    main.go

    View Slide

  11. ‹#›
    @tpryan
    package main
    import "fmt"
    func main() {
    var s string = "Hello World"
    fmt.Printf("%s\n", s)
    }
    Hello World
    main.go

    View Slide

  12. ‹#›
    @tpryan
    go run main.go
    Hello World

    View Slide

  13. ‹#›
    @tpryan
    var s string = "Hello World”
    s := "Hello World"
    Type inference

    View Slide

  14. ‹#›
    @tpryan
    package main
    import "fmt"
    func main() {
    s := "Hello World"
    fmt.Printf("%s\n", s)
    }
    Hello World
    main.go

    View Slide

  15. ‹#›
    @tpryan
    Types
    • bool
    • string
    • int int8 int16 int32 int64
    • uint uint8 uint16 uint32 uinint 64 uintptr
    • byte (uint8)
    • rune (int32)
    • float32 float 64
    • complex64 complex128
    • array, slice, map

    View Slide

  16. ‹#›
    @tpryan
    Go Arrays vs Slices
    • Array - finite, ordered collection of elements
    - users := [4]string
    • Slice - points to an array, allows for more dynamic
    operations
    - users :=[]strings
    abc abc abc abc
    abc abc abc abc abc

    View Slide

  17. ‹#›
    @tpryan
    greetings := [5]string{“你好世界",
    "Hello wereld",
    "Hello world",
    "Bonjour monde",
    "Hallo Welt"}
    Array

    View Slide

  18. ‹#›
    @tpryan
    greetings := []string{“你好世界",
    "Hello wereld",
    "Hello world",
    "Bonjour monde",
    "Hallo Welt”}
    greetings = greetings.append("γειά σου κόσμος")
    Slice

    View Slide

  19. ‹#›
    @tpryan
    If you aren’t sure,
    just use a slice.

    View Slide

  20. ‹#›
    @tpryan
    greetings := []string{"你好世界",
    "Hello wereld",
    "Hello world",
    "Bonjour monde",
    "Hallo Welt",
    "γειά σου κόσμος",
    "Ciao mondo",
    "こんにちは世界",
    "ৈࠁࣁਃ ࣁ҅",
    "Olá mundo",
    "Здравствулте мир",
    "Hola mundo"}
    Hello World

    View Slide

  21. ‹#›
    @tpryan
    package main
    import (
    "fmt"
    "math/rand"
    "time"
    )
    func main() {
    g := []string{"你好世界", … }
    rand.Seed(time.Now().UnixNano())
    l := len(g)
    i := rand.Intn(l - 1)
    fmt.Printf("%s\n", greetings[i])
    }
    Hello World

    View Slide

  22. ‹#›
    @tpryan
    Input
    Give our code something to respond to

    View Slide

  23. ‹#›
    @tpryan
    go run main.go -lang 2

    Hello World

    View Slide

  24. ‹#›
    @tpryan
    package main
    import (
    "flag"
    "fmt"
    "log"
    "os"
    "strconv"
    )
    func main() {
    i := flag.Int("lang", 0, " a number between 0 and 11")
    flag.Parse()
    a := []string{"你好世界", … }
    fmt.Printf("%s\n", a[*i])
    }
    Hello World

    View Slide

  25. ‹#›
    @tpryan
    i := flag.Int("lang", 0, " a number between 0 and 11")
    flag.Parse()

    *i
    Flags

    View Slide

  26. ‹#›
    @tpryan
    Pointers
    • Pointer is a link to the variables address in memory
    • Allows us to pass by reference not by value
    • In dealing with then you will see
    • *
    • &

    View Slide

  27. ‹#›
    @tpryan
    p := Person{"Steve", 28} // p is Person
    p := &Person{"Steve", 28} // p is a reference to a Person
    PrintPerson(*p) // pass a Person
    PrintPerson(&p) // pass a reference to a Person
    func PrintPerson(p Person) // function ONLY takes a Person
    func PrintPerson(p *Person) // function ONLY takes a reference to a Person
    Examples of pointers
    From https://gist.github.com/josephspurrier/7686b139f29601c3b370

    View Slide

  28. ‹#›
    @tpryan
    if *i < 0 || *i >= len(g) {
    log.Fatalf("%d is not valid, please choose between 0 - %d", *i, len(g)-1)
    }
    Handle errors

    View Slide

  29. ‹#›
    @tpryan
    go run main.go -lang 2

    Hello World

    View Slide

  30. ‹#›
    @tpryan
    Finishing up the Program

    View Slide

  31. ‹#›
    @tpryan
    go run main.go -lang English

    Hello World

    View Slide

  32. ‹#›
    @tpryan
    greetings := map[string]string{
    "Chinese": "你好世界",
    "Dutch": "Hello wereld",
    "English": "Hello world",
    "French": "Bonjour monde",
    "German": "Hallo Welt",
    "Greek": "γειά σου κόσμος",
    "Italian": "Ciao mondo",
    "Japanese": "こんにちは世界",
    "Korean": "ৈࠁࣁਃ ࣁ҅",
    "Portuguese": "Olá mundo",
    "Russian": "Здравствулте мир",
    “Spanish": "Hola mundo",
    }
    Hello World

    View Slide

  33. ‹#›
    @tpryan
    newMap := map[keyType]valueType{}
    newMap := make(map[keyType]valueType)
    Maps

    View Slide

  34. ‹#›
    @tpryan
    func main() {
    l := flag.String("lang", "English", "a language in which to get greeting.")
    flag.Parse()
    g := map[string]string{"Chinese":"你好世界", … }
    if r, ok := g[*l]; ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    }
    Hello World
    Wait! What the hell is that thing?

    View Slide

  35. ‹#›
    @tpryan
    $greetings = [];
    $greetings[“Chinese"]="你好世界"; …
    if (!isset($argv[1])){
    $argv[1] = "English";
    }
    if (array_key_exists($argv[1], $greetings)){
    echo $greetings[$argv[1]]."\n";
    } else {
    die("The language you selected is not valid.\n");
    }
    Hello World

    View Slide

  36. ‹#›
    @tpryan
    func main() {
    l := flag.String("lang", "English", "a language in which to get greeting.")
    flag.Parse()
    g := map[string]string{"Chinese":"你好世界", … }
    if r, ok := g[*l]; ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    }
    Hello World

    View Slide

  37. ‹#›
    @tpryan
    if r, ok := g[*l]; ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    Hello World

    View Slide

  38. ‹#›
    @tpryan
    r, ok := g[*l]
    if ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    Hello World

    View Slide

  39. ‹#›
    @tpryan
    result, keyexists? := greeting[*language]
    if keyexists? {
    fmt.Printf("%s\n", result)
    } else {
    fmt.Printf("The language you selected is not valid.\n")}
    Hello World

    View Slide

  40. ‹#›
    @tpryan
    if result, keyexists? := greeting[*language]; keyexists? {
    fmt.Printf("%s\n", result)
    } else {
    fmt.Printf("The language you selected is not valid.\n”)
    }
    Hello World

    View Slide

  41. ‹#›
    @tpryan
    if r, ok := g[*l]; ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    Hello World

    View Slide

  42. ‹#›
    @tpryan
    func main() {
    l := flag.String("lang", "English", "a language in which to get greeting.")
    flag.Parse()
    g := map[string]string{"Chinese":"你好世界", … }
    if r, ok := g[*l]; ok {
    fmt.Printf("%s\n", r)
    } else {
    fmt.Printf("The language you selected is not valid.\n")
    }
    }
    Hello World

    View Slide

  43. ‹#›
    @tpryan
    Why are go variables
    so short?

    View Slide

  44. ‹#›
    @tpryan
    We hate you and we hate
    things that are good.
    - Creators of Go

    View Slide

  45. ‹#›
    @tpryan
    Variable names in Go should be short rather than long.
    This is especially true for local variables with limited scope.
    Prefer c to lineCount.
    Prefer i to sliceIndex.
    https://github.com/golang/go/wiki/CodeReviewComments#variable-names

    View Slide

  46. ‹#›
    @tpryan
    @tpryan
    PHP dog
    Go d
    Java PuppyWithASadFaceFactoryBean

    View Slide

  47. ‹#›
    @tpryan
    Variable Length
    • As short as can be while still being descriptive
    • The further away from which they are used, the longer they can be.
    • Local variable - r
    • Package public variable - rate

    View Slide

  48. ‹#›
    @tpryan
    Variable names Conventions
    i Index
    c count or context
    r,w reader, writer
    req, res request, response
    err error
    buf buffer
    f file
    ok assertion result

    View Slide

  49. ‹#›
    @tpryan
    03 Package
    Writing code to be shared

    View Slide

  50. ‹#›
    @tpryan
    package helloworld
    import "errors"
    var greetings = map[string]string{"Chinese": "你好世界", … }
    func Greet(language string) (string, error) {
    if r, ok := greetings[language]; ok {
    return r, nil
    } else {
    return "", errors.New("The language you selected is not valid.")
    }
    }
    Hello World

    View Slide

  51. ‹#›
    @tpryan
    • Local (unexported)
    - First letter is lowercase
    • Global (exported)
    - First letter is Uppercase
    Access (Public/Private)

    View Slide

  52. ‹#›
    @tpryan
    package helloworld
    import "errors"
    var greetings = map[string]string{"Chinese": "你好世界", … }
    func Greet(language string) (string, error) {…}
    func helper(language string) (int) {…}
    Hello World

    View Slide

  53. ‹#›
    @tpryan
    Error Handling

    View Slide

  54. ‹#›
    @tpryan
    func Greet(language string) (string, error) {
    if r, ok := greetings[language]; ok {
    return r, nil
    } else {
    return "", errors.New("the language you selected is not valid")
    }
    }
    Error Handling

    View Slide

  55. ‹#›
    @tpryan
    var ErrNotFound = errors.New("the language you selected is not valid")
    func Greet(language string) (string, error) {
    if r, ok := greetings[language]; ok {
    return r, nil
    } else {
    return "", ErrNotFound
    }
    }
    Error Handling

    View Slide

  56. ‹#›
    @tpryan
    func main() {
    l := flag.String("lang", "English", "a language in which to get greeting.")
    flag.Parse()
    greet, err := helloworld.Greet(*l)
    if err != nil {
    log.Fatal(err.Error())
    }
    fmt.Printf("%s\n", greet)
    }
    Error Handling

    View Slide

  57. ‹#›
    @tpryan
    func main() {
    l := flag.String("lang", "English", "a language in which to get greeting.")
    flag.Parse()
    greet, err := helloworld.Greet(*l)
    if err != nil {
    if err == helloworld.ErrNotFound {
    listLanguages()
    return
    } else {
    log.Fatal(fmt.Errorf("could not get greeting: %v\n”, err))
    }
    }
    fmt.Printf("%s\n", greet)
    }
    Error Handling

    View Slide

  58. ‹#›
    @tpryan
    package helloworld
    import "errors"
    var greetings = map[string]string{"Chinese": "你好世界", … }
    var ErrNotFound = errors.New("the language you selected is not valid")
    func Greet(language string) (string, error) {…}
    func helper(language string) (int) {…}
    Hello World

    View Slide

  59. ‹#›
    @tpryan
    package main
    import (
    "fmt"
    "log"
    "os"
    "github.com/tpryan/gosamples/helloworld"
    )
    Hello World

    View Slide

  60. ‹#›
    @tpryan
    Object Oriented
    Sorta

    View Slide

  61. ‹#›
    @tpryan
    type Greeting struct {
    Text string
    }
    Custom Types

    View Slide

  62. ‹#›
    @tpryan
    type Greeting struct {
    Text string
    }
    func (g Greeting) Address() string{
    return g.Text + ", Human!"
    }
    Custom Types - public methods

    View Slide

  63. ‹#›
    @tpryan
    type Greeting struct {
    Text string
    }
    func (g Greeting) Address() string {
    return g.Text + ", Human!"
    }
    func (g Greeting) threat() string {
    return g.Text + ", Human! Hah, we will crush them."
    }
    Custom Types - private methods

    View Slide

  64. ‹#›
    @tpryan
    type Greeting struct {
    Text string
    secret string
    }
    func (g Greeting) Address() string {
    return g.Text + ", Human!"
    }
    func (g Greeting) threat() string {
    return g.Text + ", Human! Hah, we will crush them."
    }
    Custom Types - private field

    View Slide

  65. ‹#›
    @tpryan
    Package, Type, and Method Names
    • Be descriptive, but concise
    • No: package l
    • No: package logFileWriter
    • Yes: package log
    • Don’t repeat yourself
    • No: log.LogFileWrite
    • No: log.LogFileRead
    • Better: log.Write(dest File)
    • Better: log.Read(src File)
    • Best: log.Write(dest io.Writer)
    • Best: log.Read(src io.Reader)

    View Slide

  66. ‹#›
    @tpryan
    04 Web application
    Cause we didn’t come here to build CLIs

    View Slide

  67. ‹#›
    @tpryan
    package helloworld
    import "errors"
    var greetings = map[string]string{"Chinese": "你好世界", … }
    var ErrNotFound = errors.New("the language you selected is not valid")
    func Greet(language string) (string, error) {…}
    func Langauges() []string
    Web app - base package

    View Slide

  68. ‹#›
    @tpryan
    package main
    import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "github.com/tpryan/gosamples/helloworld"
    )
    func main() {
    http.HandleFunc("/get", HandleGet)
    http.HandleFunc("/list", HandleList)
    http.ListenAndServe(":8080", nil)
    }
    Web app - main

    View Slide

  69. ‹#›
    @tpryan
    func main() {
    http.HandleFunc("/get", HandleGet)
    http.HandleFunc("/list", HandleList)
    http.ListenAndServe(":8080", nil)
    }
    Web app - wire up routing

    View Slide

  70. ‹#›
    @tpryan
    func HandleList(w http.ResponseWriter, r *http.Request) {
    list := helloworld.Langauges()
    json, err := json.Marshal(list)
    if err != nil {
    handleError(w, err)
    return
    }
    sendJSON(w, string(json), http.StatusOK)
    }
    Web app - list handler

    View Slide

  71. ‹#›
    @tpryan
    func HandleGet(w http.ResponseWriter, r *http.Request) {
    lang := r.FormValue("language")
    greet, err := helloworld.Greet(lang)
    if err != nil {
    handleError(w, err)
    return
    }
    sendJSON(w, greet, http.StatusOK)
    }
    Web app - get handler

    View Slide

  72. ‹#›
    @tpryan
    func handleError(w http.ResponseWriter, err error) {
    msg := fmt.Sprintf("{\"error\":\"%s\"}", err.Error())
    sendJSON(w, msg, http.StatusInternalServerError)
    log.Print(err)
    }
    func sendJSON(w http.ResponseWriter, content string, status int) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    fmt.Fprint(w, content)
    }
    Web app - responders

    View Slide

  73. ‹#›
    @tpryan
    05 Concurrency

    View Slide

  74. ‹#›
    @tpryan
    06 Tooling

    View Slide

  75. ‹#›
    @tpryan
    go fmt main.go 

    Formatting Code

    View Slide

  76. ‹#›
    @tpryan
    go build main.go 

    Building Executable

    View Slide

  77. ‹#›
    @tpryan
    go test
    Testing

    View Slide

  78. ‹#›
    @tpryan
    func TestGreet(t *testing.T) {
    cases := []struct {
    In string
    Out string
    Err error
    }{
    {"", "", ErrorNotFound},
    {"English", "Hello world", nil},
    }
    for _, c := range cases {
    actualOut, actualErr := Greet(c.In)
    if actualOut != c.Out {
    t.Errorf("Validate(%q) == %q, want %q", c.In, actualOut, c.Out)
    }
    if actualErr != nil && actualErr != c.Err {
    t.Errorf("Validate(%q) == %q, want %q", c.In, actualErr, c.Err)
    }
    }
    }
    Testing

    View Slide

  79. ‹#›
    @tpryan
    go doc
    Seeing Documentation

    View Slide

  80. ‹#›
    @tpryan
    godoc -http :8080
    Seeing Documentation But Better

    View Slide

  81. ‹#›
    @tpryan
    // Package helloworld returns greetings in several common languages
    package helloworld
    import "errors"
    // ErrorNotFound occurs when the input language is not one we have
    // in our collection
    var ErrorNotFound = errors.New("the language you selected is not valid")
    // Greet returns a greeting in the input language. If the languages is not
    // found, returns ErrorNotFound
    func Greet(language string) (string, error) {…}
    // Languages returns a list of the supported languages
    func Languages() []string {…}
    Seeing Documentation But Better

    View Slide

  82. ‹#›
    @tpryan
    Seeing Documentation But Better

    View Slide

  83. ‹#›
    @tpryan
    go get github.com/gorilla/rpc
    Retrieve Dependency

    View Slide

  84. ‹#›
    @tpryan
    IDE

    View Slide

  85. ‹#›
    @tpryan

    View Slide

  86. ‹#›
    @tpryan
    07 Use Cases
    When does it make sense to switch

    View Slide

  87. ‹#›
    @tpryan
    • Get articles from Wordpress MySQL
    • Flatten into HTML Files
    • Write to Disk
    Task 1

    View Slide

  88. ‹#›
    @tpryan
    make test n=10
    Executing php test
    0.573
    Executing go test
    0.557
    Task 1

    View Slide

  89. ‹#›
    @tpryan
    make test n=100
    Executing php test
    4.384
    Executing go test
    5.146
    Task 1

    View Slide

  90. ‹#›
    @tpryan
    func writeSeq(entries []Entry, outdir string, count int, t template.Template) error {
    for i := 1; i <= count; i++ {
    err := writeEntries(entries, outdir+strconv.Itoa(i), t)
    if err != nil {
    log.Fatal(err)
    }
    }
    return nil
    }
    First attempt

    View Slide

  91. ‹#›
    @tpryan
    func writePar(entries []Entry, outdir string, count int, t template.Template) error {
    var wg sync.WaitGroup
    wg.Add(count)
    for i := 1; i <= count; i++ {
    go func(i int, wg *sync.WaitGroup) {
    defer wg.Done()
    err := writeEntries(entries, outdir+strconv.Itoa(i), t)
    if err != nil {
    log.Fatal(err)
    }
    }(i, &wg)
    }
    wg.Wait()
    return nil
    }
    Use concurrency

    View Slide

  92. ‹#›
    @tpryan
    make test n=100 method=parallel
    Executing php test
    4.614
    Executing go test
    2.889
    Task 1

    View Slide

  93. ‹#›
    @tpryan
    • Get password from Randomly Generated list
    • Test if password conforms to rules
    • Include a dictionary check
    Task 2
    Pa$$w0rdCh3ck

    View Slide

  94. ‹#›
    @tpryan
    "AALII",
    "AALIIS",
    "AALS",
    "AARDVARK",
    "AARDVARKS",
    "AARDWOLF",
    "AARDWOLVES",
    "AARGH",
    "AARRGH",
    "AARRGHH",
    "AAS",
    "AASVOGEL",
    "AASVOGELS",
    "AB",
    Method 1 - Hash
    Pa$$w0rdCh3ck
    "Pa$$",
    "a$$w",
    "$$w0",
    "$w0r",
    "w0rd",
    "0rdC",
    "rdCh",
    "dCh3",
    "Ch3c",
    "h3ck",
    "Pa$$w",
    "a$$w0",
    "$$w0r",
    "$w0rd",

    View Slide

  95. ‹#›
    @tpryan
    make test n=10 method=hash
    Executing php test
    0.141
    Executing go test
    0.077
    Task 2

    View Slide

  96. ‹#›
    @tpryan
    make test n=1000 method=hash
    Executing php test
    0.264
    Executing go test
    0.091
    Task 2

    View Slide

  97. ‹#›
    @tpryan
    make test n=100000 method=hash
    Executing php test
    7.339
    Executing go test
    0.823
    Task 2

    View Slide

  98. ‹#›
    @tpryan
    "AALII",
    "AALIIS",
    "AALS",
    "AARDVARK",
    "AARDVARKS",
    "AARDWOLF",
    "AARDWOLVES",
    "AARGH",
    "AARRGH",
    "AARRGHH",
    "AAS",
    "AASVOGEL",
    "AASVOGELS",
    "AB",
    Method 2 - Bruteforce
    Pa$$w0rdCh3ck

    View Slide

  99. ‹#›
    @tpryan
    make test n=10 method=bruteforce
    Executing php test
    0.962
    Executing go test
    0.094
    Task 2

    View Slide

  100. ‹#›
    @tpryan
    make test n=1000 method=bruteforce
    Executing php test
    96.425
    Executing go test
    1.809
    Task 2

    View Slide

  101. ‹#›
    @tpryan
    • Write an app with 3 Docker images
    • Host on Kubernetes
    • Have the smallest Docker images possible
    Task 3

    View Slide

  102. ‹#›
    @tpryan
    • Whack a pod
    • API - random color generator
    • PHP
    • gcr.io/google_appengine/php:latest
    • Admin - Kubernetes API Proxy
    • PHP
    • gcr.io/google_appengine/php:latest
    • Game - UI for app
    • HTML/JS/CSS
    • gcr.io/google_appengine/php:latest
    Task 3
    Before After
    API 171 MB
    Admin 171 MB
    Game 181 MB
    Total 523 MB

    View Slide

  103. ‹#›
    @tpryan
    • Whack a pod
    • API - random color generator
    • Golang executable
    • Scratch
    • Admin - Kubernetes API Proxy
    • Golang executable
    • Scratch
    • Game - UI for app
    • HTML/JS/CSS
    • nginx
    Task 3
    Before After
    API 171 MB 2 MB
    Admin 171 MB 2 MB
    Game 181 MB 49 MB
    Total 523 MB 53 MB
    -470 MB

    View Slide

  104. ‹#›
    @tpryan
    Does it actually
    matter?

    View Slide

  105. ‹#›
    @tpryan
    08 Go Weirdness
    Top things that bug new Gophers

    View Slide

  106. ‹#›
    @tpryan
    • https://opencredo.com/why-i-dont-like-error-handling-in-go/
    • https://blog.golang.org/errors-are-values
    • https://github.com/pkg/errors
    • But, all I can say is you get used to it.
    No exceptions

    View Slide

  107. ‹#›
    @tpryan
    • Maybe arrays, slices, and maps will work?
    • Maybe interfaces will work?
    • Maybe using … in signature definition will work?
    • Or you know, maybe Go isn’t for you
    No Generics

    View Slide

  108. ‹#›
    @tpryan
    • Yes, it is.
    Gopath is confusing

    View Slide

  109. ‹#›
    @tpryan
    • All Go projects happen in workspaces
    • All Go workspaces have 3 parts
    • src
    • bin
    • pkg
    • Most everything happens in src
    • github.com/username/project
    • Set folder that contains src, bin, pkg to GOPATH
    • export GOPATH=$HOME/go

    Go Path

    View Slide

  110. ‹#›
    @tpryan
    • go get
    • vendoring
    • dep Maturing soon
    Dependency Management

    View Slide

  111. ‹#›
    @tpryan
    08 Conclusions
    Bring it home

    View Slide

  112. ‹#›
    @tpryan
    Use go for problems where
    PHP has pain dealing with
    all the things you need to
    handle.
    - That Google Guy

    View Slide

  113. ‹#›
    @tpryan
    Use go for all the things!
    - That Google Guy

    View Slide

  114. ‹#›
    @tpryan
    Use go for problems where
    PHP has pain dealing with
    all the things you need to
    handle.
    - That Google Guy

    View Slide

  115. ‹#›
    @tpryan
    Search for ‘golang’
    - That Google Guy

    View Slide

  116. ‹#›
    @tpryan
    Thank You
    Gopher Images credits
    Renee French
    gophercloud
    Blue Matador
    Ashley McNamara

    View Slide

  117. ‹#›
    @tpryan
    Thank You
    terrenceryan.com
    @tpryan
    This preso: http://bit.ly/tpryan-go4php

    View Slide