在国内,Gin 被广泛认为是使用最为广泛的 Go 语言 Web 开发框架。它以高性能和简洁的 API 设计而著称,特别适合构建高并发的服务。
此外,Kratos 作为 B 站开源的微服务框架,也在国内拥有一定的用户基础,适用于构建复杂的分布式系统。
其他流行的 Go 语言 Web 框架还包括 Beego、Echo 和 GoFrame 等,它们各自提供不同的特性,满足开发者的多样化需求。
net/http
的轻量级封装net/http
的增强版,只是提供了 路由、中间件、JSON 解析 等功能。net/http
原生 API,比如 http.ListenAndServe()
。Context
传递请求gin.Context
是请求的核心,封装了 请求参数、请求体、响应 等信息。HttpServletRequest
和 HttpServletResponse
处理请求。c *gin.Context
,更简洁,但没有 Spring 的复杂功能。要开始使用, 需要先在本机安装 go , 由于本机是 mac, 就只介绍 mac 的安装:
在 macOS 上安装 Go 可以通过 Homebrew 或官方安装包进行:
brew install go
go version
go version go1.21.3 darwin/arm64
.pkg
文件进行安装。go version
进行验证。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
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 官方或国内的代理加速下载。你可以尝试以下几种方法:
Go 提供了一个官方代理,可以避免直接访问 GitHub:
go env -w GOPROXY=https://proxy.golang.org,direct
但该代理在国内可能不可用,如果仍然超时,尝试方法 2。
国内有多个 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
如果 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 env GOPROXY
如果返回的是国内代理地址(如 https://goproxy.cn
),说明代理已生效。
mkdir gin-demo && cd gin-demo go mod init gin-demo
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 端口
}
go run main.go
{"message": "Hello, Gin!"}
到这里, 最简单的 hello world 你就跑通过了.
目前关于 go 的 IDE:
Go
插件即可)Go
插件:
Cmd + Shift + X
进入扩展市场go env -w GO111MODULE=on
(启用 Go Modules)go mod tidy
(整理依赖)下面就是关于 Gin 的具体的 Web 请求的示例:
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
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
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
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
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
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
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
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})
})
上传示例: 用 Postman
或 curl
发送 multipart/form-data
:
curl -X POST http://localhost:8080/upload -F "[email protected]"
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 开发常见的知识了:
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
示例:
func GetUser(c *gin.Context) {
id := c.Param("id")
user := service.GetUserByID(id)
c.JSON(200, gin.H{"user": user})
}
func GetUserByID(id string) model.User {
return repository.FindUserByID(id)
}
func FindUserByID(id string) model.User {
var user model.User
db.Where("id = ?", id).First(&user)
return user
}
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())
application.properties
或 application.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")
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)
}
gin.Context
不能跨 goroutine
传递go func() { fmt.Println(c.Param("id")) // ❌ 不能这样用 }()
正确做法:
id := c.Param("id")
go func(id string) {
fmt.Println(id) // ✅ 这样才行
}(id)
Gin 解析 JSON 需要 手动校验:
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
go run main.go
修改代码后不会自动重启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 项目!