Go Workshop - Dia 1

https://golang-workshop.io

Rodolfo Finochietti

Chief Delivery Officer, Lagash

Most popular languages

Stack Overflow Developer Survey 2019

"The street finds its own uses for things."
Burning Chrome, William Gibson

2

Por que otro lenguaje de programacion?

Las computadoras tiene muchos nucleos
Los sistemas estan mas distribuidos
Los usuarios son mucho mas exigentes
Manejo de librerias y dependencias
Velocidad para compilar
Facilidad para programar
Testing
... you can build a production binary on your Mac and ship it up to a Linux server 
and just run it without any crazy installs or any worrying about dependency conflicts. 

Brian Ketelsen, Microsoft.
3

Quienes

Bell Labs, Unix, Unix Shell, UTF-8
Bell Labs, Unix, Plan 9, UTF-8
Google V8, Java HotSpot
Meet the authors
4

Por que

Programming had become too difficult and the choice of languages was partly to blame. 
One had to choose either efficient compilation, efficient execution, or ease of programming; 
all three were not available in the same mainstream language.
5

Otra razon - $$$ - :)

Stack Overflow Developer Survey 2019
6

Premisas

No corre en una maquina virtual
7

Caracteristicas

Net / Http
IO
Concurrency
Built in Web Server
Built in Testing Framework
Integracion con Git
Lineal, paso a paso
Loops, conditionals
Fuertemente tipado (pero con inferencia de tipos)
Structs instead of classes 
No Inheritance (mejor componer que heredar)
No overloading (pero si polimorfismo)
8

Caracteristicas

Pueden ser pasadas como parametros
9

Manos a la obra

10

Instalacion

Ejercicio 1
11

Hello World

Ejercicio 2
package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

Comandos basicos desde consola

go command [arguments]

build     Compila paquetes y dependencias
clean     Remueve archivos object     
get       Descarga e instala paquetes y dependencias
install   Compila e instala paquetes y dependencias
run       Compila y corre paquetes y dependencias
test      Testea paquetes
fmt       Formatea el codigo
...
12

Variables

Ejercicio 3
package main

import "fmt"

func init() { 
    fmt.Println("Se ejecuta init")
}

func main() {
    var a int // Default initialization
    fmt.Println("a: ", a)

    var b = 10 // Automatic type inference
    fmt.Println("b: ", b)

    var c, d = 20, 30 // Multiple value assignment
    fmt.Println("c: ", c, " d: ", d)

    e, f := 40, 50 // Shorthand assignment
    fmt.Println("e: ", e, " f: ", f)
}
13

Tipos

Ejercicio 4
package main

import (
    "fmt"
    "math"
)

func main() {
    var i int16 = 55     // int16
    var j float32 = 67.8 // float32
    sum := i + int16(j)  // j is converted to int
    fmt.Println(sum)

    const aa int = 48
    const bb bool = true
    fmt.Println(aa, bb)

    var x, y int = 3, 4
    var f float64 = math.Sqrt(float64(x*x + y*y)) // Explicit type conversion
    var z uint = uint(f) // Explicit type conversion
    fmt.Println(x, y, z)
}
14

Operadores

Ejercicio 5
package main

import "fmt"

func main() {
    // Numeric operators
    fmt.Println(20 + 10)
    fmt.Println(20 - 10)
    fmt.Println(20 / 10)
    fmt.Println(20 * 10)
    fmt.Println(20 % 10)

    // Boolean operators
    fmt.Println(true && true)
    fmt.Println(true && false)
    fmt.Println(true || true)
    fmt.Println(true || false)
    fmt.Println(!true)
}
15

Funciones - Multiples Valores de Retorno - Blank Identifier

Ejercicio 6
package main

import "fmt"

func main() {
    var sum = AddIntegers(10, 20)
    fmt.Println("Sum of 10 and 20 is", sum)

    var sum2, diff = SumDifference(10, 20)
    fmt.Println("Sum & Difference of 10 and 20 are (", sum2, ",", diff, ")")

    var _, diff1 = SumDifference(10, 20)
    fmt.Println("Difference of 10 and 20 is", diff1)
}

