写给 Javaer 看的 Go Gin 教程

在国内,Gin 被广泛认为是使用最为广泛的 Go 语言 Web 开发框架。它以高性能和简洁的 API 设计而著称,特别适合构建高并发的服务。

此外,Kratos 作为 B 站开源的微服务框架,也在国内拥有一定的用户基础,适用于构建复杂的分布式系统。

其他流行的 Go 语言 Web 框架还包括 Beego、Echo 和 GoFrame 等,它们各自提供不同的特性,满足开发者的多样化需求。

Gin 框架的设计特点

(1) Gin 是基于 net/http 的轻量级封装

  • Gin 本质上是 net/http 的增强版,只是提供了 路由中间件JSON 解析 等功能。
  • 你可以随时回退到 net/http 原生 API,比如 http.ListenAndServe()

(2) Gin 采用 Context 传递请求

  • gin.Context 是请求的核心,封装了 请求参数、请求体、响应 等信息。
  • 对比 Spring MVC
    • Spring MVC 依赖 HttpServletRequestHttpServletResponse 处理请求。
    • Gin 直接用 c *gin.Context,更简洁,但没有 Spring 的复杂功能。

要开始使用, 需要先在本机安装 go , 由于本机是 mac, 就只介绍 mac 的安装:

1. 安装 Go

在 macOS 上安装 Go 可以通过 Homebrew 或官方安装包进行:

方法 1:使用 Homebrew(推荐)
  1. 打开终端(Terminal),运行:

    brew install go

  2. 安装完成后,检查是否安装成功:

    go version

    输出示例

    go version go1.21.3 darwin/arm64

    (版本号可能不同)
方法 2:使用官方安装包
  1. 访问 Go 官网 下载适用于 macOS 的安装包。
  2. 双击 .pkg 文件进行安装。
  3. 安装完成后,在终端输入 go version 进行验证。

2. 配置 Go 环境变量(可选)

Go 默认的 GOPATH 目录为 ~/go,如果想自定义,可以在 ~/.zshrc(或 ~/.bashrc)中添加:

export GOPATH=$HOME/go export PATH=$GOPATH/bin:$PATH export PATH=/usr/local/go/bin:$PATH

然后执行:

source ~/.zshrc # 若使用 bash,改为 source ~/.bashrc

3. 安装 Gin 框架

Go 安装完毕后,开始安装 Gin:

go install github.com/gin-gonic/gin@latest

或在项目中使用:

go mod init myproject # 初始化 Go 模块

go get -u github.com/gin-gonic/gin

在这里你可能就遇到了死活下载不了的情况了, 这是因为国内的网络, 需要你设置个代理:

在国内,由于网络限制,go get 可能会遇到超时问题,可以使用 Go 官方或国内的代理加速下载。你可以尝试以下几种方法:


方法 1:使用 Go 官方代理(推荐)

Go 提供了一个官方代理,可以避免直接访问 GitHub:

go env -w GOPROXY=https://proxy.golang.org,direct

该代理在国内可能不可用,如果仍然超时,尝试方法 2。


方法 2:使用国内 Go 代理

国内有多个 Go 代理,比如:

  • 阿里云https://mirrors.aliyun.com/goproxy/
  • 七牛云https://goproxy.cn/
  • 腾讯云https://mirrors.cloud.tencent.com/go/
  • 中国科技大学https://mirrors.ustc.edu.cn/goproxy/

可以使用阿里云代理(推荐):

go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct

或者使用 goproxy.cn:

go env -w GOPROXY=https://goproxy.cn,direct

然后再执行:

go get -u github.com/gin-gonic/gin


方法 3:手动下载并替换

如果 go get 仍然无法使用,可以手动下载 gin 代码,并手动放入 go mod 目录:

git clone https://github.com/gin-gonic/gin.git

然后将 gin 代码放入 Go 的 pkg/mod 目录,并在 go.mod 文件中添加:

require github.com/gin-gonic/gin latest replace github.com/gin-gonic/gin => ./gin

然后执行:

go mod tidy

验证 Go 代理是否生效

可以运行:

go env GOPROXY

如果返回的是国内代理地址(如 https://goproxy.cn),说明代理已生效。

4. 创建一个简单的 Gin Web 服务

  1. 在终端运行:

    mkdir gin-demo && cd gin-demo go mod init gin-demo

  2. 创建 main.go
    package main
    
    import (
        "github.com/gin-gonic/gin"
        "net/http"
    )
    
    func main() {
        r := gin.Default()
        r.GET("/", func(c *gin.Context) {
            c.JSON(http.StatusOK, gin.H{"message": "Hello, Gin!"})
        })
        r.Run(":8080") // 启动 Web 服务,监听 8080 端口
    }
    
  3. 运行:

    go run main.go

  4. 在浏览器中访问 http://localhost:8080,看到:

    {"message": "Hello, Gin!"}

到这里, 最简单的 hello world 你就跑通过了.

目前关于 go 的 IDE:

VS Code(免费,推荐)

  • 特点
    • 免费开源
    • 插件丰富(安装 Go 插件即可)
    • 轻量级,适合 macOS
  • 安装步骤
    1. 下载 VS Code:Visual Studio Code - Code Editing. Redefined
    2. 安装 Go 插件:
      • 打开 VS Code,按 Cmd + Shift + X 进入扩展市场
      • 搜索 Go 并安装官方插件
    3. 配置 Go:
      • 终端执行 go env -w GO111MODULE=on(启用 Go Modules)
      • 在 VS Code 终端运行 go mod tidy(整理依赖)

下面就是关于 Gin 的具体的 Web 请求的示例:

1. GET 请求示例

(1) 获取 URL 上的单个参数

r.GET("/query", func(c *gin.Context) {
    name := c.Query("name") // 获取 URL 查询参数 /query?name=Tom
    c.JSON(200, gin.H{"name": name})
})

请求示例
http://localhost:8080/query?name=Tom


(2) 获取 URL 上的多个参数

r.GET("/query/multi", func(c *gin.Context) {
    firstName := c.Query("first_name")
    lastName := c.Query("last_name")
    c.JSON(200, gin.H{"first_name": firstName, "last_name": lastName})
})

请求示例
http://localhost:8080/query/multi?first_name=John&last_name=Doe


(3) 获取路径参数

r.GET("/user/:id", func(c *gin.Context) {
    userID := c.Param("id") // 获取 URL 路径参数
    c.JSON(200, gin.H{"user_id": userID})
})

请求示例
http://localhost:8080/user/123


2. POST 请求示例

(1) 获取 x-www-form-urlencoded 的单个参数

r.POST("/post/single", func(c *gin.Context) {
    name := c.PostForm("name") // 表单参数
    c.JSON(200, gin.H{"name": name})
})

POST 表单示例

Content-Type: application/x-www-form-urlencoded name=Alice


(2) 获取多个 x-www-form-urlencoded 参数

r.POST("/post/multi", func(c *gin.Context) {
    username := c.PostForm("username")
    password := c.PostForm("password")
    c.JSON(200, gin.H{"username": username, "password": password})
})

POST 表单示例

Content-Type: application/x-www-form-urlencoded username=admin&password=123456


(3) POST 路径参数

r.POST("/post/user/:id", func(c *gin.Context) {
    userID := c.Param("id")
    c.JSON(200, gin.H{"user_id": userID})
})

请求示例
http://localhost:8080/post/user/789


(4) 解析 JSON 参数

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

r.POST("/post/json", func(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"user": user})
})

POST JSON 示例

{ "name": "Alice", "email": "[email protected]" }

请求头

Content-Type: application/json


(5) 文件上传

r.POST("/upload", func(c *gin.Context) {
    file, err := c.FormFile("file")
    if err != nil {
        c.JSON(400, gin.H{"error": "Failed to get file"})
        return
    }

    c.SaveUploadedFile(file, "./uploads/"+file.Filename) // 保存文件
    c.JSON(200, gin.H{"message": "File uploaded", "filename": file.Filename})
})

上传示例: 用 Postmancurl 发送 multipart/form-data

curl -X POST http://localhost:8080/upload -F "[email protected]"


3. PUT 请求示例

