Injection de variables à la compilation en Go : utilisation de go build -ldflags -X

Contexte
Lors de mon travail sur un projet d'entreprise, j'ai cherché une méthode permettant d'injecter des variables au moment de la compilation sans utiliser de fichier .env.
Je pensais que cela serait très pratique, car un seul fichier suffirait, sans avoir besoin de .env ni de plusieurs fichiers de configuration.
Au départ, j'ai cherché un outil CLI de type go:generate qui générerait un fichier de constantes à partir d'un .env, mais je n'en ai pas trouvé.
Toutefois, dans ce cas, il suffisait de modifier directement les constantes, sans avoir à passer par une étape de génération fastidieuse. J'ai alors découvert, en Rust, des moyens d'injecter des valeurs au moment de la compilation, comme la macro include_bytes!.
Injection de variables au moment de la compilation
L'utilisation est simple.
1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8 fmt.Println(Foo)
9}
Pour le code ci-dessus, il est possible d'injecter une valeur lors de la compilation de la manière suivante.
1go build -ldflags="-X 'main.Foo=bar'"
En transmettant un argument via ldflags, la valeur bar est injectée dans la variable Foo au moment de la compilation. C'est simple.
Si plusieurs packages ou variables portant le même nom existent dans le projet, il suffit de spécifier le chemin du package.
1// github.com/myproject/config/config.go
2package config
3
4var Version string
5
6// github.com/myproject/internal/config/config.go
7package config
8
9var BuildTime string
Dans ce cas, il est possible d'effectuer l'injection en les distinguant de la manière suivante :
1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"
Lorsque plusieurs variables se trouvent dans le même package, il suffit de transmettre des arguments supplémentaires.
1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"
Les caractéristiques sont les suivantes :
- Il n'est pas nécessaire que la variable soit publique : une variable commençant par une minuscule peut également être injectée.
- Seul le type string est pris en charge : les autres types ne sont pas supportés.