func AddIntegers(a int, b int) int {
    return a + b
}

func SumDifference(a int, b int) (int, int) {
    return a + b, a - b
}
16

Funciones - Named Return Values

Ejercicio 6
func Product(a int, b int) (prod int) {
    prod = a * b
    return
}
17

Instrucciones de control - if

Ejercicio 7
package main

import "fmt"

func main() {
    var aa = 10
    if aa == 10 {
        fmt.Println("The number is 10!")
    } else if aa%2 == 0 {
        fmt.Println("Even number!")
    } else {
        fmt.Println("Odd number")
    }
}
18

Instrucciones de control - for

Ejercicio 7
package main

import "fmt"

func main() {
    // simple
    for i := 1; i <= 10; i = i + 1 {
        fmt.Print(i, " ")
    }
}
19

Instrucciones de control - for

Ejercicio 7
package main

import "fmt"

func main() {
    // simpleBreak
    for i := 1; i <= 10; i = i + 1 {
        if i == 8 {
            break
        }
        fmt.Print(i, " ")
    }
}
20

Instrucciones de control - for

Ejercicio 7
package main

import "fmt"

func main() {
    // simpleContinue
    for i := 1; i <= 10; i = i + 1 {
        if i%2 == 0 {
            continue
        }
        fmt.Print(i, " ")
    }
}
21

Instrucciones de control - for

Ejercicio 7
package main

import "fmt"

func main() {
    // printTower
    const ROWS = 5
    for i := 0; i < ROWS; i++ {
        for j := 0; j <= i; j++ {
            fmt.Print(" * ")
        }
        fmt.Println("")
    }
}
22

Instrucciones de control - switch

Ejercicio 7
package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Print("Go runs on ")

    switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        fmt.Printf("%s.", os)
    }
}
*nacl
23

Review time

24

Packages

Ejercicio 8.1

Se pueden importar paquetes desde Git:

$ go get -u -v github.com/gorilla/mux

Estructura de directorios:

bin (binarios creados con el comando go install)
pkg (package archives, versiones compiladas de los paquetes)
src (codigo fuente)
25

Packages - Visibilidad

Ejercicio 8.2

Cuidado: No exportar identificadores no es una medidad de seguridad y no oculta o proteje ninguna informacion.

26

Arreglos

Ejercicio 9
package main

import "fmt"

func main() {
    var a [3]int
    fmt.Println(a)

    a[0] = 1
    a[1] = 2
    a[2] = 3
    //a := [3]int{1, 2, 3}
    fmt.Println(a)
}
27

Arreglos - Value Type

Ejercicio 9
package main

import "fmt"

func main() {
    a := [...]string{"IRL", "IND", "US", "CAN"}
    b := a

    b[1] = "CHN"

    fmt.Println("Original:", a)
    fmt.Println("Copy    :", b)

    fmt.Println(len(a))
    fmt.Println(len(b))
}
28

Arreglos - Slices

Ejercicio 9
29

Arreglos - Slices

Ejercicio 9
package main

import "fmt"

func main() {
    a := [...]int{1, 2, 3, 4, 5}
    sa := a[1: 4]

    fmt.Println("Before:", a)
    sa[0] = 22

    fmt.Println("After:", a)
}
30

Challenge 1.1

Crear una funcion Reverse que devuelva un string invertido al pasado por parametro.

Hints:

r := []rune(s)
s := string(r)
31

Challenge 1.2 (Opcional)

Modificar la funcion Reverse para invertir el casing de las vocales (solamente).

32

Challenge 1.3

Crear un paquete stringutil que contega la funcion Reverse y se utilice en funcion la main.

33

Archivos