r.PUT("/update/:id", func(c *gin.Context) {
    id := c.Param("id")
    name := c.PostForm("name")
    email := c.PostForm("email")

    c.JSON(200, gin.H{
        "id":    id,
        "name":  name,
        "email": email,
    })
})

请求示例

curl -X PUT http://localhost:8080/update/123 -d "[email protected]"

返回 JSON

{ "id": "123", "name": "Tom", "email": "[email protected]" }


关于代码就到了这里, 下面就是一些 gin 开发常见的知识了:

Gin Web 开发的最佳实践

(1) 结构化代码,遵循 MVC 分层

  • 推荐结构(类似 Java 分层):
project-root/
│── main.go             # 入口文件
│── router/             # 路由层
│   ├── router.go       # 路由初始化
│── controller/         # 处理 HTTP 请求
│   ├── user_controller.go
│── service/            # 业务逻辑层
│   ├── user_service.go
│── model/              # 数据模型(对应数据库表)
│   ├── user.go
│── repository/         # 数据访问层(封装数据库操作)
│   ├── user_repository.go
│── config/             # 配置文件
│   ├── config.yaml

示例:

  • Controller 层
func GetUser(c *gin.Context) {
    id := c.Param("id")
    user := service.GetUserByID(id)
    c.JSON(200, gin.H{"user": user})
}
  • Service 层
func GetUserByID(id string) model.User {
    return repository.FindUserByID(id)
}
  • Repository 层
func FindUserByID(id string) model.User {
    var user model.User
    db.Where("id = ?", id).First(&user)
    return user
}


(2) 统一错误处理

Gin 没有 Spring Boot 那样的 @ExceptionHandler,你可以用 中间件 统一处理错误:

func ErrorHandler() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Next() // 处理请求
        for _, err := range c.Errors {
            c.JSON(500, gin.H{"error": err.Error()})
        }
    }
}

然后在 main.go 里:

r.Use(ErrorHandler())


(3) 配置管理

  • Java 里一般用 application.propertiesapplication.yml,在 Gin 里可以用 Viper
import "github.com/spf13/viper"

func InitConfig() {
    viper.SetConfigName("config")
    viper.SetConfigType("yaml")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        panic(err)
    }
}

示例 config.yaml

server:
  port: 8080
database:
  host: localhost
  user: root
  password: 123456

然后在 main.go 里:

viper.GetString("database.user")


(4) 使用 gorm 进行数据库操作

Gin 没有 Spring Data JPA,推荐用 gorm

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

var db *gorm.DB

func InitDB() {
    dsn := "root:123456@tcp(127.0.0.1:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"
    var err error
    db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("Failed to connect to database")
    }
}

然后:

type User struct {
    ID    uint   `json:"id" gorm:"primaryKey"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func GetUsers(c *gin.Context) {
    var users []User
    db.Find(&users)
    c.JSON(200, users)
}

4. Gin 开发的常见坑

(1) gin.Context 不能跨 goroutine 传递

go func() { fmt.Println(c.Param("id")) // ❌ 不能这样用 }()

正确做法:

id := c.Param("id") 
go func(id string) {
    fmt.Println(id) // ✅ 这样才行
}(id)

(2) JSON 解析失败不会自动返回 400

Gin 解析 JSON 需要 手动校验

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

(3) go run main.go 修改代码后不会自动重启

  • Java 里 Spring Boot 有 devtools,Go 需要 air 这样的工具:
go install github.com/cosmtrek/air@latest
air

总结

对比点 Java Web(Spring Boot) Go Web(Gin)
框架体积 大,Spring Boot 依赖多 轻量级,仅 1MB
并发模型 线程 + 线程池 Goroutine + Channel
依赖注入 @Autowired 手动管理
JSON 解析 @RequestBody 自动解析 ShouldBindJSON()
异常处理 @ExceptionHandler c.Errors + 中间件
数据库 Spring Data JPA gorm

你已经有了 Java Web 经验,学 Gin 上手会很快,掌握 Gin 路由、gorm 数据库操作、中间件 这三点,就能开发完整 Web 项目!

你可能感兴趣的:(Golang,golang,gin,开发语言)