Why we use golang

Introduction to golang

10 September 2014

Gediminas Morkevicius

Senior Gopher at, DATA-DOG

You will see a lot of this guy.. sorry if it hurts your feelings

So why

has started to use GO as a secondary language

And squint-eyed gopher friend of course

What is it good for?

We all know about long running PHP processes

Don't we?

Why not just use GO for all daemons. Its lighter than Java or C++

Lets see some code

Daemon using HTTP API to listen for jobs

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/gorilla/mux"
)

func job(name string) {
    time.Sleep(time.Second * 10)
    log.Printf("Job %s was handled successfully\n", name)
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/job/{name}", func(w http.ResponseWriter, req *http.Request) {
        go job(mux.Vars(req)["name"])
        fmt.Fprintf(w, "Job is now being processed!")
    })
    http.Handle("/", r)
    log.Fatal(http.ListenAndServe(":8888", nil))
}

Concurrent result producers through channel

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func producer(name string, publisher chan string) {
    for {
        rand.Seed(time.Now().UnixNano())
        time.Sleep(time.Second * time.Duration(rand.Intn(5)+2))
        publisher <- fmt.Sprintf("%s => did a job", name)
    }
}
func main() {
    res := make(chan string)
    go producer("job1", res)
    go producer("job2", res)
    go producer("job3", res)
    for result := range res {
        fmt.Printf("Got result: %s\n", result)
    }
}

Build your application for any platform

export GOOS=linux && export GOARCH=386 && go build
export GOOS=darwin && export GOARCH=amd64 && go build

Deployment

The executable is compiled to machine code. It does not
need anything else to run. Deployment is a simple upload.

Supervisor

For convinience, supervisord utility can be used to watch applications.

Handling multiple channels

package main

import (
    "fmt"
    "time"
)

func main() {
    var one, two = make(chan string), make(chan string)
    go func() {
        for {
            time.Sleep(time.Second)
            two <- "msg1"
            one <- "msg2"
        }
    }()
    for {
        select {
        case msg := <-one:
            fmt.Printf("received %s from chan: one\n", msg)
        case msg := <-two:
            fmt.Printf("received %s from chan: two\n", msg)
        }
    }
}

Interfaces

In golang interfaces are implicit meaning - to satisfy an interface struct
must implement all required methods with the same signature. But it does not need
to know that such interface exists.

type Stringer interface {
    String() string
}

Stringer interface from fmt package.

Stringer example

package main

import "fmt"

type Car struct {
    Name string
}

func (c Car) String() string {
    return fmt.Sprintf("Car named: %s", c.Name)
}

func main() {
    fmt.Printf("Some '%s'", Car{"BMW"})
}

An interface can be returned by functions

package main

import "fmt"

type secretCar struct {
    Name string
}

func (c *secretCar) String() string {
    return fmt.Sprintf("Secret car named: %s", c.Name)
}

func New(name string) fmt.Stringer {
    return &secretCar{name}
}

func main() {
    printables := make([]fmt.Stringer, 0)
    printables = append(printables, New("BMW"), New("Audi"))
    for _, printable := range printables {
        fmt.Printf("A stringer '%s'\n", printable)
    }
}

Composition

In GO there is no inheritance - there is composition

Given, we have a package which exports a Car

package car

import "fmt"

type Car struct {
    Doors         int
    Vendor, Model string
    millage       int // private member
}

func (c *Car) String() string {
    return fmt.Sprintf("Car %s model %s with %d doors, millage %d",
        c.Vendor, c.Model, c.Doors, c.millage)
}

func (c *Car) Drive(km int) *Car {
    c.millage += km
    return c
}

Composition

package main

import (
    "fmt"
    "talks/car"
)

type BmwX5 struct {
    car.Car // composed of Car
    Engine  string
}

func New() *BmwX5 {
    return &BmwX5{
        car.Car{Vendor: "BMW", Model: "X5", Doors: 5}, "V8",
    }
}

func main() {
    fmt.Printf("Car: %s\n", New().Drive(5))
}

Marshalers

In GO standard library provides a well structured json library, which implements Marshaler interfaces
to allow reading from and writing to structures.

Given we have some structures defined in our package:

package talks

type Product struct {
    Price float64 `json:"price"`
    Name  string  `json:"name"`
}

type Buyer struct {
    Name string `json:"name"`
}

type Message struct {
    Order    int64      `json:"order_id"`
    Buyer    *Buyer     `json:"buyer"`
    Products []*Product `json:"products"`
}

Marshalers

package main

import (
    "encoding/json"
    "fmt"
    "talks"
)

func main() {
    s := `{
"order_id": 6,
"unused": "mmm",
"buyer": {
  "name": "John Doe"
},
"products": [
  {"name": "foo", "price": 1.99},
  {"name": "bar", "price": 1.55}
]}`

    var msg talks.Message
    _ = json.Unmarshal([]byte(s), &msg)
    fmt.Printf("%+v\n", msg)
}

Trust me

It is a great deal to use GO

Actually it drives people nuts

Lithuanian gopher user group

We have the official GO to create a golang user group in lithuania!
Wait for the news from:

The site is being created. Of course, using golang :)

Thank you

Gediminas Morkevicius

Senior Gopher at, DATA-DOG

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)