Golang操作数据库简单示例

目录

准备工作

在开始之前,你需要确保自己安装了Golang的编程环境,安装MySQL数据库,有一个可以用于编写代码的编辑器或IDE工具。我在这里使用的编辑器是Fleet

准备数据

将下面的SQL语句在MySQL中执行,创建数据库并插入数据.。

sql 复制代码
drop table if exists album;
create table album (
    id int auto_increment not null,
    title varchar(128) not null,
    artist varchar(255) not null,
    price decimal(5,2) not null,
    primary key (`id`)
);
insert into album
    (title, artist, price)
values
    ('Blue Train', 'John Coltrane', 56.99),
    ('Giant Steps', 'Greey Mulligan', 63.99),
    ('Jeru', 'Gerry Mulligan', 17.99),
    ('Sarah Vaughan', 'Sarah Vaughan', 34.98);

创建项目

进入终端,输入以下命令。(当然,你也可以手动创建)

shell 复制代码
mkdir data-access
cd ./data-access

在上面创建的目录下创建文件main.go,将以下代码粘贴到文件中。

go 复制代码
package main

import (
	"database/sql"
	"errors"
	"fmt"
	"github.com/go-sql-driver/mysql"
	"log"
)

终端输入以下命令下载上面代码中引入的MySQL的驱动包

shell 复制代码
go mod tidy

连接数据库

在main.go中输入以下代码,连接数据库。

go 复制代码
var db *sql.DB

func main() {
	// 设置连接属性
	cfg := mysql.Config{
		User:   "root",
		Passwd: "123456",
		Net:    "tcp",
		Addr:   "127.0.0.1:3306",
		DBName: "recordings",
	}

	// 获取数据库句柄
	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)
	}
	log.Println("Connected!")
}

查询数据

对于数据库中的数据,我们需要定义一个结构体去接收。在main.go中输入以下代码。

go 复制代码
// Album 记录实体结构体
type Album struct {
	ID     int64
	Title  string
	Artist string
	Price  float32
}

接着我们实现String函数让输出稍微美观一些。

go 复制代码
func (album Album) String() string {
	return fmt.Sprintf(`{ "id": %d, "title": %q, "artist": %q, "price": %.2f }`, album.ID, album.Title, album.Artist, album.Price)
}

接下来,让我们编写一个函数,这个函数的功能是通过人名去查询数据库中的记录。

go 复制代码
// 通过人名查询记录
func albumsByArtist(name string) ([]Album, error) {
	var albums []Album

	rows, err := db.Query("select * from album where artist = ?", name)
	if err != nil {
		return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
	}
	// 资源释放,defer关键字修饰的语句在其下方语句未执行完成前不会执行
	defer rows.Close()

	// 循环获取相关值
	for rows.Next() {
		var alb Album
		if err := rows.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
			return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
		}
		albums = append(albums, alb)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
	}
	return albums, nil
}

接着定义一个函数,通过id去查询记录。

go 复制代码
// 通过ID查询记录
func albumsById(id int64) (Album, error) {
	var alb Album

	row := db.QueryRow("select * from album where id = ?", id)
	if err := row.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return alb, fmt.Errorf("albumsById %d: no such album", id)
		}
		return alb, fmt.Errorf("albumsById %d: %v", id, err)
	}
	return alb, nil
}

然后,我们在main函数中调用。

go 复制代码
// 查询数据
albums, err := albumsByArtist("John Coltrane")
if err != nil {
	log.Fatal(err)
}
log.Printf("Albums found: %v\n", albums)

alb, err := albumsById(2)
if err != nil {
	log.Fatal(err)
}
log.Printf("Album found: %v\n", alb)

修改数据

我们来定义一个函数用来修改数据,用id做为删选条件。

go 复制代码
// 修改数据
func updateAlbumById(alb Album) (int64, error) {
	result, err := db.Exec("update album set title = ?, artist = ?, price = ? where id = ?", alb.Title, alb.Artist, alb.Price, alb.ID)
	if err != nil {
		return 0, fmt.Errorf("updateAlbumById: %v", err)
	}

	rows, err := result.RowsAffected()
	if err != nil {
		return 0, fmt.Errorf("updateAlbumById: %v", err)
	}
	return rows, nil
}

在main函数中调用它。

go 复制代码
// 修改数据
updateRows, err := updateAlbumById(Album{
	ID: 1,
	Title: "White teddy bear",
	Artist: "John Thompson's",
	Price: 20.99,
})
if err != nil {
	log.Fatal(err)
}
log.Printf("Number of rows updated: %v\n", updateRows)

插入数据

定义一个函数用来插入数据并且返回插入数据在数据库中的id。

go 复制代码
// 插入记录
func addAlbum(alb Album) (int64, error) {
	result, err := db.Exec("insert into album (title, artist, price) values (?, ?, ?)", alb.Title, alb.Artist, alb.Price)
	if err != nil {
		return 0, fmt.Errorf("addAlbum: %v", err)
	}
	
	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("addAlbum: %v", err)
	}
	return id, nil
}

在main函数中调用

go 复制代码
// 插入数据
albId, err := addAlbum(Album{
	Title: "The Modern Sound of Betty Carter",
	Artist: "Betty Carter",
	Price: 49.99,
})
if err != nil {
	log.Fatal(err)
}
log.Printf("id of added alnum: %v\n", albId)

删除数据

定义一个函数用来删除数据。

