Vous êtes sur la page 1sur 106

Programando em Go

David Robert
davidrobert@gmail.com
David Robert
davidrobert@gmail.com
linkedin.com/in/davidrobert
Go uma linguagem de
programao open source
que faz com que seja fcil
construir software simples,
confivel, e eficiente
https://golang.org
tem grandes, grandes
problemas!
Quais (grandes) problemas?

Tanto hardware quanto software so gigantes


Milhes de linhas de cdigo
Servidores principalmente em C++ e uma grande
quantidade em Java e Python
Milhares de desenvolvedores trabalhando
Softwares sendo executado em zilhes de maquinas
Sistemas distribudos em larga escala
Software em larga escala

Builds lentos
Dependncias no controladas
Custo de updates
Dificuldade para automatizar tarefas
Builds entre vrias linguagens de programao
Cdigo difcil de compreender
''
No geral, o desenvolvimento no
grande, lento, e muitas vezes

''
desajeitado. Mas efetivo

https://talks.golang.org/2012/splash.article
Ken Thompson (B, C, Unix, UTF-8)
Rob Pike (Unix, UTF-8)
Robert Griesemer (Hotspot, JVM)
e muitos outros engenheiros do Google
Histria

Muitas pessoas ajudam Comea a ter


a transformar o adoo por outros
prottipo em realidade desenvolvedores

2007 2008 2009 2010

Iniciado e desenvolvido Go se tornou um


por Robert Griesemer, projeto Open
Rob Pike e Ken Thompson Source
em um projeto part-time

https://golang.org/doc/faq#history
Histria

2007 2008 2009 2010

Programming Language Hall of Fame

http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Histrico de Verses

Go 1 Go 1.4
Go 1.3

2012 2013 2014 2015

Go 1.2 Go 1.5
Go 1.1

https://golang.org/project/
Google Trends "golang"
Por que usar Go?
Eliminar lentido
Melhorar a eficacia
Aumentar a produtividade
Manuteno escalvel

Go foi projetado para que pessoas possam escrever,


ler, debugar e manter grandes sistemas de software.

O proposito do Go no ser uma pesquisa sobre


design de linguagens de programao.

O objetivo do Go fazer com que os programadores


vivam melhor.
Performance

http://benchmarksgame.alioth.debian.org
Go contm um conjunto de ferramentas
para gerir cdigo fonte...

Principais ferramentas:
build compila pacotes e dependencias
run compila e executa programas Go
clean remove arquivos objeto
env imprime informaes do ambiente
test testa pacotes e benchmarks

Outras ferramentas:
fix, fmt, get, install, list, tool,
version, vet.
Mas quem usa Go ?
https://github.com/golang/go/wiki/GoUsers
O que voc vai ver em Go
Compilado
Memoria gerenciada (garbage-collected)
Tem seu prprio runtime
Sintaxe simples
Excelente biblioteca padro
Multi plataforma
Orientao a Objetos
Estaticamente e fortemente tipado
Concorrncia (goroutines)
Dependncias explicitas
Retorno multi valorado
Ponteiros
e mais...
O que voc no vai
ver em Go

Tratamento de excees
Herana
Generics
Assert
Sobrecarga de mtodos

Estas caractersticas no foram


implementadas em favor da
eficincia e simplicidade
um pouco de cdigo!
Pacotes
Todo programa Go composto por pacotes
Programas comeam com o pacote main
Este exemplo usa os pacotes ftm e math

$ go run packages.go
My favorite number is 1
Variavis
A instruo var declara uma lista de variavis
O tipo informado no fim
A instruo var pode incluir inicializao, 1 por variavl. Neste
caso, o tipo pode ser omitido porque ser inferido

$ go run variables.go $ go run variables-with-initiali


0 false false false 1 2 true false no!
Declarao de Variveis
Dentro de uma funo, pode ser usada a instruo :
= para inicializar e declarar a variavl

$ go run short-variable-declarations.go
1 2 3 true false no!
Constantes
Constantes so declaradas com a keyword const
No possvel usar :=
$ go run constants.go
Hello world! Happy 3.14 Day! Go rules?
true
Funes
Funes podem ter argumentos
O tipo fica aps o nome do argumento

$ go run functions.go
55
Retorno de valores mltiplos
Uma funo pode ter mltiplos retornos

$ go run multiple-results.go
world hello
Lao For
A nica estrutura do lao que o Go tem for
Muito similar com Java ou C, exceto pelos ( )
A parte inicial e final da declarao podem estar vazias

$ go run for.go $ go run for-continu


