Go: Definindo informações usando ldflags

Tags: Go, pt-BR

Como definir informações como versão, datas etc usando -ldflags.

Obs: todo o código usado aqui está neste repositório.

A Situação

Estava começando um novo projeto em Go, e decidi ter disponíveis, nos logs, informações a respeito da minha API, como qual a versão, data de quando foi feito o binário etc. Algo como o exemplo abaixo:

{
    "level": "info",
    "ts": 1710513266.1966991,
    "caller": "code/main.go:12",
    "msg": "application up and running",
    "app_name": "Payments API",
    "app_version": "develop",
    "app_build_at": "Today"
}

A Solução

Uma forma de atingir isso é usando -ldflags no momento de criação do binário (a famosa “build”). Em Go, podemos usar esse recurso para definir informações únicas nessa etapa, que ficarão marcadas no binário final.

Para essa tarefa, utilizei go.uber.org/zap para logs (mas pode ser qualquer outra lib da sua escolha).

Primeiro, criei o lugar onde as informações estarão:

package appinfo

const (
    AppName string = "Payments API"
)

var (
    AppVersion string = "develop"
    AppBuildAt string = "Today"
)

Como não quero mudar o valor de AppName, criei-o como uma constante. Mas os valores de AppVersion e AppBuildAt serão alterados, no entanto, defini valores apenas para usar como padrão (por exemplo, executando apenas com go run).

Os logs, providenciei sem muitos detalhes, porém adicionei os valores de informação como campos padrão nos logs:

package logger

import (
    "github.com/devdrops/ldflags/appinfo"

    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

func InitGlobalLogger() {
    logger, _ := zap.NewProduction(zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
    defer logger.Sync()

    logger = logger.With(
        zap.String("app_name", appinfo.AppName),
        zap.String("app_version", appinfo.AppVersion),
        zap.String("app_build_at", appinfo.AppBuildAt),
    )

    zap.ReplaceGlobals(logger)
}

E para finalizar, criei a entrada do projeto:

package main

import (
	  "github.com/devdrops/ldflags/logger"

	  "go.uber.org/zap"
)

func main() {
	  logger.InitGlobalLogger()

	  zap.L().Info("application up and running")
}

Agora, usando -ldflags no momento de “build”, eu posso definir valores diferentes para AppVersion e AppBuildAt:

go build -ldflags "-X github.com/devdrops/ldflags/appinfo.AppBuildAt=$(date +%Y-%m-%dT%H:%M:%S_GMT%Z) -X github.com/devdrops/ldflags/appinfo.AppVersion=$GIT_TAG" main.go

Nota: $GIT_TAG pode ser qualquer variável que tenha a referência que você quer (commit, tag etc).

Com isso, o resultado de go build vai exibir o log com as informações passadas, como abaixo:

{
    "level": "info",
    "ts": 1710513834.6334388,
    "caller": "code/main.go:12",
    "msg": "application up and running",
    "app_name": "Payments API",
    "app_version": "v1.2.3",
    "app_build_at": "2024-03-15T14:43:41_GMTUTC"
}

Post anterior:


Davi Marcondes Moreira avatar
Sobre Davi Marcondes Moreira
Desenvolvedor de software, palestrante, evangelista de trabalho remoto e home office, amante de MTB/XCO e entusiasta de café. Ele/Dele. Leia mais