Go! – Ferramentas – Pacotes



Go! – Ferramentas – Pacotes

0 0


minicurso-go

Minicurso de Go

On Github nubunto / minicurso-go

Go!

Go é uma linguagem de programação garbage-collected de tipagem estática, compilada e concorrente. Foi desenvolvida pelo Google e liberada ao mundo open source em 2007.

Para alguns, Go é uma linguagem rápida, divertida e produtiva.

Porque Go?

The goals of the Go project were to eliminate the slowness and clumsiness of software development at Google, and thereby to make the process more productive and scalable. The language was designed by and for people who write—and read and debug and maintain—large software systems.

Alguns motivos

Simplicidade

Simplicidade

Simplicidade!

Go não é "The Ultimate Programming Language", nasceu com um objetivo: fazer longas bases de código mais simples e programadores mais produtivos. Pra isso, sacrifica algumas coisas.
“Less is exponentially more.” - Rob Pike, um dos criadores da linguagem.

Quem usa Go?

Google YouTube Docker Globo.com BBC Worldwide Bitbucket Bit.ly Canonical Digital Ocean eBay Facebook GitHub Heroku MongoDB Netflix SendGrid SoundCloud SpaceX StackExchange Twitter Hotel Urbano Badoo A China ... e a lista continua.

Ferramentas

go fmt

Formata todo o código de um pacote com as convenções da linguagem. Não há brigas sobre espaços + tabs, tabs com tamanho 2 ou 4, e etc.

go doc

Pesquisa rápida de documentação, sem necessidade de internet.

go build

Compila código Go para um executável. Aliás, Go suporta cross compilation. Desenvolva e compile para qualquer arquitetura/SO suportada. ARM 32 bits, Linux/Mac 32 e 64 bits, Windows 32 e 64 bits, FreeBSD, etc.
E alguns outros: go tour, go lint, go vet, go imports, etc.

Código Go, como se parece?

package main

import "fmt"

func main() {
    fmt.Println("Hello, from Go!")
}

O quão difícil é desenvolver para a web?

package main

import (
    "fmt"
    "net/http"
)

func main() {
    // registra um código que roda ao ser feito um request na raiz ("/")
    http.HandleFunc("/", meuHandler)
    http.ListenAndServe(":8080", nil)
}

// a função recebe como parametro um ResponseWriter (que é usado para escrever na resposta para o cliente)
// e um ponteiro (sim, um ponteiro) para um Request (que é usado para se obter informações sobre quem se conectou)
// a função Fprintf (sim, igual a de C) escreve em um Writer (no caso, ResponseWriter) a string "Olá, mundo!"
func meuHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Olá, mundo!")
}
                
Aponte um browser para http://localhost:8080 e veja a mensagem "Olá, mundo!"

Mas, cadê o IIS?

(:

Fora da caixa, a performance de Go é invejável: 10 mil conexões concorrentes em um servidor modesto. E sem um XML à vista. Não acredita? Veja você mesmo.

Deploy de programas Go

Ao rodar o comando "go build", é compilado um binário estático. Todas as dependências são enfiadas em um único arquivo. Deixe este arquivo no servidor, e está feito o deploy. Rollback? Volte a versão antiga do binário. Não há como evitar a falta de backups... A maioria dos frameworks de Continuous Integration aceitam código Go.

Testes Unitários

A própria distribuição de Go vem com uma ferramenta de teste e benchmarks, para garantir o grau de certeza do código e também uma ideia geral de quão bem ele vai rodar. É divertido e simples de fazer.

Se aprofundando na linguagem

Pacotes

    package main
                    
para executáveis, ou
    package qualquercoisa
                    
para libraries. Explicar as diferenças entre "package main" e "package foo"

Pacotes

Caso o programa esteja no pacote "main", uma função "main" deverá existir.
package main

func main() {
    // função que roda ao se executar o binário
}
                    

Imports

Usando a palavra chave "import", conseguimos importar pacotes:
package main

import (
    "fmt" // pacote da biblioteca padrão
)
                

Nomes exportados

Dentro de um pacote, nomes que começam com a letra maiúscula são exportados. Nomes que começam com letra minúscula são privados.
// foo/foo.go
package foo

var AInteger int = 1
var anotherInteger int = 2

// main.go
package main

import (
    "meupacote/foo"
    "fmt"
)

func main() {
    fmt.Println(foo.AInteger) // "1"
    fmt.Println(foo.anotherInteger) // erro
}
                

Declaração de tipos

O tipo vem depois do nome:
var a int
var b string
a = 1
b = "2"

var c float64 = 5.4
var numeroComplexoOdiadoNoEnsinoMedio complex128 = 2 + 5i // sim, números complexos nativos!

// pra funções também
func Soma(a int, b int) int {
    return a + b
}

// se você inicializar a variável na declaração, pode omitir o tipo
var myVar = "this is a var."
                    

Variáveis

Variáveis podem ser declaradas com seu valor zerado (nunca vai encontrar lixo do SO na variável):
var a int
fmt.Println(a) // 0
                    

Variáveis

Variáveis podem ter seu tipo inferido pelo compilador:
var a = 1
fmt.Println(a) // 1

func swap(a, b int) (int, int) {
    return b, a
}

                    

Variáveis

Variáveis podem ser declaradas e setadas de forma concisa:
a, b := "foobar", 2
fmt.Println(a, b) // foobar 2
                    

Controles de fluxo

If, For, Defer

If

Parecido com o If de C/Java/C#/JavaScript, mas não existem parênteses:
if b >= 1 {
    a = b - 5
} else if b < 0 {
    a = b + 10
}
                    

If

O If pode ter um inicializador antes de ser executado:
if _, erro := arquivo.Read(conteudo); erro != nil {
    fmt.Println("Erro ao ler arquivo:", erro)
}
                    

For

Igual ao de C/Java/C#/JavaScript, mas sem parênteses:
for i := 0; i < 10; i++ {
    fmt.Println("i:", i)
}
                    

Defer

Ah, o Defer. Defer é um comando de fluxo de controle. Ele denota uma chamada de função que só irá rodar quando a função na qual está definido terminar seu processamento.
Exemplo: abrir um arquivo para leitura
arquivo, _ := os.OpenFile("meu_arquivo.txt")
// ... fazendo coisas com o arquivo, e no final da função
arquivo.Close()
                    
Fácil de esquecer o "arquivo.Close()" ali no final da função, especialmente se ela for longa.
Conheça o defer:
arquivo, err := os.OpenFile("meu_arquivo.txt")
if err != nil {
    // cuidar do erro
}
defer arquivo.Close()
                    
Quando esta função terminar, o Close() do arquivo será chamado automaticamente. O comando também empilha as funções, e as chama em ordem LIFO (Last In, First Out).

Funções

Funções são... bem, funções.
func HelloWorld() string {
    return "hello, world"
}
fmt.Println(HelloWorld())
                    

São valores

Funções são valores como todas as variáveis. Podem ser passadas, declaradas, atribuídas, etc.
fn := func(a int) float64 {
    return a * 2.0
}
fmt.Println(fn(5)) // 10.0
                    

Tipos

Você pode declarar novos tipos. Pense no "typedef" de C, porém ele cria um tipo realmente novo.
type Foo int

var f Foo = Foo(5) // type cast de 5 para o tipo Foo
fmt.Println(f) // 5

                    
Veremos o quanto isto é útil mais pra frente.

Structs

Structs são tipos que agregam diferentes conteúdos.
type Usuario struct {
    Nome string
    Idade int
}

meuUsuario := Usuario{
    Nome: "Foo",
    Idade: 26,
}
fmt.Println(meuUsuario) // {Foo, 26}
                    

Tipos em structs

Podemos colocar funções em tipos. Pense neles como métodos do objeto.
// considere o Usuario do ultimo slide.
func (u Usuario) PrintarNome() {
    fmt.Println("Meu nome é", u.Nome, ". Prazer em conhecê-lo.")
}

meuUsuario := Usuario{
    Nome: "Marcos"
}
meuUsuario.PrintarNome() // printa na tela: "Meu nome é Marcos. Prazer em conhecê-lo."
                    

Mão na massa

Agora, iremos juntos desenvolver uma simples Wiki. Outros conceitos serão explicados enquanto desenvolvemos a aplicação. Mas por enquanto, é tudo que precisamos saber. Divirtam-se!
Go!