GoMySQL教程展示了如何在Golang中使用MySQL。这些示例执行基本的数据库操作。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
MySQL是领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL在网络上特别流行。MariaDB是MySQL关系数据库管理系统的一个社区开发的、商业支持的分支。
Go有sql
包,它提供了一个围绕SQL(或类似SQL)数据库的通用接口。sql包必须与数据库驱动程序结合使用。
该包提供了自动连接池。每次我们查询数据库时,我们都在使用应用程序启动时已设置的连接池中的一个连接。连接被重用。
$ go get -u github.com/go-sql-driver/mysql
我们需要安装MySQL驱动。
USE testdb; DROP TABLE IF EXISTS cities; CREATE TABLE cities(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), population INT); INSERT INTO cities(name, population) VALUES('Bratislava', 432000); INSERT INTO cities(name, population) VALUES('Budapest', 1759000); INSERT INTO cities(name, population) VALUES('Prague', 1280000); INSERT INTO cities(name, population) VALUES('Warsaw', 1748000); INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000); INSERT INTO cities(name, population) VALUES('New York', 8550000); INSERT INTO cities(name, population) VALUES('Edinburgh', 464000); INSERT INTO cities(name, population) VALUES('Berlin', 3671000);
在本教程中,我们使用cities
表。
GoMySQL版本
在第一个示例中,我们打印了MySQL的版本。
package main import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb") defer db.Close() if err != nil { log.Fatal(err) } var version string err2 := db.QueryRow("SELECT VERSION()").Scan(&version) if err2 != nil { log.Fatal(err2) } fmt.Println(version) }
程序返回MySQL的版本。版本通过执行SELECTVERSION()
语句确定。
_ "github.com/go-sql-driver/mysql"
当导入带有空白标识符前缀的包时,将调用包的init函数。该函数注册驱动程序。
db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
使用sql.Open
,我们打开一个数据库,该数据库由其数据库驱动程序名称和特定于驱动程序的数据源名称指定,通常至少包含数据库名称和连接信息。它不与数据库建立任何连接,也不验证驱动程序连接参数。相反,它只是准备数据库抽象供以后使用。到底层数据存储的第一个实际连接将在第一次需要时延迟建立。
defer db.Close()
Close
将连接返回到连接池。如果sql.DB的生命周期不应超出函数范围,则延迟db.Close
是惯用的.
err2 := db.QueryRow("SELECT VERSION()").Scan(&version)
QueryRow
执行预计最多返回一行的查询。Scan
函数将匹配行中的列复制到version
变量中。
$ go run version.go 10.3.24-MariaDB-2
GoMySQL使用查询选择所有行
Query
执行返回行的查询,通常是SELECT。可选参数用于查询中的任何占位符参数。
package main import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) type City struct { Id int Name string Population int } func main() { db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb") defer db.Close() if err != nil { log.Fatal(err) } res, err := db.Query("SELECT * FROM cities") defer res.Close() if err != nil { log.Fatal(err) } for res.Next() { var city City err := res.Scan(&city.Id, &city.Name, &city.Population) if err != nil { log.Fatal(err) } fmt.Printf("%v\n", city) } }
该示例打印cities
表中的所有行。
for res.Next() {
Next
准备下一个结果行以使用Scan
方法读取。成功时返回true,如果没有下一个结果行或在准备结果行时发生错误,则返回false。
err := res.Scan(&city.Id, &city.Name, &city.Population)
我们将数据读入City
结构Scan
。
$ go run select_all.go {1 Bratislava 432000} {2 Budapest 1759000} {3 Prague 1280000} {4 Warsaw 1748000} {5 Los Angeles 3971000} {6 New York 8550000} {7 Edinburgh 464000} {8 Berlin 3671000}
GoMySQLinsertrowwithExec
Exec
函数执行查询而不返回任何行。它与INSERT、UPDATE、DELETE或DROP语句一起使用。可选参数用于查询中的任何占位符参数。
package main import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb") defer db.Close() if err != nil { log.Fatal(err) } sql := "INSERT INTO cities(name, population) VALUES ('Moscow', 12506000)" res, err := db.Exec(sql) if err != nil { panic(err.Error()) } lastId, err := res.LastInsertId() if err != nil { log.Fatal(err) } fmt.Printf("The last inserted row id: %d\n", lastId) }
该示例将一个新行插入到cities
表中。
sql := "INSERT INTO cities(name, population) VALUES ('Moscow', 12506000)" res, err := db.Exec(sql)
我们在表中插入一个新城市。
lastId, err := res.LastInsertId()
使用LastInsertId
,我们可以获得最后插入的ID。
GoMySQL预处理语句
对于准备好的语句,我们使用占位符而不是直接将值写入语句。准备好的语句提高了数据库操作的安全性和性能。
Go在幕后为您创建准备好的语句。
db.Query(sql, param1, param2)
Query
函数准备SQL,然后使用参数执行它,最后关闭语句。
package main import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) type City struct { Id int Name string Population int } func main() { db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb") defer db.Close() if err != nil { log.Fatal(err) } var myid int = 1 res, err := db.Query("SELECT * FROM cities WHERE id = ?", myid) defer res.Close() if err != nil { log.Fatal(err) } if res.Next() { var city City err := res.Scan(&city.Id, &city.Name, &city.Population) if err != nil { log.Fatal(err) } fmt.Printf("%v\n", city) } else { fmt.Println("No city found") } }
该示例从数据库中选择一行。
res, err := db.Query("SELECT * FROM cities WHERE id = ?", myid)
?
是一个占位符,其中填充了myid
变量的值。在幕后,db.Query
实际上准备、执行和关闭准备好的语句。
$ go run prepared.go {1 Bratislava 432000}
GoMySQL受影响的行
RowsAffected
返回受更新、插入或删除语句影响的行数。
package main import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb") defer db.Close() if err != nil { log.Fatal(err) } sql := "DELETE FROM cities WHERE id IN (2, 4, 6)" res, err := db.Exec(sql) if err != nil { panic(err.Error()) } affectedRows, err := res.RowsAffected() if err != nil { log.Fatal(err) } fmt.Printf("The statement affected %d rows\n", affectedRows) }
在代码示例中,我们使用DELETESQL语句删除了三行。然后我们使用RowsAffected
打印删除的行数。
$ go run affected_rows.go The statement affected 3 rows
在本教程中,我们在Go中使用了MySQL。
列出所有Go教程。