Introducing 

go

@mcolomer

marcelo.colomer@gft.com

Go was designed by Google to help solve Google's problems, and Google has big problems.

  • Eliminate the slowness and clumsiness of software development
  • Make the process more productive and scalable.  
  • Go is more about software engineering than programming language research.  

 2009 by Robert Griesemer, Rob Pike y Ken Thompson.

  • Compiled
  • Statically typed
  • Garbage Collection
  • Limited Structural Typing
  • Memory Safety features
  • CSP Style - Concurrent programming

CSP -> Communicating sequential processes

go

break    default      func    interface    select
case     defer        go      map          struct
chan     else         goto    package      switch
const    fallthrough  if      range        type
continue for          import  return       var

25 keywords

// define a variable with name “variableName” and type "type"
var variableName type
 
var vname1, vname2, vname3 type
 
var variableName type = value

var vname1, vname2, vname3 type = v1, v2, v3

var vname1, vname2, vname3 = v1, v2, v3

vname1, vname2, vname3 := v1, v2, v3

Define variables

const constantName = value
// you can assign type of constants if it's necessary
const Pi float32 = 3.1415926

const Pi = 3.1415926
const i = 10000
const MaxThread = 10
const prefix = "astaxie_"

const(
    i = 100
    pi = 3.1415
    prefix = "Go_"
)

Define constants

iota enumerate

const(
    x = iota  // x == 0
    y = iota  // y == 1
    z = iota  // z == 2
    w  // If there is no expression after the constants name, it uses the last expression,
       //so it's saying w = iota implicitly. 
       // Therefore w == 3, and y and z both can omit "= iota" as well.
)

rules

  • Any variable that begins with a capital letter means it will be exported, private otherwise.
  • The same rule applies for functions and constants, no public or private keyword exists in Go.

array, slice, map

var arr [10]int  // an array of type [10]int
arr[0] = 42      // array is 0-based

b := [10]int{1, 2, 3} // define a int array with 10 elements, of which the first three are assigned.

c := [...]int{4, 5, 6} // use `…` to replace the length parameter and Go will calculate it for you.
slice := []byte {'a', 'b', 'c', 'd'}

//slice is not really a dynamic array. It's a reference type. 
//slice points to an underlying array whose declaration is similar to array, but doesn't need length. 
 
var numbers map[string] int
// another way to define map
numbers := make(map[string]int)
numbers["one"] = 1  // assign value by key

//map is disorderly. Everytime you print map you will get different results. 
//map doesn't have a fixed length. It's a reference type just like slice.
//len works for map also. It returns how many keys that map has.

//make does memory allocation for built-in models, such as map, slice, and channel, 
//while new is for types' memory allocation.

structs

type person struct {
    name string
    age int
}

var P person  // p is person type

P.name = "Astaxie"  // assign "Astaxie" to the field 'name' of p
P.age = 25  // assign 25 to field 'age' of p
fmt.Printf("The person's name is %s\n", P.name)  // access field 'name' of p

s := person{name: "Sean", age: 50}

type Skills []string

type Human struct {
    name   string
    age    int
    weight int
}

type Student struct {
    Human     // struct as embedded field
    Skills    // string slice as embedded field
    int       // built-in type as embedded field
    specialty string
}

jane := Student{Human: Human{"Jane", 35, 100}, specialty: "Biology"}

Go’s structs are typed collections of fields

methods

//A method is a function with an implicit first argument, called a receiver.
func (r ReceiverType) funcName(parameters) (results)
type Circle struct {
    radius float64
} 

// method
func (c Circle) Area() float64 {
    return c.radius * c.radius * math.Pi
} 

// method with a pointer receiver
func (c *Circle) SetRadius(r float64) {
    c.radius = f
}

func main() {
    c1 := Circle{10}  
    fmt.Println("Area of c1 is: ", c1.Area()) 
}

interfaces

//An empty interface does not contain any methods, 
//all types implement an empty interface
var void interface{}

type geometry interface {
    area() float64 
} 

type rect struct {
    width, height float64
}
type circle struct {
    radius float64
} 

func (r rect) area() float64 {
    return r.width * r.height
} 

func (c circle) area() float64 {
    return math.Pi * c.radius * c.radius
} 

func measure(g geometry) {
    fmt.Println(g)
    fmt.Println(g.area())
    fmt.Println(g.perim())
}

func main() {
    r := rect{width: 3, height: 4}
    c := circle{radius: 5} 
    measure(r)
    measure(c)
}

Testing

Package testing provides support for automated testing of Go packages

package math

