Assigner une variable lors de la compilation en Go

21/06/2015

Je viens de faire une release de mon outil idok et je me suis posé cette fameuse question: comment faire pour assigner la version dans mon binaire sans avoir à modifier le code source ? Et bien c’est simple comme tout mais il faut le savoir. Voilà la méthode.

Prenons un exemple de programme dont vous avez assigné une valeur de version et qui l’affiche:

package main

import (
    "fmt"
)

const VERSION="heuuuu"

func main(){
    fmt.Println(VERSION)
}

Le résultat est logiquement:

$ go run main.go
heuuu

Très bien… sauf que là c’est “en dur” et qu’à chaque release je dois penser à monter la version dans le source. Un peu de recherche et je comprends qu’on peut modifier les drapeaux “ld”. En gros, on peut “modifier les variables au moment de l’édition de lien”.

Attention, on ne parle pas de “ld”, l’éditeur de lien GNU, mais de celui de Go !, voir https://golang.org/cmd/ld/ et on voit une ligne très intéressante:

-X symbol value

Set the value of a string variable. The symbol name should be of the form importpath.name, as displayed in the symbol table printed by “go tool nm”.

Et c’est la variable “main.VERSION” qu’on va changer, c’est à dire “la variable VERSION dans le package main”. On va utiliser le drapeau “X” de la librairie “ld”

Cela dit vous devez penser à utiliser une variable et non une constante. Donc on modifie le programme en :

package main

import (
    "fmt"
)

// on met une variable
var VERSION="heuuuu"

func main(){
    fmt.Println(VERSION)
}

Et on va tenter:

$ go run main.go
heuuu
$ go run -ldflags '-X main.VERSION 0.0.1' main.go
0.0.1
$ go run -ldflags '-X main.VERSION alpha1' main.go
alpha1

Du coup, tout devient plus simple. On peut utiliser un Makefile qui utilise, par exemple, git pour avoir le tag en cours:

VERSION:=$(shell git describe --tags)
OPTS:=-ldflags '-X main.VERSION $(VERSION)'

build:
    go build $(OPTS) main.go
    

Reste alors à changer “main.go” pour ajouter la possibilité d’avoir une option -version:

package main

import (
    "flag"
    "fmt"
    "os"
)

// on met une variable - UNDEF 
var VERSION="UNDEF"

func main(){
    v := flag.Bool("version", false, "get the current version:"+ VERSION )
    flag.Parse()
    
    if *version {
        fmt.Println(VERSION)
        os.Exit(0)
    }
    
    fmt.Println("No version flag set...")
}

Et donc:

$ git tag 0.0.1
$ make
$ ./main -version
0.0.1
$ git tag 0.0.2
$ make
$ ./main -version
0.0.2

Quand je vous disais que c’était simple…

Juste une petite note, je n’ai pas trouvé comment assigner autre chose qu’une chaine de caractères… si vous avez la solution, merci de me prévenir que je modifie le billet.

Ça peut vous intéresser aussi


Golang, résoudre le souci d'indexation de type défini

Golang permet de créer ses prores types et notamment de ...


Mise à jour du blog en Go

Si vous connaissiez mon blog, vous avez remarqué qu’à ...


L'intérêt des closures en Go

Vous avez entendu parler des “closures” et “generators”...


Go-Pipe, streamez à la unix/like en Go

Vous connaissiez les “pipelines” de Gulp, et bien voici celles ...

Merci de m'aider à financer mes services

Si vous avez apprécié cet article, je vous serai reconnaissant de m'aider à me payer une petite bière :)

Si vous voulez en savoir plus sur l'utilisation de flattr sur mon blog, lisez cette page: Ayez pitié de moi

Commentaires

Ajouter un commentaire

Ajouter un commentaire

(*) Votre e-mail ne sera ni revendu, ni rendu public, ni utilisé pour vous proposer des mails commerciaux. Il n'est utilisé que pour vous contacter en cas de souci avec le contenu du commentaire, ou pour vous prévenir d'un nouveau commentaire si vous avez coché la case prévue à cet effet.