Execute Formate

Como escrever código Go

Introdução

Este documento demonstra o desenvolvimento de um pacote Go simples e apresenta a ferramenta go, a maneira padrão de buscar, construir e instalar pacotes Go e comandos.

A ferramenta go exige que você organize seu código de uma maneira específica. Por favor, leia este documento cuidadosamente. Ele explica a maneira mais simples de se organizar e rodar com a sua instalação Go.

Uma explicação semelhante está disponível como screencast.

Organização do código

Áreas de trabalho

A ferramenta go é projetado para trabalhar com o código fonte aberto mantido em repositórios públicos. Embora você não precise publicar o seu código, o modelo de como o ambiente está configurado funciona da mesma forma se você fize-lo ou não.

Código Go deve ser mantido dentro de uma área de trabalho. Uma área de trabalho é uma hierarquia de diretórios com três diretórios em sua raiz:

A ferramenta go constrói pacotes fonte e instala os binários resultantes nos diretórios pkg e bin.

O subdiretório src normalmente contém vários repositórios de controle de versão (como Git e Mercurial) que acompanham o desenvolvimento de um ou mais pacotes fonte.

Para lhe dar uma idéia de como uma área de trabalho parece na prática, aqui está um exemplo:

bin/
    streak                         # comando executável
    todo                           # comando executável
pkg/
    linux_amd64/
        code.google.com/p/goauth2/
            oauth.a                # objeto do pacote
        github.com/nf/todo/
            task.a                 # objeto do pacote
src/
    code.google.com/p/goauth2/
        .hg/                       # metadados do repositório mercurial
        oauth/
            oauth.go               # código do pacote
            oauth_test.go          # código do teste
    github.com/nf/
        streak/
            .git/                  # metadados do repositório git
            oauth.go               # código do comando
            streak.go              # código do comando
        todo/
            .git/                  # metadados do repositório git
            task/
                task.go            # código do pacote
            todo.go                # código do comando

Esta área de trabalho contém três repositórios (goauth2, streak, e todo) que compreendem dois comandos (streak e todo) e duas bibliotecas (oauth e task).

Executáveis e bibliotecas são construídos a partir de diferentes tipos de fontes de pacotes. Vamos discutir a distinção mais tarde.

A variável de ambiente GOPATH

A variável de ambiente GOPATH especifica a localização do sua área de trabalho. É provável que seja a única variável de ambiente que você precise definir quando desenvolver código Go.

Para começar, crie um diretório de trabalho e defina GOPATH respectivamente. Seu espaço de trabalho pode ser localizado onde você quiser, mas vamos usar $HOME/go neste documento. Note-se que este não deve ser o mesmo caminho da sua instalação Go.

$ mkdir $HOME/go
$ export GOPATH=$HOME/go

Para maior comodidade, adicione o subdiretório bin da área de trabalho ao seu PATH:

$ export PATH=$PATH:$GOPATH/bin

Caminho dos pacotes

Os pacotes da biblioteca padrão são caminhos curtos, como "fmt" e "net/http". Para seus próprios pacotes, você deve escolher um caminho base que é improvável a colidir com futuras adições à biblioteca padrão ou outras bibliotecas externas.

Se você manter o seu código em um repositório de origem em algum lugar, então você deve usar a raiz do que repositório de origem como o seu caminho base. Por exemplo, se você tiver uma conta no GitHub, github.com/user deverá ser o seu caminho base.

Note que você não precisa publicar o seu código para um repositório remoto para que você possa construir. É apenas um bom hábito de organizar seu código como se você fosse publicá-lo um dia. Na prática, você pode escolher qualquer nome do caminho arbitrário, contanto que ele seja exclusivo para a biblioteca padrão e demais ecossistema Go.

Usaremos github.com/user como o nosso caminho base. Crie um diretório dentro da sua área de trabalho para manter o código-fonte:

$ mkdir -p $GOPATH/src/github.com/user

Seu primeiro programa

Para compilar e executar um programa simples, em primeiro lugar escolha o caminho do pacote (vamos usar github.com/user/ola) e crie o diretório do pacote correspondente dentro de sua área de trabalho:

$ mkdir $GOPATH/src/github.com/user/ola

Em seguida, crie um arquivo chamado ola.go dentro desse diretório, contendo o seguinte código Go.

package main

