大家好,我是此林。
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 基本语法就行。
- 
fmt.Println():相当于 java 里的 System.out.println() 
- 
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
- 
查询所有用户  
- 
删除用户 

- 更新用户

今天分享就到这里了,
我是此林,
关注我吧,带你看不一样的世界!