Golang测试与示例代码实践指南
Golang测试与示例代码实践指南 我有一个项目,其简化结构如下:
chessImager
..
examples (文件夹)
tests (文件夹)
...
chessImager.go
...
如果我在 tests 文件夹中运行 go test ./...,所有测试都能正常工作。但是,如果我在 chessImager 文件夹中运行 go test ./...,则会收到以下错误:
# github.com/Hultan/chessImager/examples
examples/medium.go:10:6: main redeclared in this block
examples/advanced.go:10:6: other declaration of main
examples/other.go:10:6: main redeclared in this block
examples/advanced.go:10:6: other declaration of main
examples/simple.go:10:6: main redeclared in this block
examples/advanced.go:10:6: other declaration of main
? github.com/Hultan/chessImager [no test files]
ok github.com/Hultan/chessImager/test 1.997s
FAIL
examples 文件夹不包含任何可测试文件(*_test.go),那么为什么会抱怨这个文件夹呢?我是否应该为每个示例创建子文件夹,以避免此类问题?
我的项目:
ChessImager 是一个 Go 包,它根据 FEN 字符串创建棋盘图像。它具有高度可配置性,因此您可以创建外观完全符合您期望的棋盘图像…
更多关于Golang测试与示例代码实践指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
Go test 在使用通配符语法时,也会尝试构建所有包,正如您所做的那样。如果您不希望它尝试构建 main 包,那么您必须逐个指定包。
更多关于Golang测试与示例代码实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是因为示例目录中的所有文件都被声明为 package main 并且属于同一个包。Go 会尝试将它们一起编译,但当它第二次遇到 main 时就会失败。我建议在示例目录中为每个包含 main 函数的示例创建一个子目录。
Go 测试在使用通配符语法指定时,也会尝试构建所有包。如果你不希望它尝试构建主包,那么你必须逐个指定包。
那么这就是此行为的原因。
我之前提到了 examples_test.go,但该测试文件在测试文件中包含了示例代码的副本,因此不应触发构建 examples 文件夹。我第一次回复时手头没有代码。
感谢帮助…
我理解那部分,让我澄清一下我的问题。
示例文件夹中没有可测试的文件(没有以 _test 结尾的文件),所以我想知道的是,为什么它甚至要尝试编译那个文件夹?
我以为它会寻找测试文件,然后编译测试所需的内容?
就在我写下上一句话时,我想我意识到问题所在了。我有一个名为 examples_test.go 的文件,它测试示例是否正常工作。这个测试肯定触发了对示例文件夹的编译。
所以,你建议为每个示例使用子文件夹应该能解决这个问题……谢谢……
问题在于 examples 目录下包含多个 main 函数,当 Go 工具链尝试编译整个包时会产生冲突。go test ./... 会递归编译所有子目录,而 examples 目录被当作一个独立的包处理。
解决方案
1. 为每个示例创建独立子目录(推荐)
examples/
├── simple/
│ ├── main.go
│ └── go.mod
├── medium/
│ ├── main.go
│ └── go.mod
└── advanced/
├── main.go
└── go.mod
每个子目录都需要自己的 go.mod:
// examples/simple/go.mod
module github.com/Hultan/chessImager/examples/simple
go 1.21
replace github.com/Hultan/chessImager => ../..
require github.com/Hultan/chessImager v0.0.0
2. 使用构建标签隔离示例
在每个示例文件顶部添加构建标签:
// examples/simple.go
//go:build example_simple
package main
func main() {
// 简单示例代码
}
// examples/medium.go
//go:build example_medium
package main
func main() {
// 中等示例代码
}
然后通过标签单独运行:
go run -tags=example_simple examples/simple.go
3. 使用 _test 后缀重命名示例文件
将示例文件重命名为 *_example_test.go,Go 测试工具会将其视为示例代码:
// examples/simple_example_test.go
package examples_test
import (
"fmt"
"testing"
)
func ExampleSimple() {
fmt.Println("Simple example output")
// Output: Simple example output
}
4. 排除 examples 目录测试
在根目录创建 .go.test 配置文件:
// .go.test
{
"exclude": [
"examples"
]
}
或者使用命令行排除:
go test ./... -exclude ./examples
实际修复示例
基于你的项目结构,建议采用方案1:
# 重构 examples 目录
mkdir -p examples/{simple,medium,advanced,other}
# 移动文件并添加 go.mod
mv examples/simple.go examples/simple/main.go
mv examples/medium.go examples/medium/main.go
mv examples/advanced.go examples/advanced/main.go
mv examples/other.go examples/other/main.go
# 为每个示例创建 go.mod
for dir in simple medium advanced other; do
cat > examples/$dir/go.mod << EOF
module github.com/Hultan/chessImager/examples/$dir
go 1.21
replace github.com/Hultan/chessImager => ../..
require github.com/Hultan/chessImager v0.0.0
EOF
done
这样修改后,go test ./... 将正常工作,同时保持示例代码的可执行性。

