英文:
Golang test hanging
问题
我最近修改了我的应用程序,并发现测试开始出现了卡住的情况。以下是简化后的测试代码:
package app_test
import (
"testing"
"github.com/kargirwar/prosql-go/db"
)
func TestApp(t *testing.T) {
db.SetDbPath("")
}
db 包的代码如下:
package db
import (
"os"
"context"
"database/sql"
_ "github.com/mattn/go-sqlite3"
"path/filepath"
)
var dbPath string
func SetDbPath(path string) {
dbPath = path
}
func OpenDb(ctx context.Context, db string) (*sql.DB, error) {
db = filepath.Join(dbPath, db)
_, err := os.OpenFile(db, os.O_RDWR, 0600)
if err != nil {
return nil, err
}
return sql.Open("sqlite3", "file:"+db+"?_foreign_keys=true")
}
我追踪到了这个依赖项:
_ "github.com/mattn/go-sqlite3"
如果我将其注释掉,测试就可以正常运行,否则就会卡住。奇怪的是,go run
命令可以正常工作。谷歌说 go-sqlite3
需要一些时间来编译,但是为什么 go run
正常运行呢?
英文:
I modified my app recently and found that tests started hanging. This the stripped down test code:
package app_test
import (
"testing"
"github.com/kargirwar/prosql-go/db"
)
func TestApp(t *testing.T) {
db.SetDbPath("")
}
The db package is as follows:
package db
import (
"os"
"context"
"database/sql"
_ "github.com/mattn/go-sqlite3"
"path/filepath"
)
var dbPath string
func SetDbPath(path string) {
dbPath = path
}
func OpenDb(ctx context.Context, db string) (*sql.DB, error) {
db = filepath.Join(dbPath, db)
_, err := os.OpenFile(db, os.O_RDWR, 0600)
if err != nil {
return nil, err
}
return sql.Open("sqlite3", "file:"+db+"?_foreign_keys=true")
}
I traced down the problem to this dependency:
_ "github.com/mattn/go-sqlite3"
If I comment this out then the test runs fine, otherwise it hangs.
Strangely go run works just fine. Google says go-sqlite3 takes time to compile but then why is go run working normally?
答案1
得分: 2
sqlite3包使用cgo。第一次引用sqlite3包时,相关的sqlite3 C代码会被编译并缓存以供后续使用。
以下是一些命令行输出的示例:
$ cat x.go
package main
import _ "github.com/mattn/go-sqlite3"
func main(){}
$ cat x_test.go
package main
import "testing"
func TestSQLite(t *testing.T) {}
$ go clean -cache
$ time go run -v x.go
github.com/mattn/go-sqlite3
command-line-arguments
real 0m41.378s
user 0m41.176s
sys 0m1.353s
$ time go run -v x.go
real 0m0.506s
user 0m0.571s
sys 0m0.209s
$ go clean -cache
$ time go build -v x.go
github.com/mattn/go-sqlite3
real 0m41.038s
user 0m40.779s
sys 0m1.280s
$ time go build -v x.go
real 0m0.239s
user 0m0.379s
sys 0m0.101s
$ go clean -cache
$ time go test -v x.go x_test.go
=== RUN TestSQLite
--- PASS: TestSQLite (0.00s)
PASS
ok command-line-arguments 0.003s
real 0m42.751s
user 0m44.702s
sys 0m2.097s
$ time go test -v x.go x_test.go
=== RUN TestSQLite
--- PASS: TestSQLite (0.00s)
PASS
ok command-line-arguments 0.002s
real 0m0.618s
user 0m0.752s
sys 0m0.306s
英文:
The sqlite3 package uses cgo. The first time the sqlite3 package is referenced, the associated sqlite3 C code is compiled and cached for later use.
$ cat x.go
package main
import _ "github.com/mattn/go-sqlite3"
func main(){}
$ cat x_test.go
package main
import "testing"
func TestSQLite(t *testing.T) {}
$ go clean -cache
$ time go run -v x.go
github.com/mattn/go-sqlite3
command-line-arguments
real 0m41.378s
user 0m41.176s
sys 0m1.353s
$ time go run -v x.go
real 0m0.506s
user 0m0.571s
sys 0m0.209s
$ go clean -cache
$ time go build -v x.go
github.com/mattn/go-sqlite3
real 0m41.038s
user 0m40.779s
sys 0m1.280s
$ time go build -v x.go
real 0m0.239s
user 0m0.379s
sys 0m0.101s
$ go clean -cache
$ time go test -v x.go x_test.go
=== RUN TestSQLite
--- PASS: TestSQLite (0.00s)
PASS
ok command-line-arguments 0.003s
real 0m42.751s
user 0m44.702s
sys 0m2.097s
$ time go test -v x.go x_test.go
=== RUN TestSQLite
--- PASS: TestSQLite (0.00s)
PASS
ok command-line-arguments 0.002s
real 0m0.618s
user 0m0.752s
sys 0m0.306s
$
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论