import "fmt"

func main() {
	fmt.Printf("Olá, mundo.\n")
}

Agora você pode construir e instalar o programa com a ferramenta go:

$ go install github.com/user/ola

Note que você pode executar este comando a partir de qualquer lugar em seu sistema. A ferramenta go encontrará o código-fonte, olhando para github.com/user/ola pacote dentro da área de trabalho especificado pelo GOPATH.

Você também pode omitir o caminho do pacote, se você rodar go install no diretório do pacote:

$ cd $GOPATH/src/github.com/user/ola
$ go install

Este comando cria o comando ola, produzindo um binário executável. Em seguida, instala esse binário no diretório bin da área de trabalho como ola (ou ola.exe no Windows). No nosso exemplo, que será $GOPATH/bin/ola, que é $HOME/go/bin/ola.

A ferramenta go só vai imprimir a saída quando ocorre um erro, por isso, se estes comandos não produzem nenhuma saída é que foram executados com sucesso.

Agora você pode executar o programa digitando o caminho completo na linha de comando:

$ $GOPATH/bin/ola
Olá, mundo.

Ou, como você adicionou $GOPATH/bin ao seu PATH, basta digitar o nome binário:

$ ola
Olá, mundo.

Se você estiver usando um sistema de controle de versão, agora seria um bom momento para inicializar um repositório, adicionar os arquivos, e salvar a sua primeira mudança. Mais uma vez, este passo é opcional: você não precisa usar o controle de fonte para escrever código Go.

$ cd $GOPATH/src/github.com/user/ola
$ git init
Initialized empty Git repository in /home/user/go/src/github.com/user/ola/.git/
$ git add ola.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 1 insertion(+)
  create mode 100644 ola.go

Subir o código para um repositório remoto fica como um exercício para o leitor.

Sua primeira biblioteca

Vamos escrever uma biblioteca e usá-la a partir do programa ola.

Mais uma vez, o primeiro passo é escolher um caminho de pacote (vamos usar github.com/user/newmath) e criar o diretório do pacote:

$ mkdir $GOPATH/src/github.com/user/newmath

Em seguida, crie um arquivo chamado sqrt.go nesse diretório com o seguinte conteúdo.

// Pacote newmath é um exemplo tricial de pacote.
package newmath

// Sqrt retorna uma aproximação da raiz quadrada de x.
func Sqrt(x float64) float64 {
	z := 1.0
	for i := 0; i < 1000; i++ {
		z -= (z*z - x) / (2 * z)
	}
	return z
}

Agora, teste se este pacote compila com go build:

$ go build github.com/user/newmath

Ou, se você se você estiver trabalhando no diretório fonte do pacote, apenas:

$ go build

Isso não vai produzir um arquivo de saída. Para fazer isso, você deve usar go install, que coloca o objeto do pacote dentro do diretório pkg da área de trabalho.

Após a confirmação de que o pacote newmath compila, modifique seu ola.go original (que está em $GOPATH/src/github.com/user/ola) para usá-lo:

package main

import (
	"fmt"

	"github.com/user/newmath"
)

func main() {
	fmt.Printf("Olá, mundo.  Sqrt(2) = %v\n", newmath.Sqrt(2))
}

Sempre que a ferramenta go instala um pacote ou binário, ele também instala quaisquer dependências que tenha. Então, quando você instalar o programa ola.

$ go install github.com/user/ola

O pacote newmath será instalado, automaticamente.

Executando a nova versão do programa você deve ver alguma saída numérica:

$ ola
Olá, mundo.  Sqrt(2) = 1.414213562373095

Após os passos acima, sua área de trabalho deve ficar assim:

bin/
    ola                # comando executável
pkg/
    linux_amd64/       # isso dependerá do seu SO e arquitetura
        github.com/user/
            newmath.a  # objeto do pacote
src/
    github.com/user/
        ola/
            ola.go     # código do comando
        newmath/
            sqrt.go    # código do pacote

Note que go install colocou o objeto newmath.a em um diretório dentro pkg/linux_amd64 que espelha o seu diretório de origem. Isso é para que as futuras invocações da ferramenta go possam encontrar o objeto do pacote e evitar recompilar o pacote desnecessariamente. A parte linux_amd64 está lá para ajudar na compilação-cruzada, e vai refletir o sistema operacional e a arquitetura do seu sistema.