45 1024
Lao while
Ponto e vrgula pode ser removidos para simular um while
for pode executar para "sempre"

$ go run for-is-go-while.go $ go run forever.go


1024 process took too long
Condicional
Muito similar com Java ou C, exceto pelos ( )
$ go run if.go
1.4142135623730951 2i
Switch
Muito similar com Java ou C, exceto pelos ( )
$ go run switch.go
Go runs on nacl.
Defer
A declarao defer adia a execuo de uma funo at o final do
retorno da funo
Os argumentos das chamadas adiadas so avaliados imediatamente
$ go run defer.go
hello world
Orientao a Objetos
Orientao a Objetos

Estruturas do Go (similares a classes)


type retangulo struct {
largura, altura int
}
Orientao a Objetos

Estruturas do Go (similares a classes)


type retangulo struct {
largura, altura int
}

Go suporta mtodos definidos em tipos struct


func (r retangulo) area() int {
return r.largura * r.altura
}
Orientao a Objetos

Estruturas do Go (similares a classes)


type retangulo struct {
largura, altura int
}

Go suporta mtodos definidos em tipos struct


func (r retangulo) area() int {
return r.largura * r.altura
}

Inicializao de estruturas

retangulo{10, 20}
retangulo{largura: 10, altura: 20}
Orientao a Objetos
Construtores

package vingadores

type vingador struct {


nome string
}
func NewVingador(nome string) *vingador {
v := new(vingador)
v.nome = nome
return v
}

func main() {
capitao := vingadores.NewVingador("Capito Amrica")
fmt.Println(capitao.nome)
}
Orientao a Objetos
Construtores Depois de importar um pacote, voc pode
consultar os nomes que exporta
package vingadores
Um nome exportado se comea com
type vingador struct { uma LETRA MAISCULA
nome string
}
func NewVingador(nome string) *vingador {
v := new(vingador)
v.nome = nome
return v
}

func main() {
capitao := vingadores.NewVingador("Capito Amrica")
fmt.Println(capitao.nome)
}
Orientao a Objetos
struct.go

1 package main
2
3 import "fmt"
4
5 type pessoa struct {
6 nome string
7 idade int
8 }
9
10 func main() {
11 fmt.Println(pessoa{"Homem de Ferro", 40})
12 fmt.Println(pessoa{nome: "Thor", idade: 100})
13
14 s := pessoa{nome: "Hulk", idade: 45}
15 fmt.Println(s.nome)
16
17 s.idade = 42
18 fmt.Println(s.idade)
19 }
Orientao a Objetos
struct.go

1 package main
2
3 import "fmt" $ go run struct.go
4 {Homem de Ferro 40}
5 type pessoa struct { {Thor 100}
6 nome string
7 idade int Hulk
8 }
9 42
10 func main() {
11 fmt.Println(pessoa{"Homem de Ferro", 40})
12 fmt.Println(pessoa{nome: "Thor", idade: 100})
13
14 s := pessoa{nome: "Hulk", idade: 45}
15 fmt.Println(s.nome)
16
17 s.idade = 51
18 fmt.Println(s.idade)
19 }
Orientao a Objetos
methods.go

1 package main
2 import "fmt"
3
4 type retangulo struct {
5 largura, altura int
6 }
7 func (r retangulo) area() int {
8 return r.largura * r.altura
9 }
10
11 func (r retangulo) perimetro() int {
12 return 2 * r.largura + 2 * r.altura
13 }
14 func main() {
15 r := retangulo{largura: 10, altura: 5}
16
17 fmt.Println("area: ", r.area())
18 fmt.Println("perim:", r.perimetro())
19 }
Orientao a Objetos
methods.go

1 package main
2 import "fmt"
3 $ go run methods.go
4 type retangulo struct { area: 50
5 largura, altura int perim: 30
6 }
7 func (r retangulo) area() int {
8 return r.largura * r.altura
9 }
10
11 func (r retangulo) perimetro() int {
12 return 2 * r.largura + 2 * r.altura
13 }
14 func main() {
15 r := retangulo{largura: 10, altura: 5}
16
17 fmt.Println("area: ", r.area())
18 fmt.Println("perim:", r.perimetro())
19 }
HERANA
HERANA

Como assim
no tem
herana !?
Herana

Por que usamos herana?


Herana

Por que usamos herana?


Reuso de cdigo
Herana

Por que usamos herana?


Reuso de cdigo

Existe efeito colateral em seu uso?


Herana

Por que usamos herana?


Reuso de cdigo

Existe efeito colateral em seu uso?

