使用Dockertest配置Golang SQL单元测试时遇EOF连接错误
解决Dockertest连接PostgreSQL时的"Error: EOF"问题
出现"Error: EOF"通常是因为数据库容器未正常启动、端口映射错误,或者连接时数据库服务还未就绪。针对你的代码,主要问题出在硬绑定固定端口和端口获取方式错误,以下是具体修复方案:
关键修复点
- 移除硬编码的固定端口,改用Dockertest动态分配端口,避免端口冲突
- 通过容器实例获取实际映射的端口,确保连接到正确的端口
- 可选:增加重试次数,适配数据库启动的耗时
修改后的代码
1. 调整全局变量
去掉固定的port变量,改为动态获取:
var ( host = "localhost" user = "postgres" password = "postgres" dbName = "db_test" dsn = "host=%s port=%s user=%s password=%s dbname=%s sslmode=disable timezone=UTC connect_timeout=30" )
2. 修改容器启动与端口获取逻辑
在启动容器后,通过resource.GetPort获取实际映射的端口:
func TestMain(m *testing.M) { // connect to docker; fail if docker not running p, err := dockertest.NewPool("") if err != nil { log.Fatalf("could not connect to docker; is it running? %s", err) } pool = p // 可选:增加重试次数,确保等待数据库完全启动 pool.MaxRetries = 10 opts := dockertest.RunOptions{ Repository: "postgres", Tag: "14.5", // same as docker compose Env: []string{ "POSTGRES_USER=" + user, "POSTGRES_PASSWORD=" + password, "POSTGRES_DB=" + dbName, }, ExposedPorts: []string{"5432"}, // 移除硬绑定的HostPort,让Docker自动分配可用端口 PortBindings: map[docker.Port][]docker.PortBinding{ "5432": { {HostIP: "0.0.0.0"}, }, }, } resource, err = pool.RunWithOptions(&opts) if err != nil { log.Fatalf("could not start resource: %s", err) } // 获取容器实际映射的5432端口 port := resource.GetPort("5432/tcp") if err := pool.Retry(func() error { var err error testDB, err = sqlx.Connect("postgres", fmt.Sprintf(dsn, host, port, user, password, dbName)) if err != nil { log.Println("Error:", err) return err } return testDB.Ping() }); err != nil { _ = pool.Purge(resource) log.Fatalf("could not connect to database: %s", err) } err = createTables() if err != nil { log.Fatalf("error creating tables: %s", err) } testRepo = &repo{db: testDB} code := m.Run() if err := pool.Purge(resource); err != nil { log.Fatalf("could not purge resource: %s", err) } os.Exit(code) }
其他排查建议
- 检查本地原固定端口(如5437)是否被其他进程占用:Linux/macOS用
lsof -i :5437,Windows用netstat -ano | findstr :5437 - 查看容器日志确认Postgres状态:
docker logs <容器ID>,日志出现database system is ready to accept connections说明服务就绪
内容的提问来源于stack exchange,提问作者Jessica
相关产品推荐
相关产品推荐