Executáveis ​​de comando Go são estaticamente ligados, os objetos do pacote não precisam estar presentes para executar programas Go.

Nomes de pacote

A primeira declaração em um arquivo de origem Go deve ser

package nome

onde nome é o nome padrão do pacote para as importações. (Todos os arquivos em um pacote devem usar o mesmo nome.)

A convenção de Go é que o nome do pacote é o último elemento do caminho de importação: o pacote importado como "crypto/rot13" deve ser nomeado rot13.

Comandos executáveis ​​devem sempre usar o package main.

Não há exigência de que os nomes de pacotes sejam únicos em todos os pacotes ligados em um único binário, só que os caminhos de importação (os nomes completos de arquivos) sejam únicos.

Veja Go Efetivo para aprender mais sobre as convenções de nomenclatura de Go.

Testando

Go tem uma estrutura de teste leve, composta pelo comando go test e o pacote testing.

Você escreve um teste criando um arquivo com um nome terminando em _test.go que contém funções nomeadas TestXXX com assinatura func (t *testing.T). O quadro de teste é executado cada tal função, se a função chama uma função falha, como t.Error ou t.Fail, o teste é considerado falho.

Adicione um teste para o pacote newmath criando o arquivo $GOPATH/src/github.com/user/newmath/sqrt_test.go contendo o seguinte código Go.

package newmath

import "testing"

func TestSqrt(t *testing.T) {
	const in, out = 4, 2
	if x := Sqrt(in); x != out {
		t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
	}
}

Em seguida, execute o teste com o go test:

$ go test github.com/user/newmath
ok  	github.com/user/newmath 0.165s

Como sempre, se você estiver executando a ferramenta go no diretório do pacote, você pode omitir o caminho do pacote:

$ go test
ok  	github.com/user/newmath 0.165s

Executar go help test e ver a documentação do pacote de testes para mais detalhes

Pacotes remotos

Um caminho de importação pode descrever como obter o código-fonte do pacote usando um sistema de controle de revisão, como Git ou Mercurial. A ferramenta go usa essa propriedade para buscar automaticamente os pacotes de repositórios remotos. Por exemplo, os exemplos descritos neste documento, também são mantidos em um repositório Mercurial hospedado no Google Code, code.google.com/p/go.example. Se você incluir o URL do repositório no caminho de importação do pacote, go get vai buscar, construir e instalar automaticamente

$ go get code.google.com/p/go.example/hello
$ $GOPATH/bin/hello
Hello, world.  Sqrt(2) = 1.414213562373095

Se o pacote especificado não está presente em uma área de trabalho, go get irá colocá-lo dentro do primeiro espaço de trabalho especificado pelo GOPATH. (Se o pacote já existir, go get pula a busca remota e se comporta da mesma forma que o go install.)

Depois de emitir o comando go get acima, a árvore de diretórios da área de trabalho deve parecer agora como esta:

bin/
    hello                 # comando executável
pkg/
    linux_amd64/
        code.google.com/p/go.example/
            newmath.a     # objeto do pacote
        github.com/user/
            newmath.a     # objeto do pacote
src/
    code.google.com/p/go.example/
        hello/
            hello.go      # command source
        newmath/
            sqrt.go       # código do pacote
            sqrt_test.go  # código do teste
    github.com/user/
        hello/
            hello.go      # código do comando
        newmath/
            sqrt.go       # código do pacote
            sqrt_test.go  # código do teste

O comando ola hospedado no Google Code depende do pacote newmath dentro do mesmo repositório. As importações no arquivo hello.go usam a mesma convenção de caminho de importação, logo o comando go get é capaz de localizar e instalar o pacote dependente também.

import "code.google.com/p/go.example/newmath"

Esta convenção é a maneira mais fácil de fazer seus pacotes Go disponíveis para outras pessoas usarem. O Wiki Go e godashboard.appspot.com fornecem listas de projetos Go externos.

Para mais informações sobre o uso de repositórios remotos com a ferramenta go, veja go help importpath.

Outras leituras

Veja Go Efetivo para dicas sobre como escrever código Go claro e idiomático.

um passeio por Go para aprender a linguagem adequadamente.

Visite a página de documentação para um conjunto de artigos sobre a linguagem Go e suas bibliotecas e ferramentas.