Introdução
Em Go, uma build tag ou uma restrição de construção, é um identificador adicionado a um trecho de código que determina quando o arquivo deve ser incluído em um pacote durante o processo de build
. Isso permite que você construa diferentes versões da sua aplicação Go a partir do mesmo código-fonte e alternar entre elas de maneira rápida e organizada. Muitos desenvolvedores usam build tags para melhorar o fluxo de trabalho da construção de aplicativos compatíveis com várias plataformas, como programas que requerem mudanças de código para lidar com variações entre diferentes sistemas operacionais. Build tags também são usados para testes de integração, permitindo que você alternadamente entre o código integrado e o código com um serviço de simulação ou stub, além de diferentes níveis de conjuntos de recursos dentro de uma aplicação.
Vamos usar o problema das diferenças nos conjuntos de recursos dos clientes como exemplo. Ao escrever algumas aplicações, você pode querer controlar quais recursos incluir no binário, como uma aplicação que oferece níveis de Grátis, Pro e Enterprise. Conforme o cliente aumenta seu nível de assinatura nessas aplicações, mais recursos são desbloqueados e disponibilizados. Para resolver esse problema, você poderia manter projetos separados e tentar mantê-los sincronizados entre si através do uso de instruções import
. Embora essa abordagem funcione, ao longo do tempo, ela se tornará tediosa e propensa a erros. Uma abordagem alternativa seria usar tags de compilação.
Neste artigo, você usará tags de compilação no Go para gerar diferentes binários executáveis que oferecem conjuntos de recursos Grátis, Pro e Enterprise de uma aplicação de exemplo. Cada um terá um conjunto diferente de recursos disponíveis, com a versão Grátis sendo a padrão.
Pré-requisitos
Para seguir o exemplo neste artigo, você precisará:
- Um espaço de trabalho do Go configurado seguindo Como Instalar o Go e Configurar um Ambiente de Programação Local.
Construindo a Versão Grátis
Vamos começar construindo a versão Grátis do aplicativo, pois ela será a padrão ao executar go build
sem qualquer tag de build. Posteriormente, utilizaremos tags de build para adicionar selectivevemente outras partes ao nosso programa.
No diretório src
, crie uma pasta com o nome do seu aplicativo. Este tutorial usará app
:
Entre nessa pasta:
Em seguida, faça um novo arquivo de texto no seu editor de texto de escolha chamado main.go
:
Agora, definiremos a versão Grátis do aplicativo. Adicione o seguinte conteúdo ao main.go
:
Neste arquivo, criamos um programa que declara uma fatia chamada features
, que contém duas strings que representam os recursos do nosso aplicativo Grátis. A função main()
no aplicativo usa um for
loop para range
pela fatia features
e imprimir todos os recursos disponíveis na tela.
Salve e saia do arquivo. Agora que este arquivo está salvo, não precisaremos mais editá-lo para o restante do artigo. Em vez disso, usaremos tags de construção para alterar os recursos dos binários que construiremos a partir dele.
Construa e execute o programa:
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
O programa imprimiu nossas duas funcionalidades gratuitas, completando a versão Grátis do nosso aplicativo.
Até agora, você criou uma aplicação que tem um conjunto de recursos muito básico. Próximo, você construirá uma maneira de adicionar mais recursos à aplicação no momento da construção.
Adicionando as Funcionalidades Pro Com go build
Até agora, evitamos fazer mudanças no main.go
, simulando um ambiente de produção comum no qual é necessário adicionar código sem alterar e possivelmente quebrar o código principal. Como não podemos editar o arquivo main.go
, precisaremos usar outro mecanismo para injetar mais recursos na fatia features
usando tags de construção.
Vamos criar um novo arquivo chamado pro.go
que usará uma função init()
para anexar mais recursos à fatia features
:
Depois que o editor abrir o arquivo, adicione as seguintes linhas:
No código, utilizamos init()
para executar o código antes da função main()
da nossa aplicação, seguido por append()
para adicionar os recursos Pro à fatia features
. Salve e saia do arquivo.
Compile e execute a aplicação usando go build
:
Como agora há dois arquivos no nosso diretório atual (pro.go
e main.go
), go build
criará um binário a partir de ambos. Execute este binário:
Isso fornecerá o seguinte conjunto de recursos:
Output> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
A aplicação agora inclui tanto os recursos Pro quanto os Free. No entanto, isso não é desejável: como não há distinção entre as versões, a versão Free agora inclui os recursos que deveriam ser apenas disponíveis na versão Pro. Para corrigir isso, você pode incluir mais código para gerenciar os diferentes níveis da aplicação, ou você pode usar tags de build para informar a ferramenta Go quais arquivos .go
devem ser construídos e quais devem ser ignorados. Vamos adicionar tags de build no próximo passo.
Adicionando Tags de Build
Você pode agora usar tags de build para distinguir a versão Pro da sua aplicação da versão Free.
Vamos começar examinando como uma tag de build se parece:
Ao colocar esta linha de código como primeira linha do seu pacote e substituir tag_name
pelo nome da sua tag de construção, você vai marcar este pacote como código que pode ser incluído seletivamente no binário final. Vamos ver isso em ação adicionando uma tag de construção ao arquivo pro.go
para dizer ao comando go build
para ignorá-lo a menos que a tag seja especificada. Abra o arquivo em seu editor de texto:
Então, adicione a seguinte linha destacada:
// +build pro
package main
func init() {
features = append(features,
"Pro Feature #1",
"Pro Feature #2",
)
}
No topo do arquivo pro.go
, nós adicionamos // +build pro
seguido de uma nova linha em branco. Esta nova linha em branco é obrigatória, caso contrário, o Go interpreta isso como um comentário. As declarações de tags de construção devem também estar no topo de um arquivo .go
. Nada, nem sequer comentários, pode estar acima das tags de construção.
A declaração +build
diz ao comando go build
que isso não é um comentário, mas sim uma tag de construção. A segunda parte é a tag pro
. Adicionando esta tag no topo do arquivo pro.go
, o comando go build
agora incluirá o arquivo pro.go
apenas quando a tag pro
estiver presente.
Compile e execute a aplicação novamente:
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
Como o arquivo pro.go
precisa de uma tag pro
para estar presente, o arquivo é ignorado e a aplicação é compilada sem ele.
Ao executar o comando go build
, nós podemos usar a flag -tags
para incluir código condicionalmente no código compilado adicionando a tag em si como um argumento. Vamos fazer isso para a tag pro
:
Este será o seguinte:
Output> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
Agora, obtemos apenas os recursos adicionais quando construímos a aplicação usando a tag de construção pro
.
Isso está bem se houver apenas duas versões, mas as coisas ficam complicadas quando você adiciona mais tags. Para adicionar a versão Enterprise da nossa app na próxima etapa, usaremos várias tags de construção juntas com lógica booleana.
Lógica Booleana de Tag de Construção
Quando há várias tags de construção em um pacote Go, as tags interagem entre si usando lógica booleana. Para demonstrar isso, adicionaremos o nível Enterprise da nossa aplicação usando tanto a tag pro
quanto a tag enterprise
.
Para construir um binário Enterprise, precisaremos incluir tanto os recursos padrão, os recursos de nível Pro, quanto um novo conjunto de recursos para Enterprise. Primeiro, abra um editor e crie um novo arquivo, enterprise.go
, que adicionará os novos recursos de Enterprise:
O conteúdo de enterprise.go
será quase idêntico ao de pro.go
, mas conterá novos recursos. Adicione as seguintes linhas ao arquivo:
Salve e saia do arquivo.
Atualmente o arquivo enterprise.go
não tem nenhuma tag de construção, e conforme você aprendera ao adicionar pro.go
, isto significa que essas funcionalidades serão adicionadas à versão Gratuita quando for executado go build
. Para pro.go
, você adicionou // +build pro
e um novo caractere de linha no topo do arquivo para dizer ao go build
que deve ser incluído apenas quando -tags pro
é usado. Nessa situação, você só precisou de uma tag de construção para alcançar o objetivo. No entanto, quando adicionando as novas funcionalidades Empresariais, você precisará primeiro ter as funcionalidades Pro.
Vamos adicionar suporte para a tag de construção pro
em enterprise.go
primeiro. Abra o arquivo com seu editor de texto:
Em seguida, adicione a tag de construção antes da declaração de package main
e certifique-se de incluir uma nova linha após a tag de construção:
// +build pro
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
Salve e saia do arquivo.
Compile e execute a aplicação sem nenhuma tag:
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
As funcionalidades Empresariais já não aparecem na versão Gratuita. Agora vamos adicionar a tag de construção pro
e construir e executar a aplicação novamente:
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
> Pro Feature #1
> Pro Feature #2
Isto ainda não é exatamente o que precisamos: As funcionalidades Empresariais agora aparecem quando tentamos construir a versão Pro. Para solucionar isso, precisaremos de outra tag de construção. Contudo, para agora, precisaremos certificar que as funcionalidades pro
e Empresariais estejam ambas disponíveis.
O sistema de construção Go resolve esse caso permitindo o uso de algumas lógicas booleanas básicas no sistema de tags de construção.
Vamos abrir o enterprise.go
novamente:
Adicione outra tag de compilação, enterprise
, na mesma linha que a tag pro
:
// +build pro enterprise
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
Salve e feche o arquivo.
Agora vamos compilar e executar a aplicação com a nova tag de compilação enterprise
.
Isso resultará no seguinte:
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
Agora perdemos os recursos Pro. Isso acontece porque quando colocamos várias tags de compilação na mesma linha em um arquivo .go
, o go build
as interpreta usando lógica OU
. Com a adição da linha // +build pro enterprise
, o arquivo enterprise.go
será construído se ou a tag de compilação pro
ou a tag de compilação enterprise
estiver presente. Precisamos configurar as tags de compilação corretamente para exigir ambas e usar lógica E
em vez disso.
Em vez de colocar ambas as tags na mesma linha, se colocarmos elas em linhas separadas, então o go build
interpretará essas tags usando lógica E
.
Abrir o enterprise.go
novamente e vamos separar as tags de compilação em várias linhas.
// +build pro
// +build enterprise
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
Agora compile e execute a aplicação com a nova tag de compilação enterprise
.
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
Ainda não está completo: Como uma instrução E
requer que ambos os elementos sejam considerados verdadeiros
, precisamos usar ambas as tags de compilação pro
e enterprise
.
Vamos tentar de novo:
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
> Pro Feature #1
> Pro Feature #2
Agora, nossa aplicação pode ser construída da mesma árvore de fontes de várias maneiras, desbloqueando as funcionalidades da aplicação conforme necessário.
Neste exemplo, utilizamos uma nova tag // +build
para significar a lógica E
, mas há maneiras alternativas de representar a lógica booleana com tags de build. A seguinte tabela contém alguns exemplos de outras formatações sintáticas para tags de build, juntamente com seus equivalentes booleanos:
Build Tag Syntax | Build Tag Sample | Boolean Statement |
---|---|---|
Space-separated elements | // +build pro enterprise |
pro OR enterprise |
Comma-separated elements | // +build pro,enterprise |
pro AND enterprise |
Exclamation point elements | // +build !pro |
NOT pro |
Conclusão
Neste tutorial, você utilizou tags de build para permitir que controle qual parte do seu código é compilada no binário. Primeiro, você declarou tags de build e as usou com go build
, depois combinou várias tags com lógica booleana. Em seguida, você construiu um programa que representou os diferentes conjuntos de recursos de uma versão Free, Pro e Enterprise, mostrando o poderoso nível de controle que as tags de build podem dar a você sobre seu projeto.
Se você gostaria de aprender mais sobre tags de build, dê uma olhada na documentação do Golang sobre o assunto, ou continue explorando nossa série How To Code in Go.
Source:
https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags