Introdução
Em Go, uma build tag ou uma restrição de construção, é um identificador adicionado a um pedaço 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 mock ou stub, e para diferentes níveis de conjuntos de recursos dentro de uma aplicação.
Vamos tomar o problema de conjuntos de recursos de clientes diferentes 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 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 uns com os outros através do uso de declaraçõ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á de:
- Um espaço de trabalho Go configurado seguindo Como Instalar 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 selectivamente 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 choice 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 slice 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
através da slice 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 pelo 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 um aplicativo que tem um conjunto de recursos muito básico. Próximo, você criará uma maneira de adicionar mais recursos ao aplicativo no momento da construção.
Adicionando as Funcionalidades Pro Com go build
Até agora, evitamos fazer alterações 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:
Na código, utilizamos o init()
para executar código antes da função main()
do nosso aplicativo e depois usamos o append()
para adicionar as funcionalidades Pro ao slice features
. Salve e saia do arquivo.
Compile e execute o aplicativo usando go build
:
Como há agora duas fontes no diretório atual (pro.go
e main.go
), o go build
irá criar um binário de ambas elas. Executa este binário:
Isso lhe dara o seguinte conjunto de funcionalidades:
Output> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
A aplicação agora inclui as funcionalidades Pro e as Free. No entanto, isso não é desejável: pois a versão Free agora inclui as funcionalidades que são supostamente disponíveis somente na versão Pro. Para corrigir isso, você pode incluir mais código para gerenciar os diferentes níveis do aplicativo, ou você pode usar marcas de construção no próximo passo. Vamos adicionar marcas de construção na próxima etapa.
Adicionando Marcas de Construção
Veja como uma marca de construção 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ê 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 no 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
, 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 build devem também estar no topo de um arquivo .go
. Nada, nem mesmo comentários, pode estar acima das tags de build.
A declaração +build
diz ao comando go build
que isso não é um comentário, mas sim uma tag de build. 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
somente 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
exige que a tag pro
esteja 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 condicionalmente código no fonte compilado adicionando a tag própria como um argumento. Vamos fazer isso para a tag pro
:
Isso resultará no 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 do nosso aplicativo 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 do nosso aplicativo usando tanto a tag pro
quanto a tag enterprise
.
Para construir um binário Enterprise, precisaremos incluir tanto os recursos padrão quanto os recursos do nível Pro e um novo conjunto de recursos para Enterprise. Primeiro, abra um editor e crie um novo arquivo, enterprise.go
, que adicionará os novos recursos do 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 possui nenhuma tag de construção, e conforme você aprendera quando adicionou pro.go
, isto significa que essas funcionalidades serão adicionadas à versão gratuita quando executar go build
. Para pro.go
, você adicionou // +build pro
e um novo caractere de linha no topo do arquivo para informar 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 Enterprise, você precisará primeiro ter as funcionalidades Pro.
Vamos adicionar suporte para a tag de construção pro
ao 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 um novo caractere de 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 Enterprise já não aparecem na versão gratuita. Agora vamos adicionar a tag de construção pro
e compilar 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 Enterprise agora aparecem quando tentamos construir a versão Pro. Para resolver isso, precisamos usar outra tag de construção. Contudo, para agora, precisamos certificar que as funcionalidades pro
e enterprise
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 build, 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 build enterprise
.
Isso resultará no seguinte:
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
Agora perdemos os recursos Pro. Isso ocorre porque, quando colocamos várias tags de build 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 build pro
ou a tag de build enterprise
estiver presente. Precisamos configurar as tags de build corretamente para exigir ambas e usar lógica E
em vez disso.
Em vez de colocar ambas as tags na mesma linha, se colocarmos她们 em linhas separadas, o go build
interpretará essas tags usando lógica E
.
Abrir o enterprise.go
novamente e vamos separar as tags de build 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 build enterprise
.
Você receberá a seguinte saída:
Output> Free Feature #1
> Free Feature #2
Ainda não está helt allí: Porque uma instrução E
requer que ambos os elementos sejam considerados verdadeiros
, precisamos usar ambas as tags de build pro
e enterprise
.
Vamos tentar de novo:
Você receberá o seguinte output:
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 de várias formas a partir do mesmo conjunto de fontes, desbloqueando as funcionalidades da aplicação de acordo.
Neste exemplo, usamos um novo marcador de construção // +build
para indicar lógica AND
, mas existem outras maneiras alternativas de representar lógica booleana com marcadores de construção. A tabela a seguir apresenta alguns exemplos de outras formatações sintáticas para marcadores de construção, 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ê usou marcadores de construção para permitir que você controle quais partes de seu código sejam compiladas no binário. Primeiro, você declarou marcadores de construção e usou-os com go build
, então combinou vários marcadores com lógica booleana. Depois, você construiu um programa que representou os diferentes conjuntos de funcionalidades de versões Free, Pro e Enterprise, mostrando o nível de controle poderoso que os marcadores de construção podem fornecer para o seu projeto.
Se você quiser saber mais sobre os marcadores de construção, consulte a documentação do Golang sobre o assunto ou continue explorando nossa série Como Programar em Go.
Source:
https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags