Go语言中如何连接 MySQL,基础必备!

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 在现代应用中,数据库操作至关重要。本教程将指导你使用Go语言进行MySQL的CRUD操作。首先,确保已创建`test_db`数据库及`users`表。接着安装MySQL驱动:`go get -u github.com/go-sql-driver/mysql`。通过示例代码,你将学会连接数据库、创建、查询、更新及删除用户记录。尽管此方法直接,但在实际项目中可能略显繁琐,后续会介绍更高效的库如sqlx或gorm。现在,让我们从基础开始,掌握Go语言中的数据库交互技巧。

在现代应用中,数据库操作是必不可少的一部分,而 Go 语言凭借其高效性和并发处理能力,成为了越来越多开发者的选择。

在本教程中,我们将学习如何使用 Go 语言与 MySQL 数据库进行基本的 CRUD(创建、读取、更新、删除)操作。我们将使用 database/sql 标准库以及 github.com/go-sql-driver/mysql 驱动来实现这些功能。

准备工作

环境要求

  • 创建一个名为 test_db 的数据库。
  • 创建一个 users 表,表结构如下:
CREATE DATABASE test_db;

USE test_db;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT NOT NULL
);

安装 MySQL 驱动

使用以下命令安装 MySQL 驱动:

go get -u github.com/go-sql-driver/mysql

示例代码

下面是一个完整的 Go 程序,展示如何进行基本的 CRUD 操作:

package main

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

    _ "github.com/go-sql-driver/mysql"
)

func main() {
   
    // 数据库连接字符串
    dsn := "user:password@tcp(127.0.0.1:3306)/test_db"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
   
        log.Fatal(err)
    }
    // 防止 db 为 nil,因此需要先判断 err 之后才能调用 Close 方法去释放 db
    defer db.Close()

    // 测试连接
    if err := db.Ping(); err != nil {
   
        log.Fatal(err)
    }
    fmt.Println("成功连接到 MySQL 数据库!")

    // 创建用户
    id := createUser(db, "Alice", 25)
    fmt.Printf("新创建的用户 ID: %d\n", id)

    // 查询所有用户
    getUsers(db)

    // 查询单个用户
    userId := 1
    getUser(db, userId)

    // 更新用户
    affectedRows := updateUser(db, 1, "Alice Smith", 26)
    fmt.Printf("受影响的行数: %d\n", affectedRows)

    // 删除用户
    affectedRows = deleteUser(db, 1)
    fmt.Printf("受影响的行数: %d\n", affectedRows)
}

创建(Insert)

// 创建用户,返回新创建用户的 ID
func createUser(db *sql.DB, name string, age int) int {
   
    query := "INSERT INTO users (name, age) VALUES (?, ?)"
    result, err := db.Exec(query, name, age)
    if err != nil {
   
        log.Fatal(err)
    }
    // 获取最后插入的 ID
    lastInsertId, err := result.LastInsertId()
    if err != nil {
   
        log.Fatal(err)
    }
    return int(lastInsertId)
}

查询(Select)

// 查询所有用户
func getUsers(db *sql.DB) {
   
    query := "SELECT id, name, age FROM users"
    rows, err := db.Query(query)
    if err != nil {
   
        log.Fatal(err)
    }
    // 一定要记得关闭资源
    defer rows.Close()

    fmt.Println("所有用户:")
    for rows.Next() {
   
        var id int
        var name string
        var age int
        if err := rows.Scan(&id, &name, &age); err != nil {
   
            log.Fatal(err)
        }
        fmt.Printf("ID: %d, Name: %s, Age: %d\n", id, name, age)
    }
}

// 查询单个用户
func getUser(db *sql.DB, id int) {
   
    query := "SELECT id, name, age FROM users WHERE id = ?"
    row := db.QueryRow(query, id)

    var name string
    var age int
    // 调用完了 QueryRow 方法之后,一定要记得调用 Scan 方法,否则持有的数据库连接不会被释放
    if err := row.Scan(&id, &name, &age); err != nil {
   
        if err == sql.ErrNoRows {
   
            fmt.Printf("用户 ID %d 不存在\n", id)
        } else {
   
            log.Fatal(err)
        }
    } else {
   
        fmt.Printf("用户 ID: %d, Name: %s, Age: %d\n", id, name, age)
    }
}

更新(Update)

