我尝试使用go-bindata和packr,但是这些软件包没有显示如何将SQLite数据库文件打包为二进制文件。
我不需要以任何方式更新数据库,我只想在启动时从中读取数据。
如何将SQLite数据库文件嵌入Go二进制文件中?
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:
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,但是我看不出有什么优势。
另一种方法是使用内存数据库,该数据库 可能 会更快,具体取决于您要执行的操作。
sql.Open("sqlite3",
此方法无法访问磁盘,因此以较慢的启动时间为代价,查询它可能会快一点(请确保使用基准测试!)。