go语言学习笔记:gin + gorm + mysql 用户增删改查案例入门

大家好,我是此林。

Golang 语言现在已经成为了编程的趋势,毕竟是大厂背书嘛,Google 研发的。

目前很多云原生项目都是基于 go 来编写的,比如:

Kubernetes (K8s)​ 容器编排系统,

Docker​ 容器化技术,

etcd​分布式键值存储(Kubernetes 的默认存储),

Prometheus​监控 & 告警系统,

Istio​服务网格(Service Mesh,用于流量管理、安全策略、可观测性)

​💡 Go 的优势​

✅ ​​编译速度快​ ​(比 C++/Java 快)

✅ ​​静态二进制文件​ ​(部署简单,无依赖)

✅ ​​原生并发支持​​(goroutine + channel)

那作为一个 Javaer,我们用熟练了 springboot,gin + grom 那一套东西,上手也可以说很快。今天来看一个案例:user 增删查改。

目录

[1. Go 安装](#1. Go 安装)

[2. 项目开始](#2. 项目开始)

[2.1. 初始化配置](#2.1. 初始化配置)

[2.2. sql 设计](#2.2. sql 设计)

[2.3. db.go 数据库配置](#2.3. db.go 数据库配置)

[2.4. user.go 实体类设计](#2.4. user.go 实体类设计)

[2.5. controller 设计](#2.5. controller 设计)

[2.6 main.go 主程序](#2.6 main.go 主程序)

[3. postman 接口测试](#3. postman 接口测试)


1. Go 安装

这个不多说,下载安装 + 配置环境变量,笔者用的是 1.23.8 稳定版。

安装完记得用 go env -w 配置下 mod 的国内代理,mod 相当于 Maven,是依赖管理工具。

和 java 不同,mod 是 go 语言自带的,无需另外安装。

vscode 里配置插件,这里就不用笨重的 Goland 了。

2. 项目开始

2.1. 初始化配置

复制代码
mkdir go-crud
cd go-crud
go mod init go-crud

然后创建下面的目录结构

复制代码
go-crud/
├── main.go
├── models/
│   └── user.go
├── controllers/
│   └── user_controller.go
├── config/
    └── db.go

看样子,和 spring mvc 还有点像。

2.2. sql 设计

已经提前创建好了 user 表,四个字段:id,name,age,sex。

SQL自取。

sql 复制代码
create table users
(
    id   bigint unsigned auto_increment
        primary key,
    name longtext null,
    age  bigint   null,
    sex  bigint   null
);

INSERT INTO users (name, age, sex) 
VALUES 
  ('李四', 30, 1),
  ('王五', 28, 0),
  ('赵六', 22, 1);

2.3. db.go 数据库配置

Go 复制代码
package config

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func ConnectDB() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("数据库连接失败:" + err.Error())
	}

	DB = db
	fmt.Println("数据库连接成功!")
}

有点陌生?别担心,多去浏览浏览菜鸟教程的 Go 基本语法就行。

  1. fmt.Println():相当于 java 里的 System.out.println()

  2. dsn := "...":这是go里定义局部变量的简化写法

当然也可以写成 var dsn = "...",这种定义可以作为全局或者局部变量。

或者 var dsn string = "..." 也可以,不写明类型go会自动类型推导。

2.4. user.go 实体类设计

Go 复制代码
package models

type User struct {
	Id uint `json:"id" gorm:"primaryKey"`
	Name string `json:"name"`
	Age int `json:"age"`
	Sex int `json:"sex"`
}
func (User) TableName() string {
    return "user"  // 强制表名为 "user"(而不是默认的 "users")
}

在 Go 的结构体定义中,​json:"xxx" ​ 和 ​gorm:"xxx" ​ 这些是 ​​结构体标签(Struct Tags)​​,它们为字段提供额外的元信息(metadata),用于控制 JSON 序列化/反序列化、数据库映射等行为。

比如json标签:

Go 复制代码
`json:"id"`   // 指定该字段在JSON中的键名
`json:"-"`    // 忽略此字段(不参与JSON序列化)
`json:"name,omitempty"` // 如果字段为空值(0、""、nil等),JSON中省略此字段

详细来说,就是如下:

Go 复制代码
type User struct {
    Id   uint   `json:"id" gorm:"primaryKey"`  // JSON键名=id,数据库主键
    Name string `json:"name"`                  // JSON键名=name
    Age  int    `json:"age"`                   // JSON键名=age
    Sex  int    `json:"sex"`                   // JSON键名=sex
}

2.5. controller 设计

Go 复制代码
package controllers

import (
	"go-crud/config"
	"go-crud/models"
	"github.com/gin-gonic/gin"
	"net/http"
)

// 创建用户
func CreateUser(c *gin.Context) {
	var user models.User
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	config.DB.Create(&user)
	c.JSON(http.StatusOK, user)
}

// 查询所有用户
func GetUsers(c *gin.Context) {
	var users []models.User
	config.DB.Find(&users)
	c.JSON(http.StatusOK, users)
}

// 查询单个用户
func GetUserById(c *gin.Context) {
	var user models.User
	id := c.Param("id")
	if err := config.DB.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户未找到"})
		return
	}
	c.JSON(http.StatusOK, user)
}

// 更新用户
func UpdateUser(c *gin.Context) {
	var user models.User
	id := c.Param("id")
	if err := config.DB.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户未找到"})
		return
	}

	var input models.User
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	user.Name = input.Name
	user.Age = input.Age
	user.Sex = input.Sex
	config.DB.Save(&user)

	c.JSON(http.StatusOK, user)
}

// 删除用户
func DeleteUser(c *gin.Context) {
	var user models.User
	id := c.Param("id")
	if err := config.DB.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户未找到"})
		return 
	}
	config.DB.Delete(&user)
	c.JSON(http.StatusOK, gin.H{"message": "用户已删除"})
}

这里每个函数都要加 c *gin.Context,可以理解为请求request和响应response都在里边。当做规则,记住就好。

id := c.Param("id") 就是获取请求中的id。

c.JSON(http.StatusOK, gin.H{"message": "用户已删除"}) 就是返回 json 响应,restful 规范。

可以看到,使用了 gorm,大部分 sql 我们都不用手写。

当然也可以使用 config.DB = config.DB.Debug() 打印实际执行的SQL。在复杂查询时,也是可以自定义 SQL 的。

2.6 main.go 主程序

最后一步了!

Go 复制代码
package main

import (
	"go-crud/config"
	"go-crud/controllers"
	"go-crud/models"
	"github.com/gin-gonic/gin"
)

func main() {
	// 连接数据库
	config.ConnectDB()
	
	// 自动迁移
	config.DB.AutoMigrate(&models.User{})

	// 设置路由
	r := gin.Default()
	r.POST("/users", controllers.CreateUser) // 创建用户
	r.GET("/users", controllers.GetUsers)     // 查询所有用户
	r.GET("/users/:id", controllers.GetUserById) // 查询单个用户
	r.PUT("/users/:id", controllers.UpdateUser) // 更新用户
	r.DELETE("/users/:id", controllers.DeleteUser) // 删除用户
	r.Run(":1234") // 启动服务
}

这里无非是先初始化数据库连接。

我们以前 springboot里,是把 mysql 连接信息写在 yml 里,然后 spring 把它封装为 Bean 吧?

Go 里稍微不同,要去显式调用。

然后后面就是配置路由了,路由集中管理了,和 springboot 注解配置的形式又有点不同。

最后 r.Run() 启动服务。

3. postman 接口测试

启动项目:

Go 复制代码
go run main.go
  1. 查询所有用户

  2. 删除用户

  1. 更新用户

今天分享就到这里了,

我是此林,

关注我吧,带你看不一样的世界!

相关推荐
Zyxalia2 小时前
gin + es 实践 03
elasticsearch·jenkins·gin
HelloZheQ2 小时前
Go:简洁高效,构建现代应用的利器
开发语言·后端·golang
非晓为骁4 小时前
【Go】优化文件下载处理:从多级复制到零拷贝流式处理
开发语言·后端·性能优化·golang·零拷贝
北极象4 小时前
Golang中集合相关的库
开发语言·后端·golang
小猪咪piggy4 小时前
【MySQL】(10)用户和权限管理
数据库·mysql
GUIQU.5 小时前
【MySQL】SQL简述
数据库·sql·mysql
敲上瘾5 小时前
数据库(MySQL)基础
linux·数据库·mysql
顽强d石头6 小时前
viewDesign里的table内嵌套select动态添加表格行绑定内容丢失
数据库·mysql·view design
胖哥真不错7 小时前
Python基于Django和MySQL实现突发公共卫生事件舆情分析系统(有大屏功能)
python·mysql·django·突发公共卫生事件舆情分析系统·大屏功能
长流小哥9 小时前
MySQL C API高效编程:C语言实现数据库操作的深入解析
数据库·c++·mysql