Programando em Go

Preview:

Citation preview

David Robertdavidrobert@gmail.com

Programando em Go

Go é uma linguagem de programação open source que faz com que seja fácil construir software simples,

confiável, e eficiente https://golang.org

tem grandes, grandes problemas!

Quais (grandes) problemas?

❏ Tanto hardware quanto software são gigantes❏ Milhões de linhas de código❏ Servidores principalmente em C++ e uma grande

quantidade em Java e Python❏ Milhares de desenvolvedores trabalhando ❏ Softwares sendo executado em zilhões de maquinas❏ Sistemas distribuídos em larga escala

Software em larga escala

❏ Builds lentos ❏ Dependências não controladas ❏ Custo de updates ❏ Dificuldade para automatizar tarefas ❏ Builds entre várias linguagens de programação❏ Código difícil 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

Muitas pessoas ajudam a transformar o

protótipo em realidade

Go se tornou um projeto Open

Source

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

2008 2009 20102007

Começa a ter adoção por outros desenvolvedores

Iniciado e desenvolvido por Robert Griesemer,

Rob Pike e Ken Thompson em um projeto part-time

História

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

2008 2009 20102007

História

Programming Language Hall of Fame

Google Trends "golang"

❏ Eliminar lentidão❏ Melhorar a eficacia❏ Aumentar a produtividade ❏ Manutenção escalável

Go foi projetado para que pessoas possam escrever, ler, debugar e manter grandes sistemas de software.

O proposito do Go não é ser uma pesquisa sobre design de linguagens de programação.

O objetivo do Go é fazer com que os programadores vivam melhor.

Por que usar Go?

Performance

http://benchmarksgame.alioth.debian.org

fix, fmt, get, install, list, tool, version, vet.

build compila pacotes e dependencias

run compila e executa programas Go

clean remove arquivos objeto

env imprime informações do ambiente

test testa pacotes e benchmarks

Go contém um conjunto de ferramentas para gerir código fonte...

Principais ferramentas:

Outras ferramentas:

Mas quem usa Go ?

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

❏ Compilado❏ Memoria gerenciada (garbage-collected)❏ Tem seu próprio runtime❏ Sintaxe simples❏ Excelente biblioteca padrão❏ Multi plataforma❏ Orientação a Objetos❏ Estaticamente e fortemente tipado❏ Concorrência (goroutines)❏ Dependências explicitas❏ Retorno multi valorado❏ Ponteirose mais...

O que você vai ver em Go

Estas características não foram implementadas em favor da

eficiência e simplicidade

❏ Tratamento de exceções❏ Herança❏ Generics❏ Assert❏ Sobrecarga de métodos

O que você não vai ver em Go

um pouco de código!

Pacotes

❏ Todo programa Go é composto por pacotes❏ Programas começam com o pacote main❏ Este exemplo usa os pacotes ftm e math

$ go run packages.goMy favorite number is 1

❏ A instrução var declara uma lista de variavéis❏ O tipo é informado no fim❏ A instrução var pode incluir inicialização, 1 por variavél. Neste

caso, o tipo pode ser omitido porque será inferido

Variavéis

$ go run variables.go0 false false false

$ go run variables-with-initiali1 2 true false no!

❏ Dentro de uma função, pode ser usada a instrução := para inicializar e declarar a variavél

Declaração de Variáveis

$ go run short-variable-declarations.go1 2 3 true false no!

$ go run constants.goHello world! Happy 3.14 Day! Go rules? true

❏ Constantes são declaradas com a keyword const❏ Não é possível usar :=

Constantes

Funções❏ Funções podem ter argumentos❏ O tipo fica após o nome do argumento

$ go run functions.go55

❏ Uma função pode ter múltiplos retornos

Retorno de valores múltiplos

$ go run multiple-results.goworld hello

❏ A única estrutura do laço que o Go tem é for❏ Muito similar com Java ou C, exceto pelos ( )❏ A parte inicial e final da declaração podem estar vazias

Laço For

$ go run for.go45

$ go run for-continu1024

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

❏ Ponto e vírgula pode ser removidos para simular um while ❏ for pode executar para "sempre"

Laço while

$ go run forever.goprocess took too long

❏ Muito similar com Java ou C, exceto pelos ( )

Condicional

$ go run if.go1.4142135623730951 2i

$ go run switch.goGo runs on nacl.

❏ Muito similar com Java ou C, exceto pelos ( )

Switch

$ go run defer.gohello world

Defer❏ A declaração defer adia a execução de uma função até o final do

retorno da função❏ Os argumentos das chamadas adiadas são avaliados imediatamente

Orientação a Objetos

