One place for hosting & domains

      ldflags

      Usando ldflags para definir informações de versão em aplivativos Go


      Introdução

      Ao implantar aplicativos em um ambiente de produção, a compilação de binários com informações de versão e outros metadados irá melhorar seu processo de monitoramento, registro e depuração através da adição de informações de identificação para ajudar a rastrear suas compilações ao longo do tempo. Essas informações de versão com frequência podem incluir dados altamente dinâmicos, como o tempo de compilação, a máquina ou o usuário que compila o binário, o ID de confirmação do Sistema de Controle de Versão (VCS) em relação ao qual foi compilado, entre outras coisas. Como esses valores estão em constante mudança, codificar esses dados diretamente no código fonte e modificá-los antes de cada nova compilação é um processo tedioso e propenso a erros: os arquivos fonte podem mover-se e as variáveis/constantes podem trocar arquivos ao longo do desenvolvimento, interrompendo o processo de compilação.

      Uma maneira de resolver isso em Go é usando -ldflags com o comando go build para inserir informações dinâmicas no binário no momento da compilação, sem a necessidade de modificar códigos fonte. Neste identificador, o ld significa linker [vinculador], o programa que vincula os diferentes pedaços do código fonte compilado em um binário final. ldflags, então, significa *linker flags *[identificadores de vinculador]. Ele recebe esse nome porque passa um identificador para o conjunto subjacente do vinculador da cadeia de ferramentas em Go, cmd/link, que permite que você altere os valores de pacotes importados no momento da compilação a partir da linha de comando.

      Neste tutorial, você usará -ldflags para alterar o valor das variáveis no momento da compilação e introduzir suas próprias informações dinâmicas em um binário, usando um aplicativo exemplo que imprime informações de versão para a tela.

      Pré-requisitos

      Para seguir o exemplo neste artigo, será necessário:

      Compilando seu aplicativo exemplo

      Antes de poder usar ldflags para introduzir dados dinâmicos, será necessário primeiro um aplicativo no qual inserir as informações. Neste passo, você criará esse aplicativo, o qual, por enquanto,imprimirá apenas informações sobre o controle de versão estática. Vamos criar esse aplicativo agora.

      No seu diretório src, crie um diretório com o nome do seu aplicativo. Este tutorial usará o nome de aplicativo app:

      Mude seu diretório de trabalho para essa pasta:

      Em seguida, usando o editor de texto de sua escolha, crie o ponto de entrada do seu programa, main.go:

      Agora, faça seu aplicativo imprimir informações de versão, adicionando o seguinte conteúdo:

      app/main.go

      package main
      
      import (
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
      }
      

      Dentro da função main(), você declarou a variável Version, em seguida imprimiu a string Version:, seguida de um caractere de guia (tab), t e, na sequência declarou a variável.

      Neste ponto, a variável Version foi definida como development, a qual será a versão padrão desse app. Mais tarde, você trocará esse valor por um número oficial de versão, organizado segundo o formato semântico para controle de versão.

      Salve e saia do arquivo. Assim que terminar, compile e execute o aplicativo para confirmar que ele imprime a versão correta:

      Você verá o seguinte resultado:

      Output

      Agora, você tem um aplicativo que imprime informações da versão padrão, mas ainda não tem como enviar as informações da versão atual no momento da compilação. No próximo passo, você usará -ldflags e go build para resolver esse problema.

      Assim como mencionado anteriormente, ldflags significa identificadores de vinculador e é usado para enviar identificadores para o vinculador subjacente na cadeia de ferramentas Go. Isso funciona de acordo com a seguinte sintaxe:

      • go build -ldflags="-flag"

      Nesse exemplo, transmitimos o flag para o comando go tool link subjacente que executa como parte do go build. Esse comando usa aspas duplas ao redor do conteúdo transmitido para os ldflags para evitar quebrar caracteres nele, ou caracteres que a linha de comando possa interpretar como algo diferente do que queremos. A partir daqui, você poderia enviar muitos e diferentes identificadores de link. Para os fins deste tutorial, usaremos o identificador -X para gravar informações na variável no momento de vincular, seguido do caminho do pacote até a variável e seu novo valor:

      • go build -ldflags="-X 'package_path.variable_name=new_value'"

      Dentro das aspas, há agora a opção -X e um par chave-valor que representa a variável a ser alterada e seu novo valor. O caractere . separa o caminho do pacote e o nome da variável e aspas únicas são usadas para evitar a quebra de caracteres no par chave-valor.

      Para substituir a variável Version no seu aplicativo exemplo, use a sintaxe no último bloco de comando para enviar um novo valor e compilar o novo binário:

      • go build -ldflags="-X 'main.Version=v1.0.0'"

      Neste comando, main é o caminho de pacote da variável Version, uma vez que essa variável está no arquivo main.go. Version é a variável para a qual está gravando, e o v1.0.0 é o novo valor.

      Para usar o ldflags, o valor que você quiser alterar deve existir e ser uma variável do nível de pacote do tipo string. Essa variável pode ser exportada ou não exportada. O valor não pode ser const ou ter seu valor definido pelo resultado de uma chamada de função. Felizmente, Version se encaixa em todos esses requisitos: ela já foi declarada como variável no arquivo main.go, assim como o valor atual (development) e o valor desejado (v1.0.0) são ambos strings.

      Assim que seu novo binário app for compilado, execute o aplicativo:

      Você receberá o seguinte resultado:

      Output

      Usando -ldflags, você mudou com sucesso a variável Version de development para v1.0.0.

      Agora, você modificou uma variável string dentro de um aplicativo simples na hora da compilação. Usando ldflags, você pode inserir detalhes de versão, informações de licenciamento e outras coisas em um binário pronto para a distribuição, usando apenas a linha de comando.

      Neste exemplo, a variável que você mudou estava no programa main, o que reduz a dificuldade em determinar o nome do caminho. No entanto, as vezes, o caminho para essas variáveis é mais complicado de se encontrar. No próximo passo, você irá gravar valores para as variáveis nos subpacotes para demonstrar a melhor maneira de se determinar caminhos de pacotes mais complexos.

      Concentrando-se em variáveis para subpacotes

      Na última seção, você manipulou a variável Version, a qual estava no pacote de nível superior do aplicativo. Mas esse não é sempre o caso. Com frequência, é mais prático colocar essas variáveis em outro pacote, já que o main não é um pacote importável. Para simular isso em seu aplicativo exemplo, você criará um novo subpacote, app/build que armazenará informações sobre a hora em que o binário foi compilado e o nome do usuário que emitiu o comando de compilação.

      Para adicionar um novo subpacote, adicione primeiro um novo diretório ao seu projeto chamado build:

      Depois, crie um novo arquivo chamado build.go para reter as novas variáveis:

      No seu editor de texto, adicione novas variáveis para Time e User:

      app/build/build.go

      package build
      
      var Time string
      
      var User string
      

      A variável Time reterá uma representação de string da hora em que o binário foi compilado. A variável User reterá o nome do usuário que compilou o binário. Como essas duas variáveis sempre terão valores, você não precisa inicializar essas variáveis com valores padrão como você fez para Version.

      Salve e saia do arquivo.

      Em seguida, abra o main.go para adicionar essas variáveis ao seu aplicativo:

      Dentro de main.go, adicione as seguintes linhas destacadas:

      main.go

      package main
      
      import (
          "app/build"
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
          fmt.Println("build.Time:t", build.Time)
          fmt.Println("build.User:t", build.User)
      }
      

      Nessas linhas, você importou primeiro o pacote app/build e, então, imprimiu build.Time e build.User da mesma forma que imprimiu Version.

      Salve o arquivo e depois saia do seu editor de texto.

      Em seguida, para atingir essas variáveis com o ldflags, você poderia usar o caminho de importação app/build seguido de . User ou . Time, uma vez que você já sabe o caminho de importação. No entanto, para simular uma situação mais complexa na qual o caminho para a variável não é evidente, em vez disso, vamos usar o comando nm na cadeia de ferramentas Go.

      O comando go tool nm dará como resultado os símbolos envolvidos em um dado executável, arquivo de objeto ou arquivo. Neste caso, um símbolo se refere a um objeto no código, como uma variável ou função definida ou importada. Ao gerar uma tabela de símbolos com nm e usar o grep para procurar por uma variável, você pode rapidamente encontrar informações sobre seu caminho.

      Nota: o comando nm não ajudará você a encontrar o caminho da sua variável se o nome do pacote tiver qualquer caractere não ASCII ou um caractere " ou %, já que essa é uma limitação da ferramenta em si.

      Para usar esse comando, compile primeiro o binário para app:

      Agora que o app foi compilado, aponte a ferramenta nm para ele e examine o resultado:

      • go tool nm ./app | grep app

      Quando executada, a ferramenta nm gerará muitos dados como resultado. Por isso, o comando anterior usou o símbolo | para canalizar o resultado até o comando grep, o qual, na sequência, pesquisou termos que tivessem app de nível elevado no título.

      Você irá receber um resultado parecido com este:

      Output

      55d2c0 D app/build.Time 55d2d0 D app/build.User 4069a0 T runtime.appendIntStr 462580 T strconv.appendEscapedRune . . .

      Neste caso, as duas primeiras linhas do conjunto de resultados contêm os caminhos para as duas variáveis que você está procurando: app/build.Time e app/build.User.

      Agora que você conhece os caminhos, compile o aplicativo novamente, desta vez alterando Version, User e Time no momento de compilar. Para tanto, passe vários identificadores -X para os -ldflags:

      • go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"

      Aqui, você enviou o comando Bash id -u -n para listar o usuário atual e o comando date para listar a data atual.

      Assim que o executável estiver compilado, execute o programa:

      Esse comando, quando executado em um sistema Unix, gerará um resultado similar ao seguinte:

      Output

      Version: v1.0.0 build.Time: Fri Oct 4 19:49:19 UTC 2019 build.User: sammy

      Agora, você tem um binário que contém informações do controle de versão e compilação que podem fornecer assistência vital na produção ao resolver problemas.

      Conclusão

      Este tutorial mostrou como, quando aplicado corretamento, o ldflags pode ser uma ferramenta poderosa para injetar informações valiosas em binários no momento da compilação. Dessa forma, você pode controlar identificadores de recursos, informações de ambiente, informações de controle de versão e outras coisas, sem introduzir alterações no seu código fonte. Ao adicionar ldflags ao seu fluxo de trabalho de compilação atual, você pode maximizar os benefícios do formato de distribuição binária independente do Go.

      Se quiser aprender mais sobre a linguagem de programação Go, confira toda a nossa série sobre Como codificar em Go. Se estiver procurando mais soluções para controle de versão, teste nosso guia de referência Como usar o Git.



      Source link

      Cómo usar ldflags para configurar la información de versión de aplicaciones de Go


      Introducción

      Al implementar aplicaciones en un entorno de producción, la creación de binarios con información de versión y otros metadatos mejorará sus procesos de monitoreo, registro y depuración al agregar información de identificación para ayudar a realizar un seguimiento de sus compilaciones con el tiempo. Esta información de versión, a menudo, puede incluir datos muy dinámicos, como el tiempo de compilación, la máquina o el usuario que compiló el binario y el sistema de control de versiones (VCS) con el que se creó, entre otros. Debido a que estos valores cambian constantemente, codificar estos datos directamente en el código fuente y modificarlos antes de cada compilación nueva es tedioso y está expuesto errores: los archivos de código fuente se pueden mover y las variables y constantes pueden cambiar los archivos a lo largo del desarrollo, lo que interrumpe el proceso de compilación.

      Una manera de resolver esto en Go es usar -ldflags con el comando go build para insertar información dinámica en el binario en el tiempo de compilación, sin necesidad de modificar el código fuente. En este indicador, ld significa enlazador, que es el programa que vincula las diferentes piezas del código fuente compilado en el binario final. Por lo tanto, ldflags quiere decir indicadores de enlazador. Se denomina de esta manera porque pasa un indicador al enlazador subyacente de la cadena de herramientas de Go, cmd/link, que le permite cambiar los valores de los paquetes importados en el tiempo de compilación desde la línea de comandos.

      En este tutorial, usará -ldflags para cambiar el valor de las variables en el tiempo de compilación e introducir su propia información dinámica en un binario usando una aplicación de muestra que imprime información de versión en la pantalla.

      Requisitos previos

      Para seguir el ejemplo de este artículo, necesitará lo siguiente:

      Crear su aplicación de muestra

      Antes de usar ldflags para introducir datos dinámicos, primero, necesita una aplicación para insertar la información. En este paso, creará esta aplicación, que, en esta etapa, solo imprimirá información de control de versiones estática. Crearemos esa aplicación ahora.

      En su directorio src, cree un directorio que lleve el nombre de su aplicación. En ese tutorial, se usará el nombre de aplicaciónapp:

      Cambie su directorio de trabajo a esta carpeta:

      A continuación, usando el editor de texto que prefiera, cree el punto de entrada de su programa, main.go:

      Ahora, haga que su aplicación imprima información de versión añadiendo el siguiente contenido:

      app/main.go

      package main
      
      import (
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
      }
      

      Dentro de la función main(), declaró la variable Version, luego imprimió la cadena Version: seguida de un carácter de tabulación, t, y por último la variable declarada.

      En este punto, la variable Version se define como development, que será la versión predeterminada de esta aplicación. Posteriormente, cambiará este valor para que sea un número de versión oficial, que se dispondrá conforme al formato de control de versiones semántico.

      Guarde el archivo y ciérrelo. Una vez hecho esto, cree y ejecute la aplicación para confirmar que imprima la versión correcta:

      Verá lo siguiente:

      Output

      Ahora, dispondrá de una aplicación que imprime información de versión predeterminada, pero todavía no cuenta con una forma de transmitir información de versión actual en el tiempo de compilación. En el siguiente paso, usará -ldflags y go build para resolver este problema.

      Usar ldflags con go build

      Como se mencionó anteriormente, ldflags significa *indicadores de enlazador *y se utiliza para pasar indicadores al enlazador subyacente de la cadena de herramientas de Go. Esto funciona de acuerdo con la siguiente sintaxis:

      • go build -ldflags="-flag"

      En este ejemplo, pasamos flag al comando go tool link subyacente que se ejecuta como parte de go build. En este comando, se utilizan comillas dobles alrededor del contenido que se pasa a ldflags para evitar romper sus caracteres o la presencia de caracteres que la línea de comandos podría interpretar como algo distinto de lo que deseamos. Desde aquí, podría pasar muchos indicadores link diferentes. A los efectos de este tutorial, usaremos el indicador -X para escribir información en la variable en el tiempo de enlace, seguido de la ruta del paquete a la variable y su nuevo valor:

      • go build -ldflags="-X 'package_path.variable_name=new_value'"

      Dentro de las comillas, ahora se encuentran la opción -X y un par clave-valor que representa la variable que se debe cambiar y su nuevo valor. El carácter . separa la ruta del paquete y el nombre de la variable, y se utilizan comillas simples para evitar la ruptura de los caracteres en el par clave-valor.

      Para sustituir la variable Version en su aplicación de ejemplo, utilice la sintaxis del último bloque de comandos a fin de establecer un nuevo valor y compilar el nuevo binario:

      • go build -ldflags="-X 'main.Version=v1.0.0'"

      En este comando, main es la ruta del paquete de la variable Version, dado que esta variable se encuentra en el archivo main.go. Version es la variable en la que escribe y v1.0.0 es el nuevo valor.

      Para usar ldflags, el valor que desea cambiar debe existir y ser una variable de nivel de paquetes de tipo string. Esta variable puede ser exportada o no exportada. El valor no puede ser const y el resultado de la invocación de una función no puede fijarlo. Afortunadamente, Version cumple todos estos requisitos: ya se declaró como variable en el archivo main.go, y tanto el valor actual (development) como el valor deseado (v1.0.0) son cadenas.

      Una vez compilado su nuevo binario app, ejecute la aplicación:

      Recibirá el siguiente resultado:

      Output

      Con -ldflags, cambió de forma exitosa la variable Version de development a v1.0.0.

      De esta manera, modificó una variable string dentro de una aplicación simple en el tiempo de compilación. Con ldflags, puede insertar detalles de versión, información de licenciamiento y otros datos en un binario listo para la distribución usando solo la línea de comandos.

      En este ejemplo, la variable que cambió se encontraba en el programa main, lo que redujo la dificultad de determinar el nombre de la ruta. Sin embargo, a veces la ruta hacia estas variables es más difícil de encontrar. En el siguiente paso, escribirá valores en variables dentro de subpaquetes para demostrar la mejor manera de determinar rutas de paquetes más complejas.

      Proporcionar orientación hacia variables de subpaquetes

      En la última sección, manipuló la variable Version que se encontraba en el paquete de nivel superior de la aplicación. Sin embargo, esto no siempre es así. Suele ser más práctico disponer estas variables en otro paquete, ya que el paquete main no se puede importar. Para simular esto en su aplicación de muestra, creará un nuevo subpaquete, app/build, que almacenará información sobre el momento en que se compiló el binario y el nombre del usuario que ejecutó el comando de compilación.

      Para añadir un nuevo subpaquete, primero agregue a su proyecto un nuevo directorio denominado build:

      A continuación, cree un nuevo archivo llamado build.go para contener las variables nuevas:

      En su editor de texto, añada nuevas variables para Time y User:

      app/build/build.go

      package build
      
      var Time string
      
      var User string
      

      La variable Time contendrá una representación de cadena del momento en que se compiló el binario. La variable User contendrá el nombre del usuario que compiló el binario. Dado que estas dos variables siempre tendrán valores, no es necesario inicializarlas con valores predeterminados, como lo hizo para Version.

      Guarde el archivo y ciérrelo.

      A continuación, abra main.go para añadir estas variables a su aplicación:

      Dentro de main.go, agregue las siguientes líneas resaltadas:

      main.go

      package main
      
      import (
          "app/build"
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
          fmt.Println("build.Time:t", build.Time)
          fmt.Println("build.User:t", build.User)
      }
      

      En estas líneas, primero importó el paquete app/build y luego imprimió build.Time y build.User de la misma manera en que imprimió Version.

      Guarde el archivo y cierre su editor de texto.

      A continuación, para brindar orientación a estas variables con ldflags podría usar la ruta de importación app/build seguida de .User o .Time, dado que ya conoce la ruta de importación. Sin embargo, para simular una situación más compleja en la cual la ruta hacia la variable no sea tan evidente, usaremos el comando nm de la cadena de herramientas de Go.

      Con el comando go tool nm se mostrarán los símbolos presentes en un ejecutable, un objeto o un archivo. En este caso, “símbolo” se refiere a un objeto en el código, como una variable o función definida o importada. Generando una tabla de símbolos con nm y usando grep para buscar una variable, puede obtener rápidamente información sobre su ruta.

      Nota: El comando nm no lo ayudará a encontrar la ruta de su variable si el nombre del paquete tiene caracteres no ASCII, o bien los caracteres " o %, ya que es una limitación de la herramienta.

      Para usar este comando, primero, compile el binario para app:

      Ahora que se compiló app, oriente la herramienta nm hacia ella y realice una búsqueda en el resultado:

      • go tool nm ./app | grep app

      Cuando se ejecute, la herramienta nm mostrará muchos datos. Debido a esto, el comando anterior utilizó | para canalizar el resultado al comando grep, que luego buscó términos con la app de nivel superior en el título.

      Recibirá un resultado similar a este:

      Output

      55d2c0 D app/build.Time 55d2d0 D app/build.User 4069a0 T runtime.appendIntStr 462580 T strconv.appendEscapedRune . . .

      En este caso, las primeras dos líneas del resultado establecido contienen las rutas de las dos variables que busca: app/build.Time y app/build.Time.

      Ahora que conoce las rutas, compile la aplicación de nuevo, pero, esta vez, cambie Version, User y Time en el tiempo de compilación. Para hacerlo, pase varios indicadores -X a -ldflags:

      • go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"

      Aquí, pasó el comando Bash id -u -n para mostrar el usuario actual y el comando date para mostrar la fecha actual.

      Una vez compilado el ejecutable, ejecute el programa:

      Este comando, cuando se ejecuta en un sistema Unix, genera un resultado similar al siguiente:

      Output

      Version: v1.0.0 build.Time: Fri Oct 4 19:49:19 UTC 2019 build.User: sammy

      Ahora, dispondrá de un binario que contiene información de control de versiones y de compilación, y que puede proporcionar ayuda fundamental para la producción a la hora de resolver problemas.

      Conclusión

      En este tutorial, se demostró que ldflags, cuando se aplica correctamente, puede ser una potente herramienta para introducir información valiosa en binarios en el tiempo de compilación. De esta manera, puede controlar indicadores de características, información de entorno, información de control de versiones y otros elementos sin introducir cambios en su código fuente. Agregando ldflags a su flujo de trabajo de compilación actual, puede maximizar los beneficios del formato de distribución binaria autónoma de Go.

      Si desea obtener más información acerca del lenguaje de programación Go, consulte toda la serie Cómo programar en Go. Si busca más soluciones para el control de versiones, consulte nuestra guía de referencia Cómo usar Git.



      Source link

      Использование ldflags для установки информации о версиях в приложениях Go


      Введение

      При развертывании приложений в производственной среде сборка двоичных файлов с информацией о версии и другими метаданными помогает улучшить процессы мониторинга, регистрации данных и отладки за счет добавления идентификационной информации для отслеживания версий сборок. Информация о версии часто содержит динамические данные, такие как время сборки, компьютер или пользователя, выполняющих сборку двоичного файла, идентификатор в системе контроля версий (VCS) и т. д. Поскольку эти значения постоянно меняются, внесение этих данных в исходный код и их изменение при каждой сборке становится непростой задачей, где могут возникнуть ошибки. Файлы исходного кода могут перемещаться, переменные и константы могут менять файлы во время разработки, и все это может нарушить процесс сборки.

      В Go эту проблему можно решить с помощью опции -ldflags команды go build. Эта опция вставляет в двоичный файл во время сборки динамическую информацию, не требуя изменения исходного кода. В этой опции ld означает программу linker, которая связывает разные фрагменты скомпилированного исходного кода в двоичном файле. Таким образом, название опции ldflags означает флаги linker. Данная опция передает файл в инструмент linker цепи инструментов Go cmd/link, позволяющий изменять значения импортированных пакетов во время сборки из командной строки.

      В этом обучающем руководстве вы научитесь использовать -ldflags для изменения значения переменных во время сборки и внесения в двоичный файл собственных динамических данных, используя для этого образец приложения, которое распечатывает на экране информацию о версии.

      Предварительные требования

      Для выполнения примера из этой статьи вам потребуется следующее:

      Создание образца приложения

      Прежде чем вы сможете использовать ldflags для внесения динамических данных, вам потребуется приложение, куда нужно вставлять эти данные. На этом шаге вы создадите такое приложение, которое на данном этапе будет только выводить статическую информацию о версии. Давайте создадим это приложение.

      Создайте внутри каталога src подкаталог с именем вашего приложения. В этом обучающем руководстве мы будем использовать имя приложения app:

      Смените рабочий каталог на эту папку:

      Затем используйте предпочитаемый текстовый редактор для создания входной точки программы, main.go:

      Добавьте следующий код, чтобы ваше приложение распечатывало информацию о версии:

      app/main.go

      package main
      
      import (
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
      }
      

      Внутри функции main() вы декларировали переменную Version, затем распечатали строку Version: с символом табуляции t, а затем декларированную переменную.

      На данном этапе переменная Version имеет заданное значение development, и эта версия будет использоваться для приложения по умолчанию. Впоследствии вы сможете заменить это значение на официальный номер версии, соответствующий желаемому семантическому формату версий.

      Сохраните и закройте файл. После этого выполните сборку и запустите приложение, чтобы подтвердить распечатку правильной версии:

      Результат будет выглядеть следующим образом:

      Output

      Теперь у вас есть приложение, которое распечатывает информацию о версии по умолчанию, однако у вас еще нет способа передачи информации о текущей версии во время сборки. На следующем шаге вы используете -ldflags и go build для решения этой проблемы.

      Использование ldflags с go build

      Как указывалось выше, ldflags означает флаги linker и используется для передачи флагов в linker через цепочку инструментов Go. При этом используется следующий синтаксис:

      • go build -ldflags="-flag"

      В этом примере мы передали флаг в соответствующую команду go tool link, которая запускается в рамках go build. Эта команда заключает в двойные кавычки передаваемое в ldflags содержимое, чтобы предотвратить разрыв символов или неправильную интерпретацию передаваемых символов командной строкой. Отсюда вы можете передать много разных флагов link. В этом обучающем руководстве мы используем флаг -X для записи информации в переменную во время связи, а затем указываем путь пакета к переменной и ее новое значение:

      • go build -ldflags="-X 'package_path.variable_name=new_value'"

      Внутри кавычек содержится опция -X и пара ключ-значение, соответствующая изменяемой переменной и ее новому значению. Символ . разделяет путь пакета и имя переменной, а одинарные кавычки используются для предотвращения разрыва символов в паре ключ-значение.

      Чтобы заменить переменную Version в нашем примере приложения, используйте синтаксис последнего блока команд для передачи нового значения и сборки нового двоичного файла:

      • go build -ldflags="-X 'main.Version=v1.0.0'"

      В этой команде main — это путь пакета переменной Version, поскольку данная переменная содержится в файле main.go. Version — это переменная, в которую выполняется запись, а v1.0.0 — это новое значение.

      Для использования ldflags необходимо, чтобы изменяемое значение существовало и относилось к переменной уровня пакета типа string. Эта переменная может быть экспортированной или неэкспортированной. Значение не может быть const и не может задаваться результатом вызова функции. К счастью, Version соответствует всем этим требованиям. Она уже декларирована как переменная в файле main.go и ее текущее значение (development) и желаемое значение (v1.0.0) являются строками.

      После сборки нового двоичного файла app запустите приложение:

      Результат будет выглядеть следующим образом:

      Output

      С помощью -ldflags вы успешно изменили значение переменной Version с development на v1.0.0.

      Теперь вы изменили переменную string внутри простого приложения во время сборки. С помощью ldflags вы можете вставлять в двоичный файл сведения о версии, информацию о лицензирование и другие данные, используя только командную строку.

      В этом примере измененная переменная находилась в программе main, и благодаря этому было проще определить имя пути. Однако иногда путь к таким переменным бывает сложнее найти. На следующем шаге вы запишете значения в переменные в субпакетах, используя наилучший способ определения более сложных путей пакетов.

      Таргетирование переменных субпакета

      В последнем разделе вы внесли изменения в переменную Version в пакете верхнего уровня приложения. Однако ситуация не всегда такая простая. Очень часто наиболее практичным способом будет поместить эти переменные в другой пакет, поскольку пакет main не является импортируемым. Чтобы смоделировать это в образце приложения вы создадите новый субпакет app/build, в котором будет храниться информация о времени сборки двоичного файла и имени пользователя, отправившего команду сборки.

      Чтобы добавить новый субпакет, добавьте в проект новый каталог с именем build:

      Затем создайте новый файл с именем build.go для хранения новых переменных:

      Добавьте в текстовом редакторе новые переменные Time и User:

      app/build/build.go

      package build
      
      var Time string
      
      var User string
      

      Переменная Time хранит время сборки двоичного файла в форме строки. Переменная User хранит имя пользователя, который выполнил сборку двоичного файла. Поскольку эти две переменные всегда имеют значения, их не нужно инициализировать с помощью значений по умолчанию, как вы это делали для переменной Version.

      Сохраните и закройте файл.

      Затем откройте файл main.go для добавления этих переменных в ваше приложение:

      Добавьте в файл main.go следующие выделенные строки:

      main.go

      package main
      
      import (
          "app/build"
          "fmt"
      )
      
      var Version = "development"
      
      func main() {
          fmt.Println("Version:t", Version)
          fmt.Println("build.Time:t", build.Time)
          fmt.Println("build.User:t", build.User)
      }
      

      В этих строках вы вначале импортируете пакет app/build, а затем выполняете печать build.Time и build.User точно так же, как и при печати переменной Version.

      Сохраните файл и закройте текстовый редактор.

      Чтобы сделать эти переменные целью опции ldflags, вы можете использовать путь импорта app/build с символом . в конце User или . Time, поскольку вам уже известен путь импорта. Для моделирования более сложной ситуации, когда путь к переменной не очевиден, мы используем команду nm в цепочке инструментов Go.

      Команда go tool nm выводит символы из заданного исполняемого файла, объектного файла или архива. В данном случае символ относится к объекту в коде, например, к определенной или импортированной переменной или функции. Генерирование таблицы символов с помощью команды nm и использование grep для поиска переменной позволяет быстро найти информацию о пути.

      Примечание: команда nm не поможет найти путь к переменной, если имя пакета содержит любые символы, кроме символов ASCII, или содержит символ " или %, поскольку это ограничение относится к самому инструменту.

      Для использования этой команды выполните сборку двоичного файла для app:

      После сборки app укажите на него инструменту nm и выполните поиск в результатах:

      • go tool nm ./app | grep app

      Инструмент nm выводит большое количество данных. В связи с этим в предыдущей команде использовался оператор | для передачи результатов в команду grep, которая выполняет поиск терминов с app верхнего уровня в заголовке.

      Результат должен выглядеть примерно так:

      Output

      55d2c0 D app/build.Time 55d2d0 D app/build.User 4069a0 T runtime.appendIntStr 462580 T strconv.appendEscapedRune . . .

      В данном случае первые две строки набора результатов содержат пути к двум переменным, которые вы ищете: app/build.Time и app/build.User.

      Теперь вам известны пути, и вы можете снова выполнить сборку приложения с изменением переменных Version, User и Time во время сборки. Для этого нужно передать несколько флагов -X в -ldflags:

      • go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"

      Вы передали команду Bash id -u -n для вывода текущего пользователя и команду date для вывода текущей даты.

      После сборки исполняемого файла запустите программу:

      В системе Unix эта команда выводит примерно следующие результаты:

      Output

      Version: v1.0.0 build.Time: Fri Oct 4 19:49:19 UTC 2019 build.User: sammy

      Теперь у вас имеется двоичный файл с информацией о версии и сборке, который будет полезен при решении возможных проблем в производственной среде.

      Заключение

      В этом обучающем руководстве показано, как правильно использовать мощный инструмент ldflags для вставки в двоичные файлы ценной информации во время сборки. Так вы можете контролировать флаги функций, информацию о среде, информацию о версиях и другие данные, не внося изменений в исходный код. Использование ldflags в рабочем процессе сборки позволяет в полной мере получить преимущества самодостаточного формата распространения двоичных файлов Go.

      Дополнительную информацию о языке программирования Go можно найти в серии статей и обучающих статей Программирование на Go. Если вам нужно больше решений для контроля версий, воспользуйтесь справочным руководством Использование Git.



      Source link