Acoplamos a implementao da classe me


muito precocemente. A classe filha precisa
conhecer muito bem o cdigo interno da me.

Quebra de encapsulamento
Herana

Alguns crticos afirmam que ela nunca


deveria ser utilizada
Herana

Alguns crticos afirmam que ela nunca


deveria ser utilizada

Go no tem Herana !
Herana

Alguns crticos afirmam que ela nunca


deveria ser utilizada

Go no tem Herana !

Mas tem composio !

Um dos princpios do livro "Design Patterns":


Evite herana, favorea composio
Herana
composition.go
1 package main
2 import "fmt"
3
4 type Car struct {
5 wheelCount int
6 }
7 func (car Car) numberOfWheels() int {
8 return car.wheelCount
9 }
10 type Ferrari struct {
11 Car //anonymous field Car
12 }
13
14 func main() {
15 f := Ferrari{Car{4}}
16
17 fmt.Println("A Ferrari tem ",
18 f.numberOfWheels(), " rodas")
19 }
Herana
composition.go
1 package main
2 import "fmt"
3 $ go run composition.go
4 type Car struct { A Ferrari tem 4 rodas
5 wheelCount int
6 }
7 func (car Car) numberOfWheels() int {
8 return car.wheelCount
9 }
10 type Ferrari struct {
11 Car //anonymous field Car
12 }
13
14 func main() {
15 f := Ferrari{Car{4}}
16
17 fmt.Println("A Ferrari tem ",
18 f.numberOfWheels(), " rodas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct {
4 lampadas int
5 }
6
7
8
9 type Casa struct {
10 Cozinha
11
12 }
13
14
15
16 func main() {
17 c := Casa{Cozinha{2}}
18 fmt.Println("A casa tem ", c.lampadas , " lampadas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct { $ go run anonymous-field.go
4 lampadas int A casa tem 2 lampadas
5 }
6
7
8
9 type Casa struct {
10 Cozinha
11
12 }
13
14
15
16 func main() {
17 c := Casa{Cozinha{2}}
18 fmt.Println("A casa tem ", c.lampadas , " lampadas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct {
4 lampadas int
5 }
6 type Quarto struct {
7 lampadas int
8 }
9 type Casa struct {
10 Cozinha
11 Quarto
12 }
13
14
15
16 func main() {
17 c := Casa{Cozinha{2}, Quarto{3}}
18 fmt.Println("A casa tem ", c.lampadas , " lampadas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct { $ go run anonymous-field.go
4 lampadas int ambiguous selector c.lampadas
5 }
6 type Quarto struct {
7 lampadas int
8 }
9 type Casa struct {
10 Cozinha
11 Quarto
12 }
13
14
15
16 func main() {
17 c := Casa{Cozinha{2}, Quarto{3}}
18 fmt.Println("A casa tem ", c.lampadas , " lampadas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct {
4 lampadas int
5 }
6 type Quarto struct {
7 lampadas int
8 }
9 type Casa struct {
10 Cozinha
11 Quarto
12 }
13 func (c Casa) lampadas() int {
14 return c.Cozinha.lampadas + c.Quarto.lampadas
15 }
16 func main() {
17 c := Casa{Cozinha{2}, Quarto{3}}
18 fmt.Println("A casa tem ", c.lampadas(), " lampadas")
19 }
Herana (anonymous field)
anonymous-field.go

1 package main
2 import "fmt"
3 type Cozinha struct { $ go run anonymous-field.go
4 lampadas int A casa tem 5 lampadas
5 }
6 type Quarto struct {
7 lampadas int
8 }
9 type Casa struct {
10 Cozinha
11 Quarto
12 }
13 func (c Casa) lampadas() int {
14 return c.Cozinha.lampadas + c.Quarto.lampadas
15 }
16 func main() {
17 c := Casa{Cozinha{2}, Quarto{3}}
18 fmt.Println("A casa tem ", c.lampadas(), " lampadas")
19 }
Go

Tratando Erros

http://blog.golang.org/error-handling-and-go
Tratamento de Erros
Estados inconsistentes ou anormais so indicados atravs
do error. Por exemplo a funo os.Open

Assinatura da funo:
func Open(name string) (file *File, err error)

Exemplo de uso com tratamento de erro:


f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
// faa algo com o arquivo f
Representao do erro
Todo erro em Go representado pela interface error
type error interface {
Error() string
}

A implementao mais comum a errorString.


type errorString struct {
s string
}

func (e *errorString) Error() string {


return e.s
}
Disparando um errorString
A forma mais simples de criar um errorString a partir
da funo errors.New
func New(text string) error {
return &errorString{text}
}

Usando a funo para disparar um erro:


func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("negative number")
}
// implementao caso f >= 0
}
Disparando um errorString
A forma mais simples de criar um errorString a partir
da funo errors.New
func New(text string) error {
return &errorString{text}
}

Usando a funo para disparar um erro:


func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("negative number")
}
// implementao caso f >= 0
}

No estamos informando qual o nmero passado para a


funo. Informao muito importante sendo perdida!
Disparando erros com Errorf
De forma similar como disparamos um errorString
atravs da funo errors.New

... podemos usar a funo Errorf do pacote fmt para


disparar erros mais completos.

Internamente a funo Errorf se utiliza da funo


errors.New

if f < 0 {
return 0, fmt.Errof("negative number %g", f)
}
Customizando seus erros
possvel criar suas prprias implementaes de erros.

Como por exemplo deste caso do nmero negativo,


poderamos por exemplo:

type NegativeSqrtError float64

func (f NegativeSqrtError) Error() string {


return fmt.Sprintf("negative number %g",
float64(f))
}

Esta uma abordagem muito mais sofisticada do que usar


apenas errorString pois permite type assertions.
tratamento de erros importante!

As convenes e design da linguagem nos encorajam a


verificar explicitamente por erros onde eles possam ocorrer
indo em desencontro com muitas outras linguagens.

Em alguns casos, isto pode fazer Go um tanto verbosa,


mas felizmente existem tcnicas para lidar com isso.
Concorrncia & Paralelismo
Concorrncia & Paralelismo

O mundo moderno paralelo

Multicore
Networks
Cloud Computing
Grande quantidade de usurios.
Go suporta concorrncia

execuo concorrente (goroutines)


sincronizao e mensagens (channels)
controle concorrente (select)
Concorrncia legal !
Uhu paralelismo !

Isso uma falacia!

Quando o Go anunciou, muitos ficaram


confusos com a distino
Concorrncia versus Paralelismo
A concorrncia sobre como lidar com um monte de
coisas ao mesmo tempo.

O paralelismo sobre fazer muitas coisas ao mesmo


tempo.

A concorrncia sobre a estrutura, o paralelismo


sobre a execuo.

Concorrncia fornece uma maneira de estruturar uma


soluo para resolver um problema que pode (mas no
necessariamente) ser paralelizvel.
Concorrncia versus Paralelismo

Com apenas um Gopher isso vai levar muito tempo


Concorrncia versus Paralelismo

Mais Gopher no so suficientes


Eles precisam de mais carrinhos
Concorrncia versus Paralelismo

Vai ir mais rpido, mas haver gargalos na pilha e no


incinerador
Precisa sincronizar os Gophers
Comunicao entre os esquilos sera necessria
Concorrncia versus Paralelismo

Remover os gargalos torna realmente independente


Vai consumir duas vezes mais rpido
Concorrncia de dois processos Gopher
Concorrncia versus Paralelismo

Trs Gophers em ao, mas com atrasos provveis


Cada Gopher um processo independente, acrescido de
coordenao (comunicao)
Concorrncia versus Paralelismo

Quatro Gophers em ao, cada com uma tarefa simples


Quatro vezes mais rpido que a verso original com um
Concorrncia versus Paralelismo

Procedimentos concorrentes

Para cada Gopher um procedimento distinto:


Carregar o carrinho com livros
Mover o carrinho para incinerador
Descarregar o carrinho no incinerador
Retornar o carrinho vazio

Diferentes designs concorrentes permitem diferentes


formas de paralelizar
Concorrncia versus Paralelismo

Mais paralelismo
Oito Gophers totalmente ocupados
Concorrncia versus Paralelismo

Mesmo que apenas um Gopher esteja ativo (sem


paralelismo), ainda uma soluo correta e concorrente
Concorrncia versus Paralelismo

Outra maneira: Composio simultnea de procedimentos


Dois procedimentos e uma pilha de preparo
Concorrncia versus Paralelismo

Executar mais procedimentos concorrentes para obter


mais throughput
Concorrncia versus Paralelismo

Utilizando a pilha no modelo multi gopher


Concorrncia versus Paralelismo

Otimizao total
Usando todas as tcnicas, dezesseis Gopher esto
trabalhando
Concorrncia versus Paralelismo

H muitas maneiras de dividir o processamento

Isso design concorrente

Uma vez que temos a diviso, a paralelizao fica mais


fcil
Goroutines

uma funo que executa no mesmo


endereo de outras goroutines

Como uma chamada de funo no shell com &


Goroutines
goroutines.go
1 package main
2
3 import (
$ go run goroutines.go
4 "fmt"
5 "time" hello
6 ) world
7 hello
8 func say(s string) { world
9 for i := 0; i < 5; i++ { hello
10 time.Sleep(100 * world
11 time.Millisecond) hello
12 fmt.Println(s) world
13 }
world
14 }
15
hello
16 func main() {
17 go say("world")
18 say("hello")
19 }
Goroutines no so threads
Apesar de serem parecidas com threads, elas
so muito mais baratas

Goroutines so multiplexados em threads no S.O.


conforme necessrio

Quando uma goroutine fica bloqueada, aquela thread


fica bloqueada, mas no impacta em nenhuma outra
goroutine
Channels
Channels so canais que conectam goroutines
concorrentes. Voc pode enviar valores para os
canais de uma goroutine e receber esses valores em
outra goroutine

Cria um novo canal com make(chan tipo-val)

A sintaxe <- server para enviar ou receber


mensagens
Channels
channels.go
1 package main
2 import "fmt"
3
4 func sum(a []int, c chan int) {
5 sum := 0
6 for _, v := range a { $ go run channels.go
7 sum += v 17 -5 12
8 }
9 c <- sum // send sum to c
10 }
11 func main() {
12 a := []int{7, 2, 8, -9, 4, 0}
13
14 c := make(chan int)
15 go sum(a[:len(a)/2], c)
16 go sum(a[len(a)/2:], c)
17 x, y := <-c, <-c // receive from c
18 fmt.Println(x, y, x+y)
19 }
Channels
c := make (chan int)

http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html
Buffered Channels
Por padro canais so no buferizados. S aceitaro
envios se houver um receptor pronto para receber o
valor

Canais buferizados aceitam um nmero limitado de


valores sem um receptor correspondente para esses
valores
Buffered Channels
buffered-channels.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 mensagens := make(chan string, 2)
7
8 mensagens <- "buferizado"
9 mensagens <- "canal"
10
11 fmt.Println(<-mensagens)
12 fmt.Println(<-mensagens)
13 }
$ go run buffered-channels.go
buferizado
canal
Buffered Channels
c := make (chan int, 10)

