1. 前言在实际的开发中,操作数据库是必不可少的环节。 Go语言通过标准库database/sql
以及相对应的数据库驱动第三方库,让数据库操作变得简明而强大。 本文中,我们将会学习安装MySQL数据库驱动,以及如何进行增删查改(CRUD)操作。
2. 安装MySQL数据库驱动1 go get -u github.com/go-sql-driver/mysql
3. 打开数据库连接使用sql.Open
函数和 MySQL DSN 打开一个数据库连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package mainimport ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) func main () { dsn := "root:mysql123@tcp(192.168.50.133:3306)/mysql" db, err := sql.Open("mysql" , dsn) if err != nil { log.Fatalf("Error on initializing database connection: %s" , err.Error()) } err = db.Ping() if err != nil { log.Fatalf("Error on opening database connection: %s" , err.Error()) } defer db.Close() query := `SELECT version();` var version string err = db.QueryRow(query).Scan(&version) if err != nil { log.Fatalf("Query failed: %s" , err.Error()) } fmt.Printf("Connected to MySQL database successfully! MySQL version: %s\n" , version) }
在写我们的MySQL连接字符串(DSN,即Data Source Name)时,确保我们指定了正确的用户名、密码、地址、端口和数据库名称。
注意事项 :
代码中_ "github.com/go-sql-driver/mysql"
的import表明引入了mysql驱动,但是并没有直接使用它,_
的用法在Go中用来进行仅初始化该包而不实际使用包中任何函数、变量等。 需要具体根据我们的MySQL服务器的用户名(username
), 密码 (password
), 服务器地址 (127.0.0.1
), 端口 (3306
), 和数据库名(dbname
)来编辑DSN。 db.Ping()
是用来检查与数据库的连接是否仍然有效,或者在初次尝试时,确认能够建立连接。最后,使用defer db.Close()
来确保数据库连接被正确关闭,这是避免内存泄漏的一个重要习惯。defer
关键字会安排随后的函数调用在函数返回时执行。 该示例中只执行了一个简单的SELECT
查询来获取MySQL的版本信息,并将其打印到标准输出。在实际的应用程序中,我们可能需要执行更复杂的SQL查询和其他数据库操作。 在生产环境中,应该避免明文存储敏感信息如数据库的用户名和密码,可以考虑使用环境变量或加密存储这些信息。 3.1. 创建一个测试数据库和表1 2 3 4 5 6 7 8 9 10 create database test default character set utf8 collate utf8_general_ci;use test; create table if not exists `user ` ( `id` int (8 ) not null auto_increment, `name` varchar (32 ) not null , `age` int (4 ) not null default 0 , primary key (id) ) engine= innodb default charset= utf8;
4. 增删查改操作4.1. 创建(Create)创建记录通常使用INSERT语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func create (db *sql.DB) { query := `INSERT INTO user(name, age) VALUES(?, ?)` result, err := db.Exec(query, "John Doe" , 28 ) if err != nil { log.Fatal(err) } id, err := result.LastInsertId() if err != nil { log.Fatal(err) } fmt.Printf("New record ID: %d\n" , id) }
4.2. 读取(Read)读取记录可以使用SELECT语句。查询单条结果可以使用QueryRow
,查询多条结果可以使用Query
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func read (db *sql.DB) { query := `SELECT id, name, age FROM user WHERE age > ?` rows, err := db.Query(query, 18 ) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var id int var name string var age int err = rows.Scan(&id, &name, &age) if err != nil { log.Fatal(err) } fmt.Printf("ID: %d, Name: %s, Age: %d\n" , id, name, age) } err = rows.Err() if err != nil { log.Fatal(err) } }
4.3. 更新(Update)更新记录通常使用UPDATE语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func update (db *sql.DB) { query := `UPDATE user SET age = ? WHERE name = ?` result, err := db.Exec(query, 30 , "John Doe" ) if err != nil { log.Fatal(err) } count, err := result.RowsAffected() if err != nil { log.Fatal(err) } fmt.Printf("Affected rows: %d\n" , count) }
4.4. 删除(Delete)删除记录通常使用DELETE语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func delete (db *sql.DB) { query := `DELETE FROM user WHERE name = ?` result, err := db.Exec(query, "John Doe" ) if err != nil { log.Fatal(err) } count, err := result.RowsAffected() if err != nil { log.Fatal(err) } fmt.Printf("Removed rows: %d\n" , count) }
4.5. 完整示例以下是综合上述功能的一个完整示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package mainimport ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) func main () { dsn := "root:mysql123@tcp(192.168.50.133:3306)/test" db, err := sql.Open("mysql" , dsn) if err != nil { log.Fatalf("Error on initializing database connection: %s" , err.Error()) } err = db.Ping() if err != nil { log.Fatalf("Error on opening database connection: %s" , err.Error()) } defer db.Close() create(db) read(db) update(db) read(db) delete (db) }
5. 注意事项在任何数据库操作之后,如果出现错误,请确保进行错误处理(if err != nil
)。 当使用rows
进行查询时,我们必须通过rows.Close()
来关闭rows,防止资源泄露。 使用defer
来确保数据库连接被关闭。 在生产环境中,考虑使用连接池管理数据库连接,Go的database/sql
包已经默认实现了连接池。 在实际场景中,多考虑使用事务管理(db.Begin()
),以保证数据的一致性。 确保处理sql.ErrNoRows
错误,当期望的行不存在时会返回此错误。 按照上文中的办法,即可完成在Go中对MySQL数据库进行基础的增删查改操作。在更高级的应用中,我们可能会涉及到更加复杂的事务、加锁策略和性能优化问题。