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

标签 go

我尝试使用 go-bindata 和 packr,但这些包没有显示如何将 SQLite 数据库文件打包到二进制文件中。

我不需要以任何方式更新数据库,我只想在启动时从中读取数据。

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

最佳答案

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

//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:`) 并创建架构并插入行。

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

关于go - 如何将 SQLite 数据库捆绑到 Go 二进制文件中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58154936/

相关文章:

go - 如何将 magickWand 引用传递给函数

arrays - 如何在 Go 中连接两个数组

戈朗 : Bigquery Check Unique Key before Inserting

testing - 如何测试 panic ?

go - golang 中的长查询

go - 接口(interface)类型中的新功能不起作用

Go 版本 1.17.6 对于该版本的 Delve 来说太旧了(最低支持版本 1.18,使用 --check-go-version=false 抑制此错误)

go - 终端命令中的以下参数是什么意思 : ./

goimports 需要忽略 vendor 包

json - 将 map 值组合成一个json?