Orientação a Objetos

type retangulo struct { largura, altura int}

Estruturas do Go (similares a classes)

Orientação a Objetos

type retangulo struct { largura, altura int}

Go suporta métodos definidos em tipos struct

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

Estruturas do Go (similares a classes)

Orientação a Objetos

type retangulo struct { largura, altura int}

Go suporta métodos definidos em tipos struct

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

Estruturas do Go (similares a classes)

retangulo{10, 20}retangulo{largura: 10, altura: 20}

Inicialização de estruturas

Orientação a Objetos

package vingadores

type vingador struct {nome string

}func NewVingador(nome string) *vingador {

v := new(vingador)v.nome = nomereturn v

}

func main() {capitao := vingadores.NewVingador("Capitão América")fmt.Println(capitao.nome)

}

Construtores

Orientação a Objetos

package vingadores

type vingador struct {nome string

}func NewVingador(nome string) *vingador {

v := new(vingador)v.nome = nomereturn v

}

func main() {capitao := vingadores.NewVingador("Capitão América")fmt.Println(capitao.nome)

}

Construtores ❏ Depois de importar um pacote, você pode consultar os nomes que exporta

❏ Um nome é exportado se começa com uma LETRA MAIÚSCULA

Orientação a Objetosstruct.go

12345678910111213141516171819

package main

import "fmt"

type pessoa struct {nome stringidade int

}

func main() {fmt.Println(pessoa{"Homem de Ferro", 40})fmt.Println(pessoa{nome: "Thor", idade: 100})

s := pessoa{nome: "Hulk", idade: 45}fmt.Println(s.nome)

s.idade = 42fmt.Println(s.idade)

}

Orientação a Objetosstruct.go

12345678910111213141516171819

package main

import "fmt"

type pessoa struct {nome stringidade int

}

func main() {fmt.Println(pessoa{"Homem de Ferro", 40})fmt.Println(pessoa{nome: "Thor", idade: 100})

s := pessoa{nome: "Hulk", idade: 45}fmt.Println(s.nome)

s.idade = 51fmt.Println(s.idade)

}

$ go run struct.go{Homem de Ferro 40}

{Thor 100}

Hulk

42

Orientação a Objetosmethods.go

12345678910111213141516171819

package mainimport "fmt"

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

func (r retangulo) perimetro() int { return 2 * r.largura + 2 * r.altura}func main() { r := retangulo{largura: 10, altura: 5}

fmt.Println("area: ", r.area()) fmt.Println("perim:", r.perimetro())}

Orientação a Objetosmethods.go

12345678910111213141516171819

package mainimport "fmt"

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

func (r retangulo) perimetro() int { return 2 * r.largura + 2 * r.altura}func main() { r := retangulo{largura: 10, altura: 5}

fmt.Println("area: ", r.area()) fmt.Println("perim:", r.perimetro())}

$ go run methods.goarea: 50perim: 30

HERANÇA

HERANÇA

Como assim não tem

herança !?

Por que usamos herança?

Herança

Por que usamos herança?

❏ Reuso de código

Herança

Por que usamos herança?

❏ Reuso de código

Existe efeito colateral em seu uso?

Herança

Por que usamos herança?

❏ Reuso de código

Existe efeito colateral em seu uso?

Acoplamos a implementação da classe mãe muito precocemente. A classe filha precisa

conhecer muito bem o código interno da mãe.

Quebra de encapsulamento

Herança

Alguns críticos afirmam que ela nunca deveria ser utilizada

Herança

Alguns críticos afirmam que ela nunca deveria ser utilizada

Go não tem Herança !

Herança

Alguns críticos afirmam que ela nunca deveria ser utilizada

Go não tem Herança !

Mas tem composição !

Um dos princípios do livro "Design Patterns": Evite herança, favoreça composição

Herança

Herança composition.go

12345678910111213141516171819

package mainimport "fmt"

type Car struct {wheelCount int

}func (car Car) numberOfWheels() int {

return car.wheelCount}type Ferrari struct {

Car //anonymous field Car}

func main() {f := Ferrari{Car{4}}

fmt.Println("A Ferrari tem ", f.numberOfWheels(), " rodas")

}

Herança composition.go

12345678910111213141516171819

package mainimport "fmt"

type Car struct {wheelCount int

}func (car Car) numberOfWheels() int {

return car.wheelCount}type Ferrari struct {

Car //anonymous field Car}

func main() {f := Ferrari{Car{4}}

fmt.Println("A Ferrari tem ", f.numberOfWheels(), " rodas")

}

$ go run composition.goA Ferrari tem 4 rodas

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}

type Casa struct { Cozinha }

func main() { c := Casa{Cozinha{2}} fmt.Println("A casa tem ", c.lampadas , " lampadas") }

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}

