访问关系数据库mysql
在工作空间中新建一个包data-access,使用
go mod init example/data-access
进行初始化;
在data-access包中新建main.go文件内容如下:
package main
import (
"database/sql"
"fmt"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
var db *sql.DB
func main() {
// Capture connection properties.
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "***.***.***.***:3306",
DBName: "{要连接的数据库中已存在的库名}",
}
// Get a database handle.
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
}
使用
go mod tidy
自动添加"github.com/go-sql-driver/mysql"依赖,此依赖为MySQL驱动程序模块用于连接映射数据库;
上面代码中
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "***.***.***.***:3306",
DBName: "{要连接的数据库中已存在的库名}",
}
cfg即是数据库连接的配置,DBUSER与DBPASS为go中配置的环境变量,不能直接填入数据库用户名与密码,因为此为敏感信息,必须储存在环境变量中才能够让go编译识别;
在命令行中通过set设置对应环境变量
set DBUSER=username
set DBPASS=password
之后
go run .
运行程序,命令行输出为
Connected!
则连接正常;
增查操作
先定义一个结构体用于数据传输
// 定义Student结构体
type Student struct {
id int64
name string
age int64
gender string
}
创建三个函数
func studentByName(name string)
func studentByID(id int64) (Student, error)
func addStudent(alb Student) (int64, error)
分别用于多条查询,单条查询,单条插入的简单操作;
每个函数通用操作步骤为:
- 定义一个结构体实例;
- 通过数据库语柄的内置函数执行mysql语句;
- 对返回值进行判断,若报错则返回报错,否则就存入切片或者变量中,作为返回值返回。
"database/sql"
与"github.com/go-sql-driver/mysql"
必须同时使用。
最终代码如下:
package main
import (
"database/sql"
"fmt"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
// 定义数据库语柄
var db *sql.DB
// 定义Student结构体
type Student struct {
id int64
name string
age int64
gender string
}
func main() {
// 数据库连接配置
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "118.25.40.30:3307",
DBName: "dewu",
}
// 连接数据库
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
// 检查连接
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
// 多条查询
student, err := studentByName("张三")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Students found: %v\n", student)
// 单条查询
alb, err := studentByID(2)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Student found: %v\n", alb)
// 单条插入
albID, err := addStudent(Student{
id:888,
name: "苟八",
age: 18,
gender: "4",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("ID of added student: %v\n", albID)
}
func studentByName(name string) ([]Student, error) {
// 储存查询结果的切片
var students []Student
// Query多条查询
rows, err := db.Query("SELECT * FROM student WHERE name = ?", name)
if err != nil {
return nil, fmt.Errorf("studentByName %q: %v", name, err)
}
defer rows.Close()
for rows.Next() {
var alb Student
if err := rows.Scan(&alb.id, &alb.name, &alb.age, &alb.gender); err != nil {
return nil, fmt.Errorf("studentByName %q: %v", name, err)
}
students = append(students, alb)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("studentByName %q: %v", name, err)
}
return students, nil
}
func studentByID(id int64) (Student, error) {
var alb Student
row := db.QueryRow("SELECT * FROM student WHERE id = ?", id)
if err := row.Scan(&alb.id, &alb.name, &alb.age, &alb.gender); err != nil {
if err == sql.ErrNoRows {
return alb, fmt.Errorf("studentsById %d: no such student", id)
}
return alb, fmt.Errorf("studentsById %d: %v", id, err)
}
return alb, nil
}
func addStudent(alb Student) (int64, error) {
result, err := db.Exec("INSERT INTO student (id,name, age, gender) VALUES (?,?, ?, ?)",alb.id, alb.name, alb.age, alb.gender)
if err != nil {
return 0, fmt.Errorf("addStudent: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("addStudent: %v", err)
}
return id, nil
}
输出结果为: