GO

small, practical language for the new century

Talk by Matej Baćo from Nivas

Talk breakdown

  1. What is it
  2. Why it's hot
  3. Code:
    1. Pipes
    2. Concurrency
    3. Interfaces
  4. Where to start
  5. Conclusion
  6. Q&A

What is it

  1. open-source
  2. compiled
    super fast, cross compile out of the box
  3. general-purpose
    designed with systems programming in mind
  4. statically typed
    := for implicit type
  5. garbage-collected
  6. memory safe
  7. explicit support for concurrent programming
  8. language is small

The Go Programming Language Specification on http://golang.org/ref/spec

About

Original creators Ken Thompson (Unix, B etc.), Robert Griesemer (V8 etc.) and Rob Pike (Unix, UTF-8 etc.)

It borrows from Unix pipe mechanism and atomic programs (single purpose), is very fast, works great with UTF-8 and has excellent concurrency model.

Go is opinionated

it has preconceived ideas about what programming language should have or more importantly should not have in order to make programming easier and more practical

Less is more

Go is opinionated

  • no type inheritance
  • no method or operator overloading
  • no pointer arithmetic
  • no generic programming
  • no list comprehensions
  • no exceptions
  • no default function parameters

Go is opinionated

  • yes to type embedding where one type can contain others and pick up their methods
  • yes to type assertion
  • yes to interface{}, sort of a base type
  • yes to code generation
  • yes panic/recover
  • yes multiple return values

Opinionated but not dogmatic

  • Lots of OO elements: types have methods, local state, behavior, public/private access
  • Lots of functional elements: first class functions, higher-order functions, user-defined function types, function literals, closures

Why it's hot

It has the MOST FEARSOME mascot in the world!

Gopher

Easy to pick-up


package main

import (
	"log"
	"github.com/user/db"
)

func main() {
	dbUser, dbPass := "root", "password"

	dbConn, err := db.Open(dbUser, dbPass)
	if err != nil {
		log.Fatalf("DB connect failed with %v", err)
	}
	defer dbConn.Close()

	// ...
}
					

Don't have db package from last slide?

Just type go get github.com/user/db in command line

Great tools!

  • go build [-race]
  • go get
  • go fmt
  • go test [-cover]
  • godoc
  • go generate
  • go tool pprof
  • list go's on ...

pipes

as in Unix shell eq.
find . -name ".log" | grep "DEBUG" | xargs rm


// ...

staticHandler := static.NewHandler(ROOT_PATH)
gzipStaticHandler := gzip.NewHandler(staticHandler)
router.PathPrefix("/resources").Handler(gzipStaticHandler)

// ...

updateHandler := update.NewHandler(ROOT_PATH)
updateAuthHandler := auth.NewAuthHandler(updateHandler)
router.PathPrefix("/update").Methods("POST").Handler(updateAuthHandler)

// ...

http.ListenAndServe(":8080", nil)
					

CONCURRENCY model

Goroutines, non-blocking execution of concurrent functions multiplexed onto multiple OS threads, which synchronize and coordinate using special type called channel.

CONCURRENCY model

  • Based on communication
  • Easy to reason about

Simple example


package main

import "fmt"

func main() {
	idCh := make(chan int)

	go func() {
		id := 0
		for {
			idCh <- id
			id = id + 1
		}
	}()

	fmt.Println(<-idCh)
	fmt.Println(<-idCh)
	fmt.Println(<-idCh)
}
					

Run it https://play.golang.org/p/w5MPNUVi-J

Real world example


// ...

type fileTask struct {
  Path string
  Node os.FileInfo
  Err  error
}

var taskCh chan *fileTask
var wg sync.WaitGroup

func main() {
  runtime.GOMAXPROCS(runtime.NumCPU())

  // ...

  taskCh = make(chan *fileTask)

  for i := 0; i < 1000; i++ {
    go worker(i, taskCh)
  }

  err := filepath.Walk(inputPath, visit)

  // ...

  wg.Wait()
}

func visit(path string, node os.FileInfo, err error) error {
  task := &fileTask{
    Path: path,
    Node: node,
    Err:  err}
  
  wg.Add(1)
  taskCh <- task

  return nil
}

func worker(workerId int, taskCh <-chan *fileTask) {
  for {
    task := <-taskCh

    // ...

    deleted, err := visitLogic(task.Path, task.Node)
        
    // error handling and logging ...

    wg.Done()
  }
}
// ...
					

Implicit interfaces

“Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here.”

Interface usage example


package io

type Reader interface {
        Read(p []byte) (n int, err error)
}

// -----

func deletable(r io.Reader) bool
r, err := os.Open(pathToFile)
del := deletable(r)

// ----

func Open(name string) (file *File, err error)
type File struct {}
func (f *File) Read(b []byte) (n int, err error)

					

Where to start

Conclusion

  • exceptionally good at tackling some problems
  • it works for small (and big) applications
  • it fast
  • easy to learn
  • low maintenance

Q&A

Please give feedback for this talk on
joind.in/13601

Slides will be on the same address.