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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 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 的使用,这里先了解个基础知识,为后期做做准备。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
6月前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
|
28天前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
1月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
2月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
2月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
162 0
|
3月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
4月前
|
分布式计算 Go C++
初探Go语言RPC编程手法
总的来说,Go语言的RPC编程是一种强大的工具,让分布式计算变得简单如同本地计算。如果你还没有试过,不妨挑战一下这个新的编程领域,你可能会发现新的世界。
99 10
|
消息中间件 Go
go连接RabbitMQ "no access to this vhost"错误
连接的失败报错:RabbitMQ Exception (403) Reason: "no access to this vhost" 因为没有配置该用户的访问权限,可以通过 rabbitmqctl add_vhost admin 来添加,并赋予权限: rabbitmqctl set_permissions -p 用户名 admin ".
7658 0
|
7月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
7月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。

推荐镜像

更多