go 复制代码
// 删除记录,返回删除的行数
func deleteAlbum(id int64) (int64, error) {
	result, err := db.Exec("delete from album where id = ?", id)
	if err != nil {
		return 0, fmt.Errorf("deleteAlbum: %v", err)
	}
	
	rows, err := result.RowsAffected()
	if err != nil {
		return 0, fmt.Errorf("deleteAlbum: %v", err)
	}
	return rows, nil
}

在main函数中调用

go 复制代码
// 删除数据
deleteRows, err := deleteAlbum(albId)
if err != nil {
	log.Fatal(err)
}
log.Printf("Number of rows deleted: %v\n", deleteRows)

释放资源

对于数据库的操作完成后,需要释放数据库连接,在main函数中输入以下代码释放资源。

go 复制代码
// 释放资源
err = db.Close()
if err != nil {
	log.Fatal(err)
}

完整代码

完整代码如下。

go 复制代码
package main

import (
	"database/sql"
	"errors"
	"fmt"
	"github.com/go-sql-driver/mysql"
	"log"
)

var db *sql.DB

// Album 记录实体结构体
type Album struct {
	ID     int64
	Title  string
	Artist string
	Price  float32
}

func (album Album) String() string {
	return fmt.Sprintf(`{ "id": %d, "title": %q, "artist": %q, "price": %.2f }`, album.ID, album.Title, album.Artist, album.Price)
}

func main() {
	// 设置连接属性
	cfg := mysql.Config{
		User:   "root",
		Passwd: "123456",
		Net:    "tcp",
		Addr:   "127.0.0.1:3306",
		DBName: "recordings",
	}

	// 获取数据库句柄
	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)
	}
	log.Println("Connected!")

	// 查询数据
	albums, err := albumsByArtist("John Coltrane")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Albums found: %v\n", albums)

	alb, err := albumsById(2)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Album found: %v\n", alb)
	
	// 修改数据
	updateRows, err := updateAlbumById(Album{
		ID: 1,
		Title: "White teddy bear",
		Artist: "John Thompson's",
		Price: 20.99,
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Number of rows updated: %v\n", updateRows)
	
	// 插入数据
	albId, err := addAlbum(Album{
		Title: "The Modern Sound of Betty Carter",
		Artist: "Betty Carter",
		Price: 49.99,
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("id of added alnum: %v\n", albId)
	
	// 删除数据
	deleteRows, err := deleteAlbum(albId)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Number of rows deleted: %v\n", deleteRows)
	
	// 释放资源
	err = db.Close()
	if err != nil {
		log.Fatal(err)
	}
}

// 通过人名查询记录
func albumsByArtist(name string) ([]Album, error) {
	var albums []Album

	rows, err := db.Query("select * from album where artist = ?", name)
	if err != nil {
		return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
	}
	// 资源释放,defer关键字修饰的语句在其下方语句未执行完成前不会执行
	defer rows.Close()

	// 循环获取相关值
	for rows.Next() {
		var alb Album
		if err := rows.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
			return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
		}
		
		albums = append(albums, alb)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("albumsByArtist %q: %v", name, err)
	}
	return albums, nil
}

// 通过ID查询记录
func albumsById(id int64) (Album, error) {
	var alb Album

	row := db.QueryRow("select * from album where id = ?", id)
	if err := row.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return alb, fmt.Errorf("albumsById %d: no such album", id)
		}
		return alb, fmt.Errorf("albumsById %d: %v", id, err)
	}
	return alb, nil
}

// 修改数据
func updateAlbumById(alb Album) (int64, error) {
	result, err := db.Exec("update album set title = ?, artist = ?, price = ? where id = ?", alb.Title, alb.Artist, alb.Price, alb.ID)
	if err != nil {
		return 0, fmt.Errorf("updateAlbumById: %v", err)
	}

	rows, err := result.RowsAffected()
	if err != nil {
		return 0, fmt.Errorf("updateAlbumById: %v", err)
	}
	return rows, nil
}

// 插入记录
func addAlbum(alb Album) (int64, error) {
	result, err := db.Exec("insert into album (title, artist, price) values (?, ?, ?)", alb.Title, alb.Artist, alb.Price)
	if err != nil {
		return 0, fmt.Errorf("addAlbum: %v", err)
	}
	
	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("addAlbum: %v", err)
	}
	return id, nil
}

// 删除记录,返回删除的行数
func deleteAlbum(id int64) (int64, error) {
	result, err := db.Exec("delete from album where id = ?", id)
	if err != nil {
		return 0, fmt.Errorf("deleteAlbum: %v", err)
	}
	
	rows, err := result.RowsAffected()
	if err != nil {
		return 0, fmt.Errorf("deleteAlbum: %v", err)
	}
	return rows, nil
}

最终执行结果

相关推荐
Envyᥫᩣ8 分钟前
C#语言:从入门到精通
开发语言·c#
齐 飞16 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
云空16 分钟前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite
暮毅21 分钟前
10.Node.js连接MongoDb
数据库·mongodb·node.js
wowocpp24 分钟前
ubuntu 22.04 server 格式化 磁盘 为 ext4 并 自动挂载 LTS
服务器·数据库·ubuntu
童先生29 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu30 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
成富1 小时前
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
数据库·人工智能·sql·spring·oracle
songqq271 小时前
SQL题:使用hive查询各类型专利top 10申请人,以及对应的专利申请数
数据库·sql
计算机学长felix1 小时前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友