您的位置:

学会使用gosqlite3

在Web开发中,我们经常需要将数据存储到数据库中以便进行管理和处理。gosqlite3是一个轻量级的sqlite3驱动,它为Golang提供了快速、稳定的sqlite3支持。在本篇文章中,我们将从以下几个方面对gosqlite3进行详细阐述:
1. 安装gosqlite3
2. 基本使用
3. 数据库连接及操作
4. 执行事务
5. 并发使用

一、安装gosqlite3

在进行gosqlite3的使用前,我们需要先进行安装。

步骤1:安装sqlite3

sudo apt-get install sqlite3

步骤2:安装gosqlite3

go get github.com/mattn/go-sqlite3

安装完成后,我们就可以开始使用gosqlite3进行开发了。

二、基本使用

下面是一个简单的例子,演示了如何使用gosqlite3进行数据库的连接和操作:

package main

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

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

func main() {
	db, err := sql.Open("sqlite3", "test.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)
		}
		log.Println(id, name)
	}
	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}
}

这段代码首先创建了一个名为test.db的sqlite3数据库。然后,它创建了一个名为foo的表,插入了100条记录并输出了表中的所以记录。在这个例子中,我们看到了gosqlite3的基本数据类型支持和如何执行SQL语句。

三、数据库连接及操作

对于一个应用程序来说,连接数据库是一个非常关键的步骤。在gosqlite3中,我们可以使用Open方法来连接数据库。数据库连接器会在使用完毕后自动关闭。此外,在进行查询或修改时,还需要使用Transaction。下面的代码演示了如何进行数据库查询和修改:

package main

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

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

func main() {
	db, _ := sql.Open("sqlite3", "./test.db")
	defer db.Close()

	// 查询数据
	rows, _ := db.Query("select id, name from people")
	defer rows.Close()

	for rows.Next() {
		var id int
		var name string
		rows.Scan(&id, &name)
		fmt.Printf("id=%d, name='%s'\n", id, name)
	}

	// 插入数据
	stmt, _ := db.Prepare("insert into people(name) values(?)")
	defer stmt.Close()

	res, _ := stmt.Exec("Tom")
	id, _ := res.LastInsertId()
	fmt.Printf("ID of inserted row is %d\n", id)

	// 删除数据
	stmt, _ = db.Prepare("delete from people where name=?")
	defer stmt.Close()

	res, _ = stmt.Exec("Tom")
	num, _ := res.RowsAffected()
	fmt.Printf("%d row(s) deleted\n", num)
}

四、执行事务

在gosqlite3中执行事务非常简单。通过调用Begin方法,我们可以开启一个事务。在事务中,执行的所有SQL语句都将作为一个整体来进行提交或回滚。下面的代码演示了如何使用事务:

package main

import (
	"database/sql"
	"log"

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

func main() {
	db, _ := sql.Open("sqlite3", "./test.db")
	defer db.Close()

	tx, _ := db.Begin()
	stmt, _ := tx.Prepare("insert into people(name) values(?)")
	defer stmt.Close()

	for i := 0; i < 10; i++ {
		_, err := stmt.Exec(fmt.Sprintf("user-%d", i))
		if err != nil {
			log.Fatal(err)
		}
	}
	tx.Commit()

	rows, _ := db.Query("select id, name from people")
	defer rows.Close()

	for rows.Next() {
		var id int
		var name string
		rows.Scan(&id, &name)
		log.Println(id, name)
	}
}

五、并发使用

在Web应用中,我们经常需要在多个Goroutine中同时进行数据库操作。gosqlite3的设计支持并发使用。但是,需要注意的是:不要在多个线程中共享同一个*sql.DB对象,否则会导致不可预期的问题。下面的代码演示了如何在多个Goroutine中同时使用gosqlite3:

package main

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

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

func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done()

	db, _ := sql.Open("sqlite3", "./test.db")

	tx, _ := db.Begin()
	stmt, _ := tx.Prepare("insert into people(name) values(?)")

	for i := 0; i < 10; i++ {
		stmt.Exec(fmt.Sprintf("user-%d-%d", id, i))
	}

	stmt.Close()
	tx.Commit()

	rows, _ := db.Query("select count(*) from people")
	defer rows.Close()

	var count int
	rows.Next()
	rows.Scan(&count)
	log.Printf("worker%d count=%d", id, count)

	db.Close()
}

func main() {
	db, _ := sql.Open("sqlite3", "./test.db")
	db.Exec("create table if not exists people(id integer primary key, name text)")

	var wg sync.WaitGroup
	for i := 1; i <= 10; i++ {
		wg.Add(1)
		go worker(i, &wg)
	}

	wg.Wait()
}

在这个例子中,我们分别创建了10个Goroutine去并发地插入数据到表people中。在主函数中,我们使用sync.WaitGroup来等待所有的Goroutine执行完毕。最后,我们查询表people中的记录数并输出。