You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Goose嵌入式迁移报错:sql/schema/目录存在却提示不存在

问题:Goose迁移报错“sql/schema/ directory does not exist”(实际目录存在)

我正在开发一款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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:32:03