Goose嵌入式迁移报错:sql/schema/目录存在却提示不存在
我正在开发一款CLI工具,期望用户首次运行时自动将所有表迁移至PostgreSQL数据库,但遇到如下报错:
2024/10/30 17:05:01 error applying migrations: error applying migrations: sql/schema/ directory does not exist exit status 1
尽管我的项目目录中确实存在sql/schema/目录。
相关代码
migrate.go文件
package main import ( "database/sql" "embed" "fmt" _ "github.com/lib/pq" "github.com/pressly/goose/v3" ) // Embed the migrations // go:embed sql/schema/*.sql var migrations embed.FS func applyMigrations(db *sql.DB) error { // Set the base file system for Goose to embedded FS goose.SetBaseFS(migrations) if err := goose.SetDialect("postgres"); err != nil { return fmt.Errorf("error setting dialect: %w", err) } // Run migrations if err := goose.Up(db, "sql/schema/"); err != nil { return fmt.Errorf("error applying migrations: %w", err) } return nil }
main.go文件
package main import ( "database/sql" "fmt" "log" "os" _ "github.com/lib/pq" ) func main() { ... db, err := sql.Open("postgres", cfg.DBURL) if err != nil { log.Fatalf("error connecting to db: %v", err) } defer db.Close() // Apply migrations if err := applyMigrations(db); err != nil { log.Fatalf("error applying migrations: %v", err) } ... }
项目结构
. ├── internal │ ├── config │ └── database ├── main.go ├── sql │ ├── queries │ └── schema └── sqlc.yaml
sql/schema目录中存放着SQL表迁移文件,预期迁移能正常执行却报错,请问问题出在哪里?
问题核心是嵌入式文件系统(embed.FS)的路径与Goose调用时的路径不匹配,以下是具体修复方案:
调整Goose调用路径:
你用// go:embed sql/schema/*.sql嵌入的是sql/schema/下的所有SQL文件,此时嵌入式FS的根目录对应项目根目录。当你调用goose.Up(db, "sql/schema/")时,Goose会在嵌入式FS中查找该路径,但嵌入式FS里的文件路径是sql/schema/xxx.sql,并没有单独的sql/schema/目录节点(因为你只嵌入了文件,没嵌入目录本身)。只需把调用改为:
if err := goose.Up(db, "."); err != nil { return fmt.Errorf("error applying migrations: %w", err) }这里的
.代表嵌入式FS的根目录,也就是你嵌入的所有sql/schema/*.sql文件所在的上下文。或者调整embed指令以嵌入目录:
如果你想保留goose.Up(db, "sql/schema/")的调用方式,需要修改embed指令,同时嵌入目录和文件://go:embed sql/schema sql/schema/*.sql var migrations embed.FS这样嵌入式FS中会包含
sql/schema目录节点,Goose就能找到该路径。检查embed指令格式:
确保//go:embed指令与变量声明紧挨着,中间不要有空行,比如://go:embed sql/schema/*.sql var migrations embed.FS(注释和指令可以共存,但指令必须直接在变量上方)
确认编译环境:
确保使用Go 1.16及以上版本(embed特性从Go 1.16开始支持),并且在项目根目录执行编译命令(如go build),这样embed才能正确定位到sql/schema下的文件。
内容的提问来源于stack exchange,提问作者guts_thakur

