Esse artigo mostrará como desenvolver um pacote Go simples e introduz o go tool, a maneira padrão de manipular, compilar e instalar comandos e pacotes Go.
Esta ferramenta necessita que você organize seu código de uma maneira específica. Leia este artigo com bastante atenção. Ele explica a maneira mais simples de pôr sua instalação Go em funcionamento.
Organização do código
Visão Geral
- Programadores Go tipicamente mantém seu código Go em um único local.
- Um workspace contém vários repositórios de controle de versão (gerenciados pelo Git, por exemplo).
- Cada repositório contém um ou vários pacote.
- Cada pacote consiste de um ou mais arquivos de código fonte Go em um único diretório.
- O caminho para o diretório de um pacote determina o import path.
Observe que isso tudo é diferente de outros ambientes de programação em que cada projeto possui um workspace separado e workspaces são fortemente associados a repositórios de controle de versão.
Workspaces
Um worlspace é uma hierarquia de diretório com três subdiretórios dentro dele:
- src contém arquivos de código Go,
- pkg contém objectos de pacotes e,
- bin contém arquivos executáveis.
A ferramenta go compila pacotes de código e instala os binários resultantes nos diretórios pkg e bin.
O subdiretório src tipicamente contém múltiplos repositórios (como os do Git ou Mercurial) que rastreiam o desenvolvimento de um ou mais pacotes de código.
Para lhe dar uma ideia de como um workspace se parece na prática, segue um exemplo:
bin/ hello # command executable outyet # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object src/ github.com/golang/example/ .git/ # Git repository metadata hello/ hello.go # command source outyet/ main.go # command source main_test.go # test source stringutil/ reverse.go # package source reverse_test.go # test source golang.org/x/image/ .git/ # Git repository metadata bmp/ reader.go # package source writer.go # package source ... (many more repositories and packages omitted) ...
A estrutura acima mostra um workspace que contém dois repositórios (example e image). O diretório exemple contém dois comandos(hello e outyet) e uma biblioteca (stringutil). O repositório image contém o pacote bmp e diversos outros.
Um workspace típico contém múltiplos repositórios de código contendo múltiplos comandos e pacotes. Muitos programadores Go mantém todo o seu código Go e as respectivas dependências em um único workspace.
Comandos e bibliotecas são compilados a partir de diferentes pacotes de código. Discutiremos isso mais à frente.
A variável de ambiente GOPATH
A variável de ambiente GOPATH especifica a localização de seu workspace. É basicamente a única variável de ambiente que você precisa configurar quando desenvolver usando Go.
Para começar, crie um diretório para seu workspace e configure a variável GOPATH de acordo. Seu workspace pode estar localizado em qualquer local que você queira, mas usaremos $HOME/work neste artigo. Observe que este diretório não precisa estar no mesmo caminho de sua instalação Go (Uma outra configuração comum é GOPATH=$HOME).
$ mkdir $HOME/work $ export GOPATH=$HOME/work
Por conveniência, adicione o subdiretório bin ao seu PATH:
$ export PATH=$PATH:$GOPATH/bin
Para aprender mais sobre a configuração da variável de ambiente GOPATH, leia go help path.
Caminhos de importação (Import paths)
Um import path é uma string que identifica de maneira única o seu pacote. O import path de um pacote corresponde a sua localização dentro do workspace ou a um repositório remoto (explicado abaixo).
Os pacotes da biblioteca padrão recebem um caminho de importação curto como fmt e net/http. Para seus pacotes, você precisa escolher um caminho base que não corra o risco de colidir com futuras adições à biblioteca padrão ou de outras bibliotecas externas.
Observe que você não precisa publicar seu código em um repositório remoto para poder compila-lo. É só um bom hábito organizar seu código como se ele fosse ser publica um dia. Na prática, você pode escolher qualquer nome arbitrário para o caminho, tão longo e único possível.
Usaremos github.com/user como caminho base. Crie um diretório dentro de seu workspace para guardar o código fonte.
$ mkdir -p $GOPATH/src/github.com/user
Seu primeiro programa
Para compilar e executar um programa simples, primeiro escolha um pacote (usaremos o github.com/user/hello) e crie um diretório para o pacote dentro do workspace:
$ mkdir $GOPATH/src/github.com/user/hello
Em seguida, crie um arquivo chamado hello.go dentro do diretório, com o seguinte código Go:
package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }
Agora você pode compilar e instalar esse programa com a ferramenta Go:
$ go install github.com/user/hello
Observe que você pode executar esse comando de qualquer local de seu sistema. A ferramenta go encontra o código fonte do pacote github.com/user/hello dentro do workspace especificado por GOPATH.
Você também pode omitir o caminho para o pacote se você executar go install dentro do diretório de pacote:
$ cd $GOPATH/src/github.com/user/hello $ go install
Esse comando compila o comando hello, produzindo um binário executável. Em seguida, instala esse binário no diretório bin do workspace as hello (ou, sob o Windows, hello.exe). Em nosso exemplo, será em $GOPATH/bin/hello, o que significa $HOME/work/bin/hello.
A ferramenta go irá exibir mensagens apenas se um erro ocorrer, assim se esses comandos não produzirem nenhuma mensagem eles foram executados com sucesso.
Você pode executar o programa agora digitando o caminho completo para ele na linha de comando:
$ $GOPATH/bin/hello Hello, world.
Se você estiver usando um sistema de controle de código, agora pode ser uma boa hora de inicializar um repositório, adicionar os arquivos, e dar um commit em sua primeira alteração. Novamente, esse passo é opcional: vocÊ não precisa usar um sistema de controle de código para escrever código Go.
$ cd $GOPATH/src/github.com/user/hello $ git init Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/ $ git add hello.go $ git commit -m "initial commit" [master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.go
Enviar o código para um diretório remoto fica como exercício para o leitor.
Sua primeira biblioteca
Vamos agora criar uma biblioteca e usa-la no programa hello.
Novamente, o primeiro passo é escolher um caminho para o pacote (usaremos github.com/user/stringutil) e criar o diretório do pacote:
$ mkdir $GOPATH/src/github.com/user/stringutil
Em seguida, crie um arquivo chamado reverse.go nesse diretório com o seguinte conteúdo:
// Package stringutil contains utility functions for working with strings. package stringutil // Reverse returns its argument string reversed rune-wise left to right. func Reverse(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r) }
Agora, cheque se esse pacote compila com go build:
$ go build github.com/user/stringutil
Ou, se você estiver trabalhando no próprio diretório de pacote, apenas use:
$ go build
Esse comando não produzirá um arquivo de saída. Para isso, você deve usar go install, que irá por o objeto no diretório pkg do workspace.
Depois de confirmar que o pacote stringutil está compilando sem erros, modifique o arquivo hello.go (que está em $GOPATH/src/github.com/user/hello) para usar stringutil:
package main import ( "fmt" "github.com/user/stringutil" ) func main() { fmt.Printf(stringutil.Reverse("!oG ,olleH")) }
Sempre que a ferramenta go instala um pacote ou binário, também instala quaisquer dependências que ele tiver. Assim, quando você instala o programa hello:
$ go install github.com/user/hello
O pacote stringutil será instalado também, automaticamente.
A executar a nova versão do programa, você deve visualizar uma nova mensagem, invertida:
$ hello Hello, Go!
Depois dos passos acima, seu workspace deve se parecer com isso:
bin/ hello # command executable pkg/ linux_amd64/ # this will reflect your OS and architecture github.com/user/ stringutil.a # package object src/ github.com/user/ hello/ hello.go # command source stringutil/ reverse.go # package source
Observe que go install pos o object stringutil.a em um diretório pkg/linux_amd64 que espelha o diretório onde está o código fonte. Isso faz com que invocações futuras da ferramenta go encontrem o object e evite-se recompilações desnecessárias do pacote. A parte linux_amd64 é uma ajuda para o caso de compilação cruzada, e reflete o sistema operacional e arquitetura de seu sistema.
Comandos executáveis Go são lincados estaticamente, o objeto do pacote precisa estar presente para que os programas Go sejam executados.
Nomes de pacotes
A primeira sentença de um arquivo de código Go deve ser:
package name
onde name é o nome padrão do pacote para imports (todos os arquivos de um pacote devem usar o mesmo name.
Por convenção, em Go o nome do pacote é o último elemento do import path: o pacote importado como crypto/rot13 deve ser nomeado como rot13.
Comando executáveis devem sempre usar package main.
Não há necessidade que nomes de pacotes sejam únicos dentre todos os pacotes lincados em um único binário, apenas que import paths (seus nomes completos) sem únicos.
Pacotes remotos
Um import path pode descrever como obter o código do pacote usando um sistema de controle de versões como o Git or Mercurial. A ferramenta go usar essa propriedade para obter automaticamente pacote de repositórios remotos. Por exemplo, os pacotes descritos nesse artigo também são mantidos em um repositório Git hispedado no GitHub em github.com/golang/example. Se você incluir a URL do repositório no import path do pacote, go get irá obter, compilar e instala-lo automaticamente.
$ go get github.com/golang/example/hello $ $GOPATH/bin/hello Hello, Go examples!
Se o pacote especificado não estiver presente no workspace, go get irá coloca-lo dentro do primeiro workspace especificado por GOPATH (se o pacote já existir, go get pula a captura remota do pacote e se comporta de forma análoga à go install).
Depois de disparado o comando go get acima, o diretório de workspace deve se parecer com o seguinte:
bin/ hello # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object github.com/user/ stringutil.a # package object src/ github.com/golang/example/ .git/ # Git repository metadata hello/ hello.go # command source stringutil/ reverse.go # package source reverse_test.go # test source github.com/user/ hello/ hello.go # command source stringutil/ reverse.go # package source reverse_test.go # test source
O comando hello hospedado no GitHub depende do pacote stringutil localizado no mesmo repositório. O imports em hello.go usa a mesma convenção para o import path, assim o comando go get é capaz de localizar e instalar a dependência também.
import "github.com/golang/example/stringutil"
essa convenção é a maneira mais fácil de fazer seus pacotes Go ficarem disponíveis para outros.
Traduzido de golang.org