用Go Fiber快速开发Web应用

一、前言:为什么选择 Golang 和 Fiber?

  • Golang 的优势:天生支持高并发、编译速度快、部署简单,是企业级后端的首选语言之一。
  • Fiber 的亮点:基于 Go 语言的轻量级 Web 框架,对标 Express 和 Koa,提供更简洁的 API 设计和极致的性能(底层集成 Fasthttp)。
  • 适用场景:API 开发、微服务、实时应用等高并发场景。

二、环境准备

1. 安装 Go 环境

bash 复制代码
# 下载并安装 Go(以 Linux/macOS 为例)
curl -o- https://raw.githubusercontent.com/golang/install/master/install.sh | bash

# 验证安装
go version

2. 安装 Fiber CLI

bash 复制代码
go get github.com/gofiber/fiber/v2/cmd/fiber

3. 创建新项目

arduino 复制代码
fiber new hello-world
cd hello-world

三、核心代码解析:从零构建一个 API

1.main.go入门示例

go 复制代码
package main

import (
    "log"
    "github.com/gofiber/fiber/v2"
)

func main() {
    app := fiber.New()

    app.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello, Fiber!")
    })

    log.Fatal(app.Listen(":3000"))
}
  • 启动命令go run main.go
  • 访问效果 :浏览器输入http://localhost:3000即可见到 "Hello, Fiber!"。

2. 路由与参数

go 复制代码
app.Get("/user/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    return c.JSON(fiber.Map{
        "message": "User ID is " + id,
    })
})

3. 中间件使用(日志记录)

go 复制代码
func Logger(c *fiber.Ctx) error {
    log.Println("Request:", c.Request().URL.Path)
    return c.Next()
}

app.Use(Logger)

4. 数据库集成(以 SQLite 为例)

go 复制代码
import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

func initDB() *sql.DB {
    db, err := sql.Open("sqlite3", "./test.db")
    if err != nil {
        log.Fatal(err)
    }
    return db
}

// 创建表
db.Exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")

四、Fiber 的性能优势

指标 Fiber Gin Echo
微秒级响应
内存占用 更低 中等 较高
路由匹配速度 极快 中等

五、实例代码

1. 项目结构调整

csharp 复制代码
hello-world/
├── cmd/          # 可执行文件入口(可选)
├── internal/      # 业务逻辑层
│   ├── config/   # 配置文件(数据库连接等)
│   ├── handlers/ # 路由处理函数
│   ├── models/   # 数据模型定义
│   └── services/ # 业务逻辑服务层
├── main.go        # 入口文件
└── go.mod        # Go模块依赖

2. 初始化数据库

(1) 创建 ****config/db.go

go 复制代码
package config

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-sqlite3"
)

var DB *sql.DB

func InitDB() {
    var err error
    DB, err = sql.Open("sqlite3", "./blog.db")
    if err != nil {
        fmt.Printf("Failed to connect to database: %v\n", err)
        return
    }

    // 执行迁移脚本
    _, err = DB.Exec(`
        CREATE TABLE posts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            body TEXT NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        );
    `)
    if err != nil {
        fmt.Printf("Failed to create table: %v\n", err)
        return
    }

    // 插入测试数据
    _, err = DB.Exec("INSERT INTO posts (title, body) VALUES ('Hello World', 'This is my first post!')")
    if err != nil {
        fmt.Printf("Failed to insert seed data: %v\n", err)
        return
    }
}

(2) 在 main.go 中初始化数据库

go 复制代码
func main() {
    config.InitDB()
    defer config.DB.Close()

    app := fiber.New()
    // ... 注册路由
}

3. 定义数据模型

internal/models/post.go

go 复制代码
package models

type Post struct {
    ID        int        `json:"id"`
    Title     string     `json:"title"`
    Body      string     `json:"body"`
    CreatedAt time.Time `json:"created_at"`
}

4. 编写业务逻辑服务层

internal/services/post_service.go

go 复制代码
package services

import (
    "errors"
    "time"

    "hello-world/internal/models"
    "hello-world/internal/config"
)