import "testing"

func TestAverage(t *testing.T) {
  var v float64
  v = Average([]float64{1,2})
  if v != 1.5 {
    t.Error("Expected 1.5, got ", v)
  }
}
$ go test

Includes benchmarking and statement-based code coverage

Avoids the use of assertions and leaves the responsibility to the developer

$ go test -cover
$ go test -cover -coverprofile=c.out
$ go tool cover -html=c.out -o coverage.html 

A file with a name ending in _test.go that contains functions named TestXXX with signature func (t *testing.T)

designed for concurrency

Concurrency is not parallelism  

  • Concurrency is about dealing with lots of things at once.
  • Parallelism is about doing lots of things at once.

If you have only one processor, your program can still be concurrent but it cannot be parallel.

On the other hand, a well-written concurrent program might run efficiently in parallel on a multiprocessor.

  • Independently executing function, launched by a go statement.
  • It has its own call stack, which grows and shrinks as required.
  • It's not a thread.
  • It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines.
  • There might be only one thread in a program with thousands of goroutines.
  • goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running.

What is a goroutine?

"a very cheap thread"

Channels

A channel in Go provides a connection between two goroutines, allowing them to communicate.

  
  • A sender and receiver must both be ready to play their part in the communication. Otherwise we wait until they are.
  • Thus channels both communicate and synchronize.
  // Declaring and initializing.
    var c chan int
    c = make(chan int)
    // or
    c := make(chan int)
    // Sending on a channel.
    c <- 1
    // Receiving from a channel.
    // The "arrow" indicates the direction of data flow.
    value = <-c

The Go approach

Don't communicate by sharing memory, share memory by communicating.

func boring(msg string) <-chan string { // Returns receive-only channel of strings.
    c := make(chan string)
    go func() { // We launch the goroutine from inside the function.
        for i := 0; ; i++ {
            c <- fmt.Sprintf("%s %d", msg, i)
            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
        }
    }()
    return c // Return the channel to the caller.
}
  • Handle multiple channels.
  • It's like a switch, but each case is a communication:
   select {
    case v1 := <-c1:
        fmt.Printf("received %v from c1\n", v1)
    case v2 := <-c2:
        fmt.Printf("received %v from c2\n", v1)
    case c3 <- 23:
        fmt.Printf("sent %v to c3\n", 23)
    default:
        fmt.Printf("no one was ready to communicate\n")
    }

Select

  • All channels are evaluated.
  • Selection blocks until one communication can proceed, which then does.

  • If multiple can proceed, select chooses pseudo-randomly.

  • A default clause, if present, executes immediately if no channel is ready

   
  c := make(chan Result)
    go func() { c <- First(query, Web1, Web2) } ()
    go func() { c <- First(query, Image1, Image2) } ()
    go func() { c <- First(query, Video1, Video2) } ()
    timeout := time.After(80 * time.Millisecond)
    for i := 0; i < 3; i++ {
        select {
        case result := <-c:
            results = append(results, result)
        case <-timeout:
            fmt.Println("timed out")
            return
        }
    }
    return

Example

  • There is no VM. compiles directly to the machine code  

  • Fast compilation.  

  • Compiles cross-platform  

  • Creates only one executable file 

  • Safe
    • Strong and static typed.

    • Garbage collected.  

    • Reliable

  • Different kind of object-oriented programming

  • Built-in concurrency

  • Almost all of the things built into its standard library

goodness

The Computer Language Benchmarks Game

http://benchmarksgame.alioth.debian.org/

Go is now a supported language for AWS Lambda

Speed

Java and C# both have notoriously slow cold-start time, in terms of multiple seconds. With Go, the cold-start time is much lower, closer to Python and Javascript.

Safety

Golang is a compiled & statically-typed language.

  • No generics support.

  • Err everywhere

  • No function overloading support.

  • Strict rules.

  • Not so strong runtime safety.

  • Smaller number of packages

 

 

drawbacks

https://www.stackoverflowbusiness.com/hubfs/content/2017_Global_Developer_Hiring_Landscape.pdf

Tooling

build       compile packages and dependencies
clean       remove object files
doc         show documentation for package or symbol
env         print Go environment information
bug         start a bug report
fix         run go tool fix on packages
fmt         run gofmt on package sources
generate    generate Go files by processing source
get         download and install packages and dependencies
install     compile and install packages and dependencies
list        list packages
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         run go tool vet on packages

https://github.com/golang/go/wiki/GoUsers

THANK YOU

Introducing GO

By Marcelo Colomer

Introducing GO

  • 813