Trabalhando com dependências em Go

Olá,
Esse é o último artigo da minha sequência proposta para introduzir novas pessoas ao Go. Espero que tenha sido útil até aqui e hoje esse material se complete para você ter a liberdade de começar a praticar e usar o Go. Ao invés de explicar como as coisas devem ser feitas hoje vou mostrar um pouco do histórico desse contexto no Go no meu ponto de vista como usuário mostrando o que encontrei nesse caminho.
Quando comecei com Go não tinha nenhuma ferramenta de gestão de dependências em Go, então, a solução era manter ou um make dep
que tinha todos os go get
necessários para rodar o projeto ou algum script em bash que fazia o mesmo trabalho. Sofrido, não? Para quem vinha de de C/C++ era até melhor a experiência mas para quem já vinha de Ruby, Python e Java, por exemplo, era horrível a experiência. Não demorou muito com a aderência da comunidade pela linguagem isso ser uma reclamação constante e emergir da comunidade algumas soluções até a solução oficial da linguagem hoje, segue a minha jornada que vou abordar em mais detalhes a seguir: Godeps, govendor, Glide, go dep e go modules.
Godeps
Esse foi o primeiro projeto que usei para gerir dependências em Go. Foi uma experiência de uso de ferramenta bem ruim e ai começava a saga de comitar a pasta vendor
no repositório para não correr risco de quebrar a integração contínua.
govendor
Esse ainda consta no Github aqui. Foi o primeiro que usei depois do Godeps e ajudou bastante com a interface de linha de comandos dele, ajudou o controlar melhor e ficar mais com cara de sistema de gestão de dependências iguais ao que eu tinha familiaridade de outras linguagens.
Glide
Ainda sentindo com os problemas do govendor, achei o Glide que ajudou muito com o conceito de arquivo de lock
que versionava as minhas dependências. Agora sim, estava satisfeito pois tinha chegado a um nível próximo ao do que vinha usando no Python e Ruby, o que faltava era ter um serviço central para cuidar das dependências.
go dep
Estava feliz com meus projetos migrados para o Glide e me deparo com a chegada do go dep, pronto, mais uma vez lá vamos nós migrar por conta que parece que a solução oficial da linguagem vai ser essa. Acabou que a migração não aconteceu e entrei em um hiato de trabalhar com Go e não tive a experiência de usar.
go modules
Afastado da programação em Go, eis que surge o Go Modules e parece que a saga da gestão de dependências chega ao fim. Agora, voltando a programar em Go tenho como meta usar ele mas ainda estamos aqui com umas outras pendências mais importantes no projeto antes de migrar, estou ansioso para testar mas nos projetos que vi no Github que usam e testei a experiência ficou bem melhor. Nos último artigo acabei dando spoiler
de como usar go modules
no projeto hello
. Como é a cara desse go modules
:
$ go mod
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod <command>" for more information about a command.
Alterando o projeto hello
para ver como funciona o go modules
:
package morestrings
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestReverseRunes(t *testing.T) {
cases := []struct {
in, want string
}{
{"Hello, world", "dlrow ,olleH"},
{"Hello, 世界", "界世 ,olleH"},
{"", ""},
}
for _, c := range cases {
got := ReverseRunes(c.in)
if got != c.want {
assert.Equal(t, got, c.want)
}
}
}
Executando agora vamos ter o seguinte resultado:
$ go test ./...
go: finding github.com/stretchr/testify v1.4.0
go: downloading github.com/stretchr/testify v1.4.0
go: extracting github.com/stretchr/testify v1.4.0
go: downloading gopkg.in/yaml.v2 v2.2.2
go: downloading github.com/davecgh/go-spew v1.1.0
go: downloading github.com/pmezard/go-difflib v1.0.0
go: extracting gopkg.in/yaml.v2 v2.2.2
go: extracting github.com/pmezard/go-difflib v1.0.0
go: extracting github.com/davecgh/go-spew v1.1.0
go: finding github.com/pmezard/go-difflib v1.0.0
go: finding github.com/davecgh/go-spew v1.1.0
go: finding gopkg.in/yaml.v2 v2.2.2
? github.com/jvrmaia/hello [no test files]
ok github.com/jvrmaia/hello/morestrings 0.002s
Repare que ainda não temos uma pasta vendor
trabalhando dessa forma no projeto:
$ ls
go.mod go.sum hello.go morestrings/
Para criar a estrutura do vendor
basta usar o comando go mod vendor
, veja o resultado:
$ tree -L 3 .
.
├── go.mod
├── go.sum
├── hello.go
├── morestrings
│ ├── morestrings.go
│ └── reverse_test.go
└── vendor
├── github.com
│ ├── davecgh
│ ├── google
│ ├── pmezard
│ └── stretchr
├── gopkg.in
│ └── yaml.v2
└── modules.txt
$ cat vendor/modules.txt
# github.com/davecgh/go-spew v1.1.0
github.com/davecgh/go-spew/spew
# github.com/google/go-cmp v0.4.0
github.com/google/go-cmp/cmp
github.com/google/go-cmp/cmp/internal/diff
github.com/google/go-cmp/cmp/internal/flags
github.com/google/go-cmp/cmp/internal/function
github.com/google/go-cmp/cmp/internal/value
# github.com/pmezard/go-difflib v1.0.0
github.com/pmezard/go-difflib/difflib
# github.com/stretchr/testify v1.4.0
github.com/stretchr/testify/assert
# gopkg.in/yaml.v2 v2.2.2
gopkg.in/yaml.v2
Existem outras coisas mais a serem exploradas no go modules
mas recomendo que agora você tente ir por você mesmo nessa descoberta e para ajudar no próximo tópico recomendo alguns artigos sobre essa parte da história de gestão de dependências em Go e sobre o uso de go modules
.
Espero que com essa sequência de artigos tenha ajudado você a começar a sua jornada em Go.
Comments ()