type Casa struct { Cozinha }

func main() { c := Casa{Cozinha{2}} fmt.Println("A casa tem ", c.lampadas , " lampadas") }

$ go run anonymous-field.goA casa tem 2 lampadas

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}type Quarto struct { lampadas int}type Casa struct { Cozinha Quarto}

func main() { c := Casa{Cozinha{2}, Quarto{3}} fmt.Println("A casa tem ", c.lampadas , " lampadas") }

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}type Quarto struct { lampadas int}type Casa struct { Cozinha Quarto}

func main() { c := Casa{Cozinha{2}, Quarto{3}} fmt.Println("A casa tem ", c.lampadas , " lampadas") }

$ go run anonymous-field.goambiguous selector c.lampadas

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}type Quarto struct { lampadas int}type Casa struct { Cozinha Quarto}func (c Casa) lampadas() int { return c.Cozinha.lampadas + c.Quarto.lampadas}func main() { c := Casa{Cozinha{2}, Quarto{3}} fmt.Println("A casa tem ", c.lampadas(), " lampadas") }

Herança (anonymous field) anonymous-field.go

12345678910111213141516171819

package mainimport "fmt"type Cozinha struct { lampadas int}type Quarto struct { lampadas int}type Casa struct { Cozinha Quarto}func (c Casa) lampadas() int { return c.Cozinha.lampadas + c.Quarto.lampadas}func main() { c := Casa{Cozinha{2}, Quarto{3}} fmt.Println("A casa tem ", c.lampadas(), " lampadas") }

$ go run anonymous-field.goA casa tem 5 lampadas

Go

Tratando Erros

http://blog.golang.org/error-handling-and-go

Assinatura da função: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)

}

// faça algo com o arquivo f

Estados inconsistentes ou anormais são indicados através do error. Por exemplo a função os.Open

Tratamento de Erros

Todo erro em Go é representado pela interface errortype error interface { Error() string}

A implementação mais comum é a errorString.type errorString struct {

s string}

func (e *errorString) Error() string { return e.s

}

Representação do erro

A forma mais simples de criar um errorString é a partir da função errors.New

func New(text string) error { return &errorString{text}}

Usando a função para disparar um erro:func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("negative number") } // implementaçào caso f >= 0}

Disparando um errorString

Usando a função para disparar um erro:func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("negative number") } // implementaçào caso f >= 0}

A forma mais simples de criar um errorString é a partir da função errors.New

func New(text string) error { return &errorString{text}}

Disparando um errorString

Não estamos informando qual o número passado para a função. Informação muito importante sendo perdida!

De forma similar como disparamos um errorString através da função errors.New ... podemos usar a função Errorf do pacote fmt para disparar erros mais completos.

Internamente a função Errorf se utiliza da função errors.New

Disparando erros com Errorf

if f < 0 { return 0, fmt.Errof("negative number %g", f) }

Esta é uma abordagem muito mais sofisticada do que usar apenas errorString pois permite type assertions.

type NegativeSqrtError float64

func (f NegativeSqrtError) Error() string { return fmt.Sprintf("negative number %g", float64(f))}

É possível criar suas próprias implementações de erros.

Como por exemplo deste caso do número negativo, poderíamos por exemplo:

Customizando seus erros

tratamento de erros é importante!

As convenções 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 técnicas para lidar com isso.

Concorrência & Paralelismo

Concorrência & Paralelismo

O mundo moderno é paralelo

❏ Multicore❏ Networks❏ Cloud Computing❏ Grande quantidade de usuários.

Go suporta concorrência

❏ execução concorrente (goroutines)❏ sincronização e mensagens (channels)❏ controle concorrente (select)

Concorrência é legal !

Uhu paralelismo !

Isso é uma falacia!

Quando o Go anunciou, muitos ficaram confusos com a distinção

❏ A concorrência é sobre como lidar com um monte de coisas ao mesmo tempo.

❏ O paralelismo é sobre fazer muitas coisas ao mesmo tempo.

❏ A concorrência é sobre a estrutura, o paralelismo é sobre a execução.

❏ Concorrência fornece uma maneira de estruturar uma solução para resolver um problema que pode (mas não necessariamente) ser paralelizável.

Concorrência versus Paralelismo

Concorrência versus Paralelismo

❏ Com apenas um Gopher isso vai levar muito tempo

Concorrência versus Paralelismo

❏ Mais Gopher não são suficientes ❏ Eles precisam de mais carrinhos

Concorrência versus Paralelismo

