1234 字
6 分钟
Go 库和框架
Go 库和框架
一、标准库 net/http
1.1 HTTP Server基础
- 创建http server对象 → 注册路由和处理函数 → 启动http服务器
func main() { // 创建多路复用器 mux := http.NewServeMux()
// 注册路由,w是ResponseWriter,r是Request mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") })
// 启动服务器 err := http.ListenAndServe(":8080", mux) if err != nil { log.Fatal(err) }}
1.2 表单处理
- 获取表单数据
// 必须先解析表单err := r.ParseForm()if err != nil { // 处理错误}
// 获取表单数据的不同方式r.Form // 获取所有表单数据(包括URL查询参数)r.PostForm // 仅获取POST表单数据r.FormValue("key") // 自动调用ParseForm(),获取第一个值r.PostFormValue("password") // 自动调用ParseForm(),仅从POST body获取
- 如何防止重复提交
- Token机制(推荐):生成唯一token存储在Redis,作为隐藏字段添加到表单,提交时验证并删除token
- PRG模式:Post-Redirect-Get,提交后重定向到其他页面
- 前端控制:禁用提交按钮,使用AJAX异步提交
二、Web框架对比
2.1 框架特点
-
Gin - 轻量级高性能
- 极简设计,专注HTTP路由和中间件
- 高性能,基于httprouter
- 需要自行实现MVC架构
- 适合微服务和API开发
-
Beego - 全功能框架
- 类似Django的全栈框架
- 内置ORM、Session、缓存、日志等
- 提供完整MVC架构
- 适合快速开发企业应用
2.2 性能差异
-
路由实现
- Gin:使用radix tree(基数树),O(log n)复杂度
- Beego:使用正则和反射,性能相对较低
-
内存分配
- Gin:预分配内存池,减少GC压力
- Beego:功能丰富但内存占用较大
三、Gin框架详解
3.1 初始化方式
-
gin.Default()
- 包含Logger中间件(请求日志)
- 包含Recovery中间件(panic恢复)
- 适合大多数场景
-
gin.New()
- 不包含任何中间件
- 完全自定义配置
- 适合对性能要求极高的场景
3.2 中间件机制
-
实现原理
- 中间件本质是
func(*gin.Context)
类型的函数 - 通过
c.Next()
控制执行流程 - 通过
c.Abort()
中断后续处理
- 中间件本质是
-
执行流程
func Logger() gin.HandlerFunc { return func(c *gin.Context) { // 前置处理 start := time.Now() path := c.Request.URL.Path
// 执行后续中间件和处理函数 c.Next()
// 后置处理 latency := time.Since(start) status := c.Writer.Status() log.Printf("%s %s %d %v", c.Request.Method, path, status, latency) }}
3.3 中间件使用方式
- 全局中间件
r := gin.New()r.Use(Logger(), Recovery())
- 路由组中间件
api := r.Group("/api")api.Use(AuthMiddleware()){ api.GET("/users", getUsers) api.POST("/users", createUser)}
- 单个路由中间件
r.GET("/admin", AuthMiddleware(), AdminHandler)
3.4 常用功能
- 参数绑定
// 路径参数r.GET("/user/:id", func(c *gin.Context) { id := c.Param("id")})
// 查询参数r.GET("/search", func(c *gin.Context) { query := c.Query("q") page := c.DefaultQuery("page", "1")})
// JSON绑定type User struct { Name string `json:"name" binding:"required"` Age int `json:"age" binding:"min=1,max=100"`}r.POST("/user", func(c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return }})
四、RPC框架
4.1 gRPC概述
- 特点
- 基于HTTP/2协议,支持双向流
- 使用Protocol Buffers作为IDL和序列化协议
- 支持多种语言,跨平台
- 内置认证、负载均衡、监控等
4.2 四种调用模式
-
一元RPC(Unary RPC)
- 客户端发送一个请求,服务端返回一个响应
- 类似传统的函数调用
-
服务端流式RPC(Server Streaming RPC)
- 客户端发送一个请求,服务端返回数据流
- 适用于大数据传输、实时推送
-
客户端流式RPC(Client Streaming RPC)
- 客户端发送数据流,服务端返回一个响应
- 适用于文件上传、数据采集
-
双向流式RPC(Bidirectional Streaming RPC)
- 客户端和服务端都可以发送数据流
- 适用于聊天、游戏等实时交互
4.3 调用过程
-
客户端调用
- 调用Stub(客户端存根)的方法
- 将请求参数序列化为Protocol Buffers格式
-
网络传输
- 使用HTTP/2协议传输
- 支持多路复用、流控制、头部压缩
-
服务端处理
- 服务端接收并反序列化请求
- 调用实际的服务实现方法
- 将响应序列化后返回
-
客户端接收
- 反序列化响应数据
- 返回给调用方
4.4 gRPC vs REST
- 性能:gRPC使用二进制协议,性能更高
- 流式传输:gRPC原生支持流式传输
- 类型安全:gRPC通过Proto文件定义强类型接口
- 浏览器支持:REST更好,gRPC需要grpc-web
- 调试:REST更容易调试(JSON可读)
五、数据库操作
5.1 database/sql
- 基础用法
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")defer db.Close()
// 查询单行var name stringerr = db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
// 查询多行rows, err := db.Query("SELECT id, name FROM users WHERE age > ?", 18)defer rows.Close()for rows.Next() { var id int var name string err = rows.Scan(&id, &name)}
// 执行更新result, err := db.Exec("UPDATE users SET name = ? WHERE id = ?", "Alice", 1)affected, _ := result.RowsAffected()
5.2 GORM
-
特点
- 全功能ORM
- 支持关联、钩子、事务
- 自动迁移
- SQL构建器
-
基础用法
type User struct { gorm.Model Name string Age int}
// 自动迁移db.AutoMigrate(&User{})
// CRUD操作db.Create(&User{Name: "Alice", Age: 20})db.First(&user, 1)db.Model(&user).Update("Age", 21)db.Delete(&user)