var ErrPostNotFound = errors.New("post not found")

func GetAllPosts() ([]models.Post, error) {
    rows, err := config.DB.Query("SELECT id, title, body, created_at FROM posts")
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var posts []models.Post
    for rows.Next() {
        var p models.Post
        err := rows.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt)
        if err != nil {
            return nil, err
        }
        posts = append(posts, p)
    }
    return posts, nil
}

func GetPostByID(id int) (*models.Post, error) {
    row := config.DB.QueryRow("SELECT id, title, body, created_at FROM posts WHERE id = ?", id)
    var p models.Post
    err := row.Scan(&p.ID, &p.Title, &p.Body, &p.CreatedAt)
    if err == sql.ErrNoRows {
        return nil, ErrPostNotFound
    }
    return &p, err
}

func CreatePost(title, body string) (*models.Post, error) {
    res, err := config.DB.Exec(
        "INSERT INTO posts (title, body) VALUES (?, ?)",
        title,
        body,
    )
    if err != nil {
        return nil, err
    }

    id, err := res.LastInsertId()
    if err != nil {
        return nil, err
    }

    return &models.Post{
        ID:        int(id),
        Title:     title,
        Body:      body,
        CreatedAt: time.Now(),
    }, nil
}

func UpdatePost(id int, title, body string) (*models.Post, error) {
    row := config.DB.Exec(
        "UPDATE posts SET title = ?, body = ? WHERE id = ?",
        title,
        body,
        id,
    )
    if err := row.Error; err != nil {
        return nil, err
    }

    return GetPostByID(id)
}

func DeletePost(id int) error {
    _, err := config.DB.Exec("DELETE FROM posts WHERE id = ?", id)
    return err
}

5. 实现路由和处理函数

internal/handlers/post_handler.go

go 复制代码
package handlers

import (
    "errors"
    "net/http"

    "github.com/gofiber/fiber/v2"
    "hello-world/internal/services"
    "hello-world/internal/models"
)

var ErrPostNotFound = errors.New("post not found")

// GetPosts 获取所有文章
func GetPosts(c *fiber.Ctx) error {
    posts, err := services.GetAllPosts()
    if err != nil {
        return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    return c.JSON(posts)
}

// GetPost 获取单篇文章
func GetPost(c *fiber.Ctx) error {
    id := c.Params("id")
    post, err := services.GetPostByID(id)
    if err == ErrPostNotFound {
        return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "Post not found"})
    }
    if err != nil {
        return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    return c.JSON(post)
}