❏ Vai ir mais rápido, mas haverá gargalos na pilha e no incinerador

❏ Precisa sincronizar os Gophers❏ Comunicação entre os esquilos sera necessária

Concorrência versus Paralelismo

❏ Remover os gargalos torna realmente independente❏ Vai consumir duas vezes mais rápido❏ Concorrência de dois processos Gopher

Concorrência versus Paralelismo

❏ Três Gophers em ação, mas com atrasos prováveis❏ Cada Gopher é um processo independente, acrescido de

coordenação (comunicação)

Concorrência versus Paralelismo

❏ Quatro Gophers em ação, cada com uma tarefa simples❏ Quatro vezes mais rápido que a versão original com um

Concorrência 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

Concorrência versus Paralelismo

❏ Mais paralelismo❏ Oito Gophers totalmente ocupados

Concorrência versus Paralelismo

❏ Mesmo que apenas um Gopher esteja ativo (sem paralelismo), ainda é uma solução correta e concorrente

Concorrência versus Paralelismo

❏ Outra maneira: Composição simultânea de procedimentos❏ Dois procedimentos e uma pilha de preparo

Concorrência versus Paralelismo

❏ Executar mais procedimentos concorrentes para obter mais throughput

Concorrência versus Paralelismo

❏ Utilizando a pilha no modelo multi gopher

Concorrência versus Paralelismo

❏ Otimização total❏ Usando todas as técnicas, dezesseis Gopher estão

trabalhando

Concorrência versus Paralelismo

❏ Há muitas maneiras de dividir o processamento

❏ Isso é design concorrente

❏ Uma vez que temos a divisão, a paralelização fica mais fácil

É uma função que executa no mesmo endereço de outras goroutines

❏ Como uma chamada de função no shell com &

Goroutines

Goroutinesgoroutines.go

12345678910111213141516171819

package main

import ("fmt""time"

)

func say(s string) {for i := 0; i < 5; i++ {

time.Sleep(100 * time.Millisecond)

fmt.Println(s)}

}

func main() {go say("world")say("hello")

}

$ go run goroutines.gohelloworldhelloworldhelloworldhelloworldworldhello

Apesar de serem parecidas com threads, elas são muito mais baratas

❏ Goroutines são multiplexados em threads no S.O. conforme necessário

❏ Quando uma goroutine fica bloqueada, aquela thread fica bloqueada, mas não impacta em nenhuma outra goroutine

Goroutines não são threads

❏ Channels são 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

Channelschannels.go

12345678910111213141516171819

package mainimport "fmt"

func sum(a []int, c chan int) {sum := 0for _, v := range a {

sum += v}c <- sum // send sum to c

}func main() {

a := []int{7, 2, 8, -9, 4, 0}

c := make(chan int)go sum(a[:len(a)/2], c)go sum(a[len(a)/2:], c)x, y := <-c, <-c // receive from cfmt.Println(x, y, x+y)

}

$ go run channels.go17 -5 12

http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html

c := make (chan int)

Channels

❏ Por padrão canais são não buferizados. Só aceitarão envios se houver um receptor pronto para receber o valor

❏ Canais buferizados aceitam um número limitado de valores sem um receptor correspondente para esses valores

Buffered Channels

Buffered Channelsbuffered-channels.go

12345678910111213

package main

import "fmt"

func main() { mensagens := make(chan string, 2) mensagens <- "buferizado" mensagens <- "canal" fmt.Println(<-mensagens) fmt.Println(<-mensagens)}

$ go run buffered-channels.go

buferizado

canal

http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html

c := make (chan int, 10)

Buffered Channels

❏ Para executar uma goroutine: go

❏ Para enviar ou receber informações entre goroutines: channels

❏ Use a variável de ambiente GOMAXPROCS para definir a quantidade de threads

Concorrência em Go

Go Runtime

https://www.quora.com/How-does-the-Go-runtime-workhttp://www.cs.columbia.edu/~aho/cs6998/reports/12-12-11_DeshpandeSponslerWeiss_GO.pdfhttp://blog.altoros.com/golang-internals-part-5-runtime-bootstrap-process.html

❏ Um pacote como qualquer outro em Go.

❏ É implementado em GO, C e Assembly

❏ É empacotado junto com o programa no momento do build

❏ Responsável pelo:❏ Gerencimento de mémória❏ Criação das GO Routines❏ Comunicação entre channels

Go Runtime

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

$ go run http.go

Servidor Web❏ Um servidor web com menos de 15 lines!!

Now you are ready to

!

Perguntas?

Obrigado!

David Robertdavidrobert@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_programação)❏ 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