golangにおけるcgo freeドライバに関連して

二年ぐらい前には、まだcgoしか無いようなドライバもそこそこ存在してましたが、cgo freeのドライバに変えてコンパイルをすっきりさせた方が良さそうです

cgo freeでは無いドライバが含まれるコードを普通にコンパイルしてラズパイzeroで実行させると、

$ ./rasp_zero
2025/01/12 17:17:17 "Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub": 
	create table foo (id integer not null primary key, name text);
	delete from foo;

と言われるし、cgo対応のlinkerはいまいち不明だし、というわけで以下のリンクのサンプルコード(実は上のエラーメッセージはオリジナルのソースをコンパイルしてます)をcgo freeドライバに入れ替え

https://zenn.dev/teasy/articles/go-sqlite3-sample

github.com/mattn/go-sqlite3

を、

modernc.org/sqlite

に変更して、db openのコードを変更するだけでcgo freeとなって、

% GOOS=linux GOARCH=arm GOARM=6 go build -o rasp_zero

でコンパイルするとラズパイzeroで動くバイナリが出力されます

実はcgo free以外に、M1 Macの動作ではgo run ***では動作しても、./***では起動も終了もしないという不思議な現象が出てましたが、この件も一緒に解決、ただしこの現象ではIntel Macでは出ないという怪しげな現象でした

orm(例えばgormなど)もcgo freeにできるので、今後はcgoが必要なのはおそらくよほどな時になりそうです

<コードは>

sql.open()が変わっただけです

package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"

	_ "modernc.org/sqlite"
)

func main() {
	os.Remove("./foo.db")

	// original
	// db, err := sql.Open("sqlite3", "./foo.db")
	//
	db, err := sql.Open("sqlite", "./foo.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sqlStmt := `
	create table foo (id integer not null primary key, name text);
	delete from foo;
	`
	_, err = db.Exec(sqlStmt)
	if err != nil {
		log.Printf("%q: %s\n", err, sqlStmt)
		return
	}

	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	stmt, err := tx.Prepare("insert into foo(id, name) values(?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	for i := 0; i < 100; i++ {
		_, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i))
		if err != nil {
			log.Fatal(err)
		}
	}
	tx.Commit()

	rows, err := db.Query("select id, name from foo")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		var id int
		var name string
		err = rows.Scan(&id, &name)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(id, name)
	}
	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}

	stmt, err = db.Prepare("select name from foo where id = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var name string
	err = stmt.QueryRow("3").Scan(&name)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(name)

	_, err = db.Exec("delete from foo")
	if err != nil {
		log.Fatal(err)
	}

	_, err = db.Exec("insert into foo(id, name) values(1, 'foo'), (2, 'bar'), (3, 'baz')")
	if err != nil {
		log.Fatal(err)
	}

	rows, err = db.Query("select id, name from foo")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		var id int
		var name string
		err = rows.Scan(&id, &name)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(id, name)
	}
	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}
}

P.S.  2025/1/13

”実はcgo free以外に、M1 Macの動作ではgo run ***では動作しても、./***では起動も終了もしないという不思議な現象が出てました”

この件に関連して、DB(sqlite3)を使う別のコードではビルドもできず、やはりIntel Macでは問題なくビルドできて動作したので、おそらくVenturaのアップデートと関連ありますね

 

admin

コメントを残す