Ejercicio 10
package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    data, err := ioutil.ReadFile("sample.txt")
    if err != nil {
        fmt.Println("File reading error", err)
        return
    }
    fmt.Println("Contents of file:", string(data))

    data := []byte("This is some information!")
    err := ioutil.WriteFile("write_data.txt", data, 0666)
    if err != nil {
        fmt.Println("There has been an error:", err)
        return
    }
}
34

Maps

Ejercicio 11
package main

import "fmt"

func main() {
    m := map[string]int{
        "a": 1,
        "b": 2,
        "c": 3,
    }
    for key, value := range m {
        fmt.Println("Key:", key, " Value:", value)
    }
}
35

Linea de comandos - Argumentos

Ejercicio 12
package main

import (
    "fmt"
    "os"
)

func main() {
    argsWithProg := os.Args
    argsWithoutProg := os.Args[1:]

    arg := os.Args[3]
    fmt.Println("With program name: ", argsWithProg)
    fmt.Println("Just args:", argsWithoutProg)
    fmt.Println("3rd Argument:", arg)
}
36

Linea de comandos - Flags

Ejercicio 12
package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    wordPtr := flag.String("word", "foo", "a string")
    numbPtr := flag.Int("numb", 42, "an int")
    boolPtr := flag.Bool("fork", false, "a bool")
    flag.Parse()

    fmt.Println("word:", *wordPtr)
    fmt.Println("numb:", *numbPtr)
    fmt.Println("fork:", *boolPtr)
    fmt.Println("tail:", flag.Args())
}
37

Linea de comandos - Variables de entorno

Ejercicio 12
package main

import (
    "flag"
    "fmt"
    "os"
    "strings"
)

func main() {
    os.Setenv("FOO", "1")
    fmt.Println("FOO:", os.Getenv("FOO"))
    fmt.Println("BAR:", os.Getenv("BAR"))

    for _, e := range os.Environ() {
        pair := strings.Split(e, "=")
        fmt.Println(pair[0], "->", pair[1])
    }
}
38

Challenge 1.4 (Opcional)

Cambiar el programa para que el parametro string de la funcion Reverse se obtenga desde la linea de comandos con un flag llamado text.

39

Testing

Unit Tests
Benchmarks
Examples
40

Testing - Unit Test

Ejercicio 13
func TestFibonacci(t *testing.T) {
    var in int = 10
    var want int = 55

    got := Fibonacci(in)
    if got != want {
        t.Errorf("Fibonacci(%d) == %d, want %d", in, got, want)
    }
}
41

Testing - Code Coverage

Se puede controlar el code coverage con el comando:

$ go test -cover

Se pueden exportar los resultados y verlos en html con:

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

Testing - Benchmark

Ejercicio 13
func BenchmarkFibonacci(b *testing.B) {
    for n := 0; n < b.N; n++ {
        Fibonacci(10)
    }
}
43

Testing - Benchmark

Ejercicio 13

Un benchmark se ejecuta con el comando go test -bench=. (el parametro bench es regex para indicar cuales benchmarks queremos correr).

El resultado es:

$ go test -bench=.
PASS
BenchmarkFibonacci   5000000               509 ns/op
ok      github.com/rfinochi/golang-workshop       3.084s

La segunda linea indica el valor final de b.N y el tiempo promedio de ejecucion en nanosegundos/operacion.

44

Testing - Benchmark

Ejercicio 13
func BenchmarkFibonacciWrong(b *testing.B) {
        for n := 0; n < b.N; n++ {
                Fibonacci(n)
        }
}

func BenchmarkFibonacciWrong2(b *testing.B) {
        Fibonacci(b.N)
}

Un loop es un operacion crucial en un benchmark, cuidado!

45

Testing - Example

Ejercicio 13
func ExampleFibonacci() {
    fmt.Println(Fibonacci(10))
    // Output: 55
}
46

Challenge 1.5

Crear un unit test, un benchmark, y un example para la funcion Reverse.

47

Thank you

Rodolfo Finochietti

Chief Delivery Officer, Lagash

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.)