Golang中如何使用`go get`安装时指定不同的可执行文件名?

Golang中如何使用go get安装时指定不同的可执行文件名? 在使用 go get 安装时,是否可以使用不同的可执行文件名称? 我知道 go build 有一个 -o 标志可以使用,但对于我的软件包的用户来说呢。

背景是公司仓库强制要求 Git 仓库的命名规范。 类似于 git.company.com/pkg/GoPkg-Name 但这会破坏 go get 的使用。

go: git.company.com/pkg/GoPkg-MyTool.git upgrade => v0.0.0-20210121150345-6241afcc3125
go get: git.company.com/pkg/GoPkg-MyTool.git@v0.0.0-20210121150345-6241afcc3125: parsing go.mod:
	module declares its path as: git.company.com/pkg/mytool
	        but was required as: git.company.com/pkg/GoPkg-MyTool.git

如果能够使用 go get 并让它将工具安装为 mytool,而无需经过更多手动步骤(例如 mv GoPkg-MyTool mytool),那就太好了。


更多关于Golang中如何使用`go get`安装时指定不同的可执行文件名?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

go mod replace … 请自行搜索。

更多关于Golang中如何使用`go get`安装时指定不同的可执行文件名?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


h3adache:

我99%确定你没有阅读。

我100%确定你没有阅读。

你引用的资料日期是2017年3月9日。而关于Go模块的首次公开提及直到2018年2月20日才出现。

我 99% 确定你没看,不过没关系。

stackoverflow.com

如何构建名称不同于 Go 语言包的可执行文件

标签: go, build, package, naming-conventions

看来对于 go get 来说,没有方法可以做到这一点。 我只能接受让人们手动重命名,或者直接分发二进制文件了。

提醒一下正在尝试此操作的人。 不要像我一样,试图通过 mod replace 让它工作,这行不通,只会让你抓耳挠腮。 请采用 https://github.com/bazelbuild/buildtools 所使用的方法,将你的工具放入以工具命名的子目录中。 我犯了一个错误,试图让我的仓库名称与工具名称相同。 这种方法对公共和私有仓库都有效,唯一的例外是对于私有仓库,你必须添加 .git 后缀。 因此,在我上面的例子中,你可以在实际工具所在的位置创建一个 mytool 子目录,用户可以通过以下方式安装它:

go get git.company.com/pkg/GoPkg-MyTool.git/mytool

在Go模块系统中,go get安装的可执行文件名由模块路径的最后一个元素决定,但可以通过在go.mod文件中使用replace指令结合自定义构建来解决。以下是具体方案:

方案1:使用replace指令(推荐)

在用户项目的go.mod中添加replace指令,将不符合规范的路径映射到正确的模块路径:

// 用户项目的go.mod
module myproject

go 1.21

require (
    git.company.com/pkg/mytool v0.1.0
)

replace git.company.com/pkg/mytool => git.company.com/pkg/GoPkg-MyTool.git v0.1.0

然后用户可以通过以下方式安装:

# 安装到$GOPATH/bin
go install git.company.com/pkg/mytool@latest

# 或者安装到当前目录
go install git.company.com/pkg/mytool@latest

方案2:包维护者提供安装脚本

包维护者可以在仓库中提供安装脚本:

#!/bin/bash
# install.sh
set -e

# 临时目录
TMP_DIR=$(mktemp -d)
cd "$TMP_DIR"

# 克隆仓库
git clone https://git.company.com/pkg/GoPkg-MyTool.git
cd GoPkg-MyTool

# 构建并安装为mytool
go build -o mytool ./cmd/mytool
sudo mv mytool /usr/local/bin/

# 清理
cd /
rm -rf "$TMP_DIR"

方案3:使用go install的@version语法

用户可以直接指定版本安装:

# 安装特定版本
go install git.company.com/pkg/GoPkg-MyTool.git/cmd/mytool@v0.1.0

# 安装最新版本
go install git.company.com/pkg/GoPkg-MyTool.git/cmd/mytool@latest

方案4:包内使用build tags控制输出名称

包维护者可以在main.go中添加构建约束:

//go:build rename
// +build rename

package main

import (
    "fmt"
    "os"
)

func main() {
    // 程序逻辑
    fmt.Println("Running as mytool")
}

然后用户可以通过构建标签控制输出名称:

go build -tags rename -o mytool .

方案5:使用go generate

包维护者可以在代码中添加go generate指令:

//go:generate sh -c "go build -o mytool ."

用户执行:

go generate ./...

实际示例

假设包结构如下:

GoPkg-MyTool/
├── cmd/
│   └── mytool/
│       └── main.go
├── go.mod
└── README.md

go.mod内容:

module git.company.com/pkg/mytool

go 1.21

用户安装时使用:

# 方法1:使用完整路径
go install git.company.com/pkg/GoPkg-MyTool.git/cmd/mytool@latest

# 方法2:配置replace后
echo 'replace git.company.com/pkg/mytool => git.company.com/pkg/GoPkg-MyTool.git v0.1.0' >> go.mod
go install git.company.com/pkg/mytool@latest

安装后,可执行文件将命名为mytool(来自cmd/mytool目录名),而不是GoPkg-MyTool

回到顶部