Как связать базу данных SQLite в двоичный файл Go?
Я пытаюсь использовать go-bindata и packr, но эти пакеты не показывают, как упаковать файл базы данных SQLite в двоичный файл.
Мне не нужно обновлять базу данных, я просто хочу прочитать данные при запуске.
Как я могу встроить файл базы данных SQLite в двоичный файл Go?
1 ответ
Драйвер 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 для этого, если хотите, но я не вижу преимущества.
Альтернативный способ - использовать базу данных памяти, которая может быть быстрее в зависимости от того, что вы хотите сделать.
- Внедрите схему SQL и строки, которые вы хотите, в ваш двоичный файл Go как строки.
- Откройте новую базу данных памяти при запуске вашей программы (
sql.Open("sqlite3",
: memory: `) и создайте схему и вставьте строки.
При использовании этого метода нет доступа к диску, поэтому запрос к нему, вероятно, будет немного быстрее при больших затратах времени на запуск (эталонный тест, чтобы быть уверенным!)