ldflags и информация о версии CLI | Go Theme Month

Go
ldflags и информация о версии CLI | Go Theme Month

ПисатьcliУ программистов должна возникнуть проблема, как записать информацию о версии в программу и окончательный исполняемый двоичный файл, чтобы достичьcli -vилиcli --versionМожно ли отобразить эффект информации о версии?

手动写入или使用构建脚本это то, что я делал раньше, но сегодня я нашел еще один хороший способ, который заключается в использовании-ldflagsУстановите значение переменной.

написать вручную

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

Используйте скрипты сборки

У меня обычно есть один в моем проектеMakefileфайл, черезmakeЭто может помочь нам интегрировать шаги, необходимые для строительства, тестирования и других операций, а затем нужно только использоватьmake buildилиmake testВы можете построить или протестировать, следующее простоеMakefile:

.PHONY build test

build:
    go build -o cli main.go
    
test:
    go test .

В это время я будуMakefileНапишите следующее, чтобы установить информацию о версии:

VERSION = $(shell git tag --sort=committerdate | tail -n 1)

version:
    sed -i "s/version = \".*\"/version = \"$(VERSION)\"/g" pkg/cmd/version.go

pkg/cmd/version.goЕсть такой кусок кода:

const version = "dev"

-ldflagsиграть в

-ldflagsМожет помочь нам установить значения переменных, нам нужно только определить переменные в исходном файле Go.

например, вmain.goВ файле определены три переменные, относящиеся к информации о версии:

package main

var (
    version string
    commit  string
    date    string
)

func main() {
    args := os.Args
    if len(args) == 2 && (args[1] == "--version" || args[1] == "-v") {
        fmt.Printf("Release version: %s\n", version)
        fmt.Printf("Git commit: %s\n", commit)
        fmt.Printf("Build date: %s\n", date)
        return
    }
    
    ...
}

потомMakefileСкрипт сборки пишется так:

NAME := cli
CGO_ENABLED = 0
BUILD_GOOS = $(shell go env GOOS)
GO := go
BUILD_TARGET = build
COMMIT := $(shell git rev-parse --short HEAD)
VERSION := dev-$(shell git describe --tags $(shell git rev-list --tags --max-count=1))
BUILD_FLAGS = -ldflags "-X main.version=$(VERSION) \
	-X main.commit=$(COMMIT) \
	-X main.date=$(shell date +'%Y-%m-%d')"
MAIN_SRC_FILE = main.go

.PHONY: build

build: pre-build
    GO111MODULE=on CGO_ENABLED=$(CGO_ENABLED) GOOS=$(BUILD_GOOS) GOARCH=amd64 $(GO) $(BUILD_TARGET) $(BUILD_FLAGS) -o bin/$(BUILD_GOOS)/$(NAME) $(MAIN_SRC_FILE)
    chmod +x bin/$(BUILD_GOOS)/$(NAME)
    rm -rf $(NAME) && ln -s bin/$(BUILD_GOOS)/$(NAME) $(NAME)

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