Programando em Go

1.277 visualizações

Publicada em

Uma visão geral da linguagem de programação Go

Publicada em: Tecnologia

Programando em Go

  1. 1. David Robert davidrobert@gmail.com Programando em Go
  2. 2. David Robert davidrobert@gmail.com linkedin.com/in/davidrobert
  3. 3. 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
  4. 4. tem grandes, grandes problemas!
  5. 5. 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
  6. 6. 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
  7. 7. No geral, o desenvolvimento no é grande, lento, e muitas vezes desajeitado. Mas é efetivo '' '' https://talks.golang.org/2012/splash.article
  8. 8. ❏ Ken Thompson (B, C, Unix, UTF-8) ❏ Rob Pike (Unix, UTF-8) ❏ Robert Griesemer (Hotspot, JVM) … e muitos outros engenheiros do Google
  9. 9. 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
  10. 10. http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html 2008 2009 20102007 História Programming Language Hall of Fame
  11. 11. Histórico de Versões Go 1.4 Go 1.3 Go 1 Go 1.2 Go 1.1 https://golang.org/project/ 2013 2014 20152012 Go 1.5
  12. 12. Google Trends "golang"
  13. 13. ❏ 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?
  14. 14. Performance http://benchmarksgame.alioth.debian.org
  15. 15. 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:
  16. 16. Mas quem usa Go ?
  17. 17. https://github.com/golang/go/wiki/GoUsers
  18. 18. ❏ 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 ❏ Ponteiros e mais... O que você vai ver em Go
  19. 19. 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
  20. 20. um pouco de código!
  21. 21. 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.go My favorite number is 1
  22. 22. ❏ 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.go 0 false false false $ go run variables-with-initiali 1 2 true false no!
  23. 23. ❏ 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.go 1 2 3 true false no!
  24. 24. $ go run constants.go Hello world! Happy 3.14 Day! Go rules? true ❏ Constantes são declaradas com a keyword const ❏ Não é possível usar := Constantes
  25. 25. Funções ❏ Funções podem ter argumentos ❏ O tipo fica após o nome do argumento $ go run functions.go 55
  26. 26. ❏ Uma função pode ter múltiplos retornos Retorno de valores múltiplos $ go run multiple-results.go world hello
  27. 27. ❏ 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.go 45 $ go run for-continu 1024
  28. 28. $ go run for-is-go-while.go 1024 ❏ Ponto e vírgula pode ser removidos para simular um while ❏ for pode executar para "sempre" Laço while $ go run forever.go process took too long
  29. 29. ❏ Muito similar com Java ou C, exceto pelos ( ) Condicional $ go run if.go 1.4142135623730951 2i
  30. 30. $ go run switch.go Go runs on nacl. ❏ Muito similar com Java ou C, exceto pelos ( ) Switch
  31. 31. $ go run defer.go hello 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
  32. 32. Orientação a Objetos
  33. 33. Orientação a Objetos type retangulo struct { largura, altura int } Estruturas do Go (similares a classes)
  34. 34. 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)
  35. 35. 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
  36. 36. Orientação a Objetos 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("Capitão América") fmt.Println(capitao.nome) } Construtores
  37. 37. Orientação a Objetos 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("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
  38. 38. Orientação a Objetos struct.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "fmt" type pessoa struct { nome string idade 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 = 42 fmt.Println(s.idade) }
  39. 39. Orientação a Objetos struct.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "fmt" type pessoa struct { nome string idade 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 = 51 fmt.Println(s.idade) } $ go run struct.go {Homem de Ferro 40} {Thor 100} Hulk 42
  40. 40. Orientação a Objetos methods.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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()) }
  41. 41. Orientação a Objetos methods.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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.go area: 50 perim: 30
  42. 42. HERANÇA
  43. 43. HERANÇA Como assim não tem herança !?
  44. 44. Por que usamos herança? Herança
  45. 45. Por que usamos herança? ❏ Reuso de código Herança
  46. 46. Por que usamos herança? ❏ Reuso de código Existe efeito colateral em seu uso? Herança
  47. 47. 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
  48. 48. Alguns críticos afirmam que ela nunca deveria ser utilizada Herança
  49. 49. Alguns críticos afirmam que ela nunca deveria ser utilizada Go não tem Herança ! Herança
  50. 50. 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
  51. 51. Herança composition.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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") }
  52. 52. Herança composition.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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.go A Ferrari tem 4 rodas
  53. 53. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "fmt" type Cozinha struct { lampadas int } type Casa struct { Cozinha } func main() { c := Casa{Cozinha{2}} fmt.Println("A casa tem ", c.lampadas , " lampadas") }
  54. 54. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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.go A casa tem 2 lampadas
  55. 55. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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") }
  56. 56. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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.go ambiguous selector c.lampadas
  57. 57. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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") }
  58. 58. Herança (anonymous field) anonymous-field.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "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.go A casa tem 5 lampadas
  59. 59. Go Tratando Erros http://blog.golang.org/error-handling-and-go
  60. 60. 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
  61. 61. Todo erro em Go é representado pela interface error type 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
  62. 62. 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
  63. 63. 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!
  64. 64. 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) }
  65. 65. 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
  66. 66. 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.
  67. 67. Concorrência & Paralelismo
  68. 68. Concorrência & Paralelismo O mundo moderno é paralelo ❏ Multicore ❏ Networks ❏ Cloud Computing ❏ Grande quantidade de usuários.
  69. 69. Go suporta concorrência ❏ execução concorrente (goroutines) ❏ sincronização e mensagens (channels) ❏ controle concorrente (select)
  70. 70. Concorrência é legal ! Uhu paralelismo ! Isso é uma falacia! Quando o Go anunciou, muitos ficaram confusos com a distinção
  71. 71. ❏ 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
  72. 72. Concorrência versus Paralelismo ❏ Com apenas um Gopher isso vai levar muito tempo
  73. 73. Concorrência versus Paralelismo ❏ Mais Gopher não são suficientes ❏ Eles precisam de mais carrinhos
  74. 74. 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
  75. 75. Concorrência versus Paralelismo ❏ Remover os gargalos torna realmente independente ❏ Vai consumir duas vezes mais rápido ❏ Concorrência de dois processos Gopher
  76. 76. 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)
  77. 77. 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
  78. 78. 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
  79. 79. Concorrência versus Paralelismo ❏ Mais paralelismo ❏ Oito Gophers totalmente ocupados
  80. 80. Concorrência versus Paralelismo ❏ Mesmo que apenas um Gopher esteja ativo (sem paralelismo), ainda é uma solução correta e concorrente
  81. 81. Concorrência versus Paralelismo ❏ Outra maneira: Composição simultânea de procedimentos ❏ Dois procedimentos e uma pilha de preparo
  82. 82. Concorrência versus Paralelismo ❏ Executar mais procedimentos concorrentes para obter mais throughput
  83. 83. Concorrência versus Paralelismo ❏ Utilizando a pilha no modelo multi gopher
  84. 84. Concorrência versus Paralelismo ❏ Otimização total ❏ Usando todas as técnicas, dezesseis Gopher estão trabalhando
  85. 85. 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
  86. 86. É uma função que executa no mesmo endereço de outras goroutines ❏ Como uma chamada de função no shell com & Goroutines
  87. 87. Goroutines goroutines.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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.go hello world hello world hello world hello world world hello
  88. 88. 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
  89. 89. ❏ 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
  90. 90. Channels channels.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package main import "fmt" func sum(a []int, c chan int) { sum := 0 for _, 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 c fmt.Println(x, y, x+y) } $ go run channels.go 17 -5 12
  91. 91. http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html c := make (chan int) Channels
  92. 92. ❏ 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
  93. 93. Buffered Channels buffered-channels.go 1 2 3 4 5 6 7 8 9 10 11 12 13 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
  94. 94. http://www.goinggo.net/2014/02/the-nature-of-channels-in-go.html c := make (chan int, 10) Buffered Channels
  95. 95. ❏ 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
  96. 96. Go Runtime
  97. 97. 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 ❏ 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
  98. 98. Go Runtime
  99. 99. 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
  100. 100. $ go run http.go Servidor Web ❏ Um servidor web com menos de 15 lines!!
  101. 101. Now you are ready to !
  102. 102. Perguntas?
  103. 103. Obrigado! David Robert davidrobert@gmail.com
  104. 104. 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
  105. 105. Estamos contratando jobs@elo7.com

×