http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html
Concorrncia em Go
Para executar uma goroutine: go

Para enviar ou receber informaes entre goroutines:


channels

Use a varivel de ambiente GOMAXPROCS para


definir a quantidade de threads
Go Runtime
Go Runtime
Um pacote como qualquer outro em Go.
implementado em GO, C e Assembly
empacotado junto com o programa no
momento do build
Responsvel pelo:
Gerencimento de mmria
Criao das GO Routines
Comunicao entre channels

https://www.quora.com/How-does-the-Go-runtime-work
http://www.cs.columbia.edu/~aho/cs6998/reports/12-12-11_DeshpandeSponslerWeiss_GO.pdf
http://blog.altoros.com/golang-internals-part-5-runtime-bootstrap-process.html
Go Runtime
S isso ou tem mais?
Pointer
Struct
Matrix
Slice
Range
Map
Value function
Closures
Method
Interface
Stringer
Error

e muito mais!!!

http://go-tour-br.appspot.com
Servidor Web
Um servidor web com menos de 15 lines!!

$ go run http.go
Now you are ready to

!
Perguntas?
Obrigado!

David Robert
davidrobert@gmail.com
Bibliografia
http://golang.org
http://go-tour-br.appspot.com/
https://tour.golang.org
http://www.golangbr.org/
https://vimeo.com/49718712
http://talks.golang.org/2012/waza.slide
http://gophercon.com
http://www.infoq.com/br/news/2014/09/go-1-3
http://www.casadocodigo.com.br/products/livro-google-go
http://www.grokpodcast.com/series/a-linguagem-go/
https://pt.wikipedia.org/wiki/Go_(linguagem_de_programao)
https://gobyexample.com
http://goporexemplo.golangbr.org/
http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html
http://www.goinggo.net/2013/09/detecting-race-conditions-with-go.html
http://golangtutorials.blogspot.com.br/2011/06/inheritance-and-subclassing-in-go-or.html
http://golangtutorials.blogspot.com.br/2011/06/anonymous-fields-in-structs-like-object.html
http://commandcenter.blogspot.ca/2012/06/less-is-exponentially-more.html
http://www.toptal.com/go/go-programming-a-step-by-step-introductory-tutorial
http://www.slideshare.net/while42/programando-em-Go
Estamos contratando
jobs@elo7.com