合并多个 Go 包中的数据库设置,使其只运行一次的方法是什么?
从现在开始,努力学习吧!本文《合并多个 Go 包中的数据库设置,使其只运行一次的方法是什么?》主要讲解了等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!
我正在尝试在数据库中创建一些对象,以便我的测试可以使用一些数据。我已将设置逻辑放入包 testsetup
中。但是,我发现 go test
将每个包作为完全独立的实例运行,因此即使我在 testsetup 包中使用 sync.once
,setup
仍然运行多次,因为每个包的测试作为单独的 go 实例运行。我真的很想继续并行运行我的测试,因为它要快得多,所以我目前不考虑关闭并行化。有没有一种干净的方法可以做到这一点?
此时我什至开始考虑肮脏的黑客攻击,例如使用 shell 脚本来实现操作系统级同步。
这是我的包结构:
testsetup testsetup.go package1 package1.go package1_test.go package2 package2.go package2_test.go
这是我的 testsetup 函数的简化版本:
var onceSetup sync.Once var data model.MockData func Setup() model.MockData { onceSetup.Do(createData) return data } func createData() { // Do some SQL calls to create the objects. We only want to do this once. data = model.Data{ Object1: ..., Object2: ..., } }
正确答案
这是可以做到的,但可能不值得,你必须自己决定。
您将需要一个实现“测试注册表”和“测试运行程序”的包,以及另一个作为“入口点”的包,将它们连接在一起并启动运行程序。
生成的结构可能如下所示:
../module ├── app │ ├── pkg1 │ │ ├── foo.go │ │ ├── ... │ │ └── tests │ │ ├── test_foo.go │ │ ├── ... │ │ └── pkg1_test.go │ └── pkg2 │ ├── ... │ ├── bar.go │ └── tests │ ├── ... │ ├── test_bar.go │ └── pkg2_test.go ├── go.mod ├── internal │ └── testutil │ ├── registry.go # the test registry │ └── runner.go # the test runner └── tests └── start_test.go # the test entrypoint
首先,让我们考虑一下完成后入口点会是什么样子。您可能不喜欢所看到的内容,在这种情况下,您可能应该忽略答案的其余部分。
文件module/tests/start_test.go
:
package tests import ( "testing" // use the blank identifier for "side-effect-only" imports _ "module/app/pkg1/tests" _ "module/app/pkg2/tests" // ... "module/internal/testutil" ) func test(t *testing.t) { testutil.testall(t) }
接下来,module/internal/testutil/registry.go
中的注册表:
package testutil import ( "path/filepath" "runtime" "testing" ) // v: the directory of a package // v: the files in a directory // v: the tests in a file var tests = make(map[string][][]func(*testing.t)) func register(ft ...func(*testing.t)) int { // use the directory of the caller's file // to map the tests. why this can be useful // will be shown later. _, f, _, _ := runtime.caller(1) dir := filepath.dir(f) tests[dir] = append(tests[dir], ft) // this is not necessary, but a function with a return // can be used in a top-level variable declaration which // can be used to avoid unnecessary init() functions. return 0 }
module/internal/testutil/runner.go
中的运行程序:
package testutil import ( "testing" ) func testall(t *testing.t) { // todo setup ... defer func() { // todo teardown ... }() // run for _, dir := range tests { for _, file := range dir { for _, test := range file { test(t) } } } }
现在是单独的包,例如module/app/pkg1/tests/test_foo.go
:
package tests import ( "testing" "module/internal/testutil" ) var _ = testutil.register( testfoo1, testfoo2, ) func testfoo1(t *testing.t) { // ... } func testfoo2(t *testing.t) { // ... }
就是这样,您现在可以转到 module/tests
“入口点”并运行:
go test
附录 #1
如果您想保留单独测试各个包的能力 那么也可以集成。
首先,在 module/internal/testutil/runner.go
中向运行器添加一个新函数:
package testutil import ( // ... "path/filepath" "runtime" ) // ... func testpkg(t *testing.t) { // now the directory of the caller's file // comes in handy. we can use it to make // sure no other tests but the caller's // will get executed. _, f, _, _ := runtime.caller(1) dir := filepath.dir(f) // todo setup ... defer func() { // todo teardown ... }() // run for _, file := range tests[dir] { for _, test := range file { test(t) } } }
并在单独的测试包中添加一个测试文件,例如module/app/pkg1/tests/pkg1_test.go
:
package tests import ( "testing" "module/internal/testutil" ) func test(t *testing.t) { testutil.testpkg(t) }
就是这样,现在您可以将 cd
放入 module/app/pkg1/tests
并运行:
go test
附录#2
现在,各个软件包都有自己的 _test.go
文件,如果您想使用 go 测试模块/...
执行所有中的测试,您就回到了原点。模块,因为这不仅会运行入口点,还会导致单独执行各个测试包。
但是,您可以使用简单的环境变量来解决该问题。只需对 testutil.testpkg
函数进行一个小调整:
package testutil import ( // ... "os" ) // ... func testpkg(t *testing.t) { if os.getenv("skippkg") == "yes" { return } // ... }
现在...
# ... the following will work as you'd expect skippkg=yes go test module/... go test module/tests go test module/app/pkg1/tests
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

- 上一篇
- 虚拟机装mac系统efi(虚拟机装mac系统蓝屏)

- 下一篇
- 嵌套结构元素的访问方法
-
- Golang · Go问答 | 1年前 |
- 在读取缓冲通道中的内容之前退出
- 139浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 戈兰岛的全球 GOPRIVATE 设置
- 204浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将结构作为参数传递给 xml-rpc
- 325浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何用golang获得小数点以下两位长度?
- 477浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何通过 client-go 和 golang 检索 Kubernetes 指标
- 486浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将多个“参数”映射到单个可变参数的习惯用法
- 439浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将 HTTP 响应正文写入文件后出现 EOF 错误
- 357浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 结构中映射的匿名列表的“复合文字中缺少类型”
- 352浏览 收藏
-
- Golang · Go问答 | 1年前 |
- NATS Jetstream 的性能
- 101浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将复杂的字符串输入转换为mapstring?
- 440浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 相当于GoLang中Java将Object作为方法参数传递
- 212浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何确保所有 goroutine 在没有 time.Sleep 的情况下终止?
- 143浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 可图AI图片生成
- 探索快手旗下可灵AI2.0发布的可图AI2.0图像生成大模型,体验从文本生成图像、图像编辑到风格转绘的全链路创作。了解其技术突破、功能创新及在广告、影视、非遗等领域的应用,领先于Midjourney、DALL-E等竞品。
- 31次使用
-
- MeowTalk喵说
- MeowTalk喵说是一款由Akvelon公司开发的AI应用,通过分析猫咪的叫声,帮助主人理解猫咪的需求和情感。支持iOS和Android平台,提供个性化翻译、情感互动、趣味对话等功能,增进人猫之间的情感联系。
- 29次使用
-
- Traini
- SEO摘要Traini是一家专注于宠物健康教育的创新科技公司,利用先进的人工智能技术,提供宠物行为解读、个性化训练计划、在线课程、医疗辅助和个性化服务推荐等多功能服务。通过PEBI系统,Traini能够精准识别宠物狗的12种情绪状态,推动宠物与人类的智能互动,提升宠物生活质量。
- 27次使用
-
- 可图AI 2.0图片生成
- 可图AI 2.0 是快手旗下的新一代图像生成大模型,支持文本生成图像、图像编辑、风格转绘等全链路创作需求。凭借DiT架构和MVL交互体系,提升了复杂语义理解和多模态交互能力,适用于广告、影视、非遗等领域,助力创作者高效创作。
- 31次使用
-
- 毕业宝AIGC检测
- 毕业宝AIGC检测是“毕业宝”平台的AI生成内容检测工具,专为学术场景设计,帮助用户初步判断文本的原创性和AI参与度。通过与知网、维普数据库联动,提供全面检测结果,适用于学生、研究者、教育工作者及内容创作者。
- 46次使用
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- Golang取得代码运行时间的问题
- 2023-02-24 501浏览
-
- 请问 go 代码如何实现在代码改动后不需要Ctrl+c,然后重新 go run *.go 文件?
- 2023-01-08 501浏览
-
- 如何从同一个 io.Reader 读取多次
- 2023-04-11 501浏览