// CreatePost 创建新文章
func CreatePost(c *fiber.Ctx) error {
    var post models.Post
    if err := c.BodyParser(&post); err != nil {
        return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
    }
    createdPost, err := services.CreatePost(post.Title, post.Body)
    if err != nil {
        return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    return c.Status(http.StatusCreated).JSON(createdPost)
}

// UpdatePost 更新文章
func UpdatePost(c *fiber.Ctx) error {
    id := c.Params("id")
    var post models.Post
    if err := c.BodyParser(&post); err != nil {
        return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
    }
    updatedPost, err := services.UpdatePost(id, post.Title, post.Body)
    if err != nil {
        return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    return c.JSON(updatedPost)
}

// DeletePost 删除文章
func DeletePost(c *fiber.Ctx) error {
    id := c.Params("id")
    err := services.DeletePost(id)
    if err != nil {
        return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
    }
    return c.SendString("Post deleted successfully")
}

6. 注册路由

main.go

go 复制代码
package main

import (
    "log"

    "github.com/gofiber/fiber/v2"
    "hello-world/internal/handlers"
)

func main() {
    config.InitDB()
    defer config.DB.Close()

    app := fiber.New()

    // 路由组:/api/v1
    apiV1 := app.Group("/api/v1")
    {
        apiV1.Get("/posts", handlers.GetPosts)        // GET /api/v1/posts
        apiV1.Get("/posts/:id", handlers.GetPost)      // GET /api/v1/posts/:id
        apiV1.Post("/posts", handlers.CreatePost)      // POST /api/v1/posts
        apiV1.Put("/posts/:id", handlers.UpdatePost)    // PUT /api/v1/posts/:id
        apiV1.Delete("/posts/:id", handlers.DeletePost)// DELETE /api/v1/posts/:id
    }

    log.Fatal(app.Listen(":3000"))
}

7. 测试 API

(1) 使用 Postman 或 cURL 测试

shellscript 复制代码
# 创建文章
curl -X POST -H "Content-Type: application/json" -d '{"title": "My First Post", "body": "Hello Fiber!"}' http://localhost:3000/api/v1/posts

# 获取所有文章
curl http://localhost:3000/api/v1/posts

# 获取单篇文章
curl http://localhost:3000/api/v1/posts/1

# 更新文章
curl -X PUT -H "Content-Type: application/json" -d '{"title": "Updated Post", "body": "Body content"}' http://localhost:3000/api/v1/posts/1

# 删除文章
curl -X DELETE http://localhost:3000/api/v1/posts/1

8. 添加中间件(JWT 认证)

(1) 安装 JWT 包

shellscript 复制代码
go get github.com/gofiber/fiber/v2/middleware/jwt

(2) 生成密钥和配置

go 复制代码
// config/jwt.go
package config

import "github.com/gofiber/fiber/v2/middleware/jwt"

var JWTMiddleware = jwt.New(jwt.Config{
    SigningKey: []byte("your-secret-key"),
})

(3) 保护路由

go 复制代码
// main.go
func main() {
    // ...

    protectedApi := apiV1.Group("/protected")
    {
        protectedApi.Get("/posts", handlers.GetProtectedPosts) // 需要 JWT 认证
    }

    // 全局中间件
    app.Use(config.JWTMiddleware)
}

(4) 处理受保护的路由

go 复制代码
// handlers/post_handler.go
func GetProtectedPosts(c *fiber.Ctx) error {
    // 用户已通过 JWT 认证
    return c.JSON(fiber.Map{"message": "This is a protected route"})
}

9. 部署到云平台(Docker 示例)

(1) 创建 ****Dockerfile

docker 复制代码
# 使用官方 Golang 镜像作为基础镜像
FROM golang:1.20-alpine

# 设置工作目录
WORKDIR /app

# 复制 Go 模块依赖文件
COPY go.mod go.sum ./

# 下载依赖
RUN go mod download

# 复制源代码
COPY . .

# 构建应用
RUN go build -o main .

# 暴露端口
EXPOSE 3000

# 启动容器
CMD ["./main"]

(2) 创建 ****docker-compose.yml

yaml 复制代码
version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app

(3) 运行 Docker

shellscript 复制代码
docker-compose up --build

10. 总结

通过以上步骤,你已经完成了一个包含以下功能的博客 API:

  • 完整的 CRUD 操作
  • SQLite 数据库集成
  • JWT 身份验证保护
  • Docker 部署支持

下一步学习方向

  • 添加分页和过滤功能
  • 实现文件上传(使用 Fiber 的 multipart 中间件)
  • 集成 Redis 缓存高频访问数据
  • 使用 Swagger 自动生成 API 文档

相关推荐
王中阳Go10 小时前
面试完第一反应是想笑
后端·go
Code季风14 小时前
gRPC与Protobuf集成详解—从服务定义到跨语言通信(含Go和Java示例)
go·grpc·protobuf
Code季风14 小时前
Protobuf 高级特性详解
go·protobuf
_代号00714 小时前
Go 编译报错排查:vendor/golang.org/x/crypto/cryptobyte/asn1 no Go source files
后端·go
岁忧1 天前
(LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)
java·c++·算法·leetcode·面试·go
Nejosi_念旧1 天前
解读 Go 中的 constraints包
后端·golang·go
漫步向前1 天前
gin问题知识点汇总
go
mao毛1 天前
go Mutex 深入理解
go·源码阅读
钩子波比1 天前
🚀 Asynq 学习文档
redis·消息队列·go
漫步向前1 天前
beegoMVC问题知识点汇总
go