为了账号安全,请及时绑定邮箱和手机立即绑定

如何将 SQLite 数据库捆绑到 Go 二进制文件中?

如何将 SQLite 数据库捆绑到 Go 二进制文件中?

Go
芜湖不芜 2023-07-10 14:43:24
我尝试使用 go-bindata 和 packr,但这些包没有显示如何将 SQLite 数据库文件打包到二进制文件中。我不需要以任何方式更新数据库,我只想在启动时从中读取数据。如何将 SQLite 数据库文件嵌入到 Go 二进制文件中?
查看完整描述

1 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

SQLite 驱动程序无法从内存(例如从字节片)读取数据库文件。但是您可以将数据写入临时文件,然后打开该文件:


//go:generate go run gen.go


package main


import (

    "database/sql"

    "fmt"

    "io/ioutil"

    "log"

    "os"


    _ "github.com/mattn/go-sqlite3"

)


func main() {

    // Create temporary file for database.

    tmpDB, err := ioutil.TempFile("", "db*.sqlite3")

    if err != nil {

        log.Fatal(err)

    }

    // Remove this file after on exit.

    defer func() {

        err := os.Remove(tmpDB.Name())

        if err != nil {

            log.Print(err)

        }

    }()


    // Write database to file.

    _, err = tmpDB.Write(sqlDB)

    if err != nil {

        log.Print(err)

    }

    err = tmpDB.Close()

    if err != nil {

        log.Print(err)

    }


    // Open DB.

    db, err := sql.Open("sqlite3", tmpDB.Name()+"?mode=ro")

    if err != nil {

        log.Fatal(err)

    }


    // Make sure it's loaded correct.

    rows, err := db.Query("select * from test")

    if err != nil {

        log.Fatal(err)

    }


    for rows.Next() {

        var c string

        err := rows.Scan(&c)

        if err != nil {

            log.Fatal(err)

        }

        fmt.Println(c)

    }

}

db.go您可以使用以下内容写入数据库:


// +build generate


package main


import (

    "fmt"

    "io/ioutil"

    "log"

    "os"

    "strings"

)


func main() {

    // Read source database file.

    d, err := ioutil.ReadFile("source.sqlite3")

    if err != nil {

        log.Fatal(err)

    }


    fp, err := os.Create("db.go")

    if err != nil {

        log.Fatal(err)

    }


    _, err = fmt.Fprintf(fp, "// Code generated by gen.go; DO NOT EDIT.\n\n"+

        "package main\n\n"+

        "var sqlDB = %s\n", asbyte(d))

    if err != nil {

        log.Fatal(err)

    }

}


// Write any data as byte array.

func asbyte(s []byte) string {

    var b strings.Builder

    for i, c := range s {

        if i%19 == 0 {

            b.WriteString("\n\t\t")

        }

        b.WriteString(fmt.Sprintf("%#x, ", c))

    }

    return "[]byte{" + b.String() + "}"

}

如果您愿意,也可以使用 go-bindata 或 packr,但我并没有真正看到优势。

另一种方法是使用内存数据库,这可能会更快,具体取决于您想要执行的操作。

  1. 将您想要的 SQL 架构和行作为字符串嵌入到 Go 二进制文件中。

  2. 当程序启动时打开一个新的内存数据库(sql.Open("sqlite3",:memory:`)并创建模式并插入行。

此方法没有磁盘访问,因此查询它可能会更快一点,但代价是启动时间较慢(当然是基准!)



查看完整回答
反对 回复 2023-07-10
  • 1 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信