// 更新用户,返回受影响的行数
func updateUser(db *sql.DB, id int, name string, age int) int {
   
    query := "UPDATE users SET name = ?, age = ? WHERE id = ?"
    result, err := db.Exec(query, name, age, id)
    if err != nil {
   
        log.Fatal(err)
    }
    // 获取受影响的行数
    affectedRows, err := result.RowsAffected()
    if err != nil {
   
        log.Fatal(err)
    }
    return int(affectedRows)
}

删除(Delete)

// 删除用户,返回受影响的行数
func deleteUser(db *sql.DB, id int) int {
   
    query := "DELETE FROM users WHERE id = ?"
    result, err := db.Exec(query, id)
    if err != nil {
   
        log.Fatal(err)
    }
    // 获取受影响的行数
    affectedRows, err := result.RowsAffected()
    if err != nil {
   
        log.Fatal(err)
    }
    return int(affectedRows)
}

代码解析

1. 数据库连接

我们使用 sql.Open 方法连接到 MySQL 数据库,连接字符串格式为 user:password@tcp(host:port)/dbname。在连接后,我们调用 db.Ping() 测试数据库连接是否成功。

2. 创建用户

createUser 函数通过 INSERT 语句向 users 表中添加新用户,并返回新创建用户的 ID。

3. 查询用户

  • getUsers 函数查询所有用户并打印每个用户的 ID、姓名和年龄。
  • getUser 函数通过用户 ID 查询单个用户,并处理用户不存在的情况。

4. 更新用户

updateUser 函数用于更新用户信息,并返回受影响的行数,以确认操作是否成功。

5. 删除用户

deleteUser 函数用于删除指定 ID 的用户,并同样返回受影响的行数。

总结

在本文中,我们展示了如何使用 Go 语言与 MySQL 数据库进行基本的 CRUD 操作。通过本教程,您可以创建、查询、更新和删除用户数据,这为您在开发基于数据库的应用程序时打下了基础。

用这个库还是比较累赘的,代码写起来比较累,并且一般在实际应用中很少会直接拼接 sql 语句,会遇到 SQL 注入的风险,后面会介绍 sqlx 或者 gorm 的使用,这里先了解个基础知识,为后期做做准备。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
28 10
|
2天前
|
Go API 开发者
深入探讨:使用Go语言构建高性能RESTful API服务
在本文中,我们将探索Go语言在构建高效、可靠的RESTful API服务中的独特优势。通过实际案例分析,我们将展示Go如何通过其并发模型、简洁的语法和内置的http包,成为现代后端服务开发的有力工具。
|
4天前
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
25 10
|
4天前
|
编译器 Go
go语言学习记录(关于一些奇怪的疑问)有别于其他编程语言
本文探讨了Go语言中的常量概念,特别是特殊常量iota的使用方法及其自动递增特性。同时,文中还提到了在声明常量时,后续常量可沿用前一个值的特点,以及在遍历map时可能遇到的非顺序打印问题。
|
1天前
|
存储 监控 数据可视化
Go 语言打造公司监控电脑的思路
在现代企业管理中,监控公司电脑系统对保障信息安全和提升工作效率至关重要。Go 语言凭借其高效性和简洁性,成为构建监控系统的理想选择。本文介绍了使用 Go 语言监控系统资源(如 CPU、内存)和网络活动的方法,并探讨了整合监控数据、设置告警机制及构建可视化界面的策略,以满足企业需求。
12 1
|
8天前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
5天前
|
存储 Shell Go
Go语言结构体和元组全面解析
Go语言结构体和元组全面解析
|
23天前
|
SQL 关系型数据库 MySQL
【揭秘】MySQL binlog日志与GTID:如何让数据库备份恢复变得轻松简单?
【8月更文挑战第22天】MySQL的binlog日志记录数据变更,用于恢复、复制和点恢复;GTID为每笔事务分配唯一ID,简化复制和恢复流程。开启binlog和GTID后,可通过`mysqldump`进行逻辑备份,包含binlog位置信息,或用`xtrabackup`做物理备份。恢复时,使用`mysql`命令执行备份文件,或通过`innobackupex`恢复物理备份。GTID模式下的主从复制配置更简便。
106 2
|
18天前
|
弹性计算 关系型数据库 数据库
手把手带你从自建 MySQL 迁移到云数据库,一步就能脱胎换骨
阿里云瑶池数据库来开课啦!自建数据库迁移至云数据库 RDS原来只要一步操作就能搞定!点击阅读原文完成实验就可获得一本日历哦~
|
21天前
|
关系型数据库 MySQL 数据库
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决