编程 Go 测试数据不用手写:用 go-faker 按标签生成结构化假数据

2026-09-12 09:50:25

Go 测试数据不用手写:用 go-faker 按标签生成结构化假数据

go-faker 是一个 Go 的假数据生成库,仓库在 github.com/go-faker/faker,文档在 pkg.go.dev

1. 为什么需要假数据生成

有一个用户结构体:

type User struct {
    Name    string
    Email   string
    Phone   string
    Age     int
    Address string
}

需要 100 个用户来做测试。

手动写:

users := []User{
    {Name: "张三", Email: "zhangsan@example.com", Phone: "13800138000", Age: 25, Address: "北京市朝阳区"},
    {Name: "李四", Email: "lisi@example.com", Phone: "13900139000", Age: 30, Address: "上海市浦东新区"},
    // ... 还要写 98 个
}

又累又容易出错,而且数据看起来太假。

用 go-faker:

var users []User
for i := 0; i < 100; i++ {
    var user User
    faker.FakeData(&user)
    users = append(users, user)
}

2. go-faker 是什么

go-faker 是一个 Go 语言的假数据生成库。

用官方话说:

Go (Golang) Fake Data Generator for Struct.

具体来说:

  • 为结构体生成假数据
  • 基于标签(tag)配置
  • 支持各种数据类型
  • 简单好用

核心定位

go-faker 不是数据库填充工具,也不是数据脱敏工具。

它是一个结构体数据生成器,用于快速生成看起来真实的假数据。

做的事情很简单:

  1. 定义结构体
  2. 添加标签指定生成规则
  3. 调用 FakeData 生成数据

3. 核心特性:标签系统

go-faker 最强大的特性是标签系统。

基础标签

type User struct {
    Name    string `faker:"name"`
    Email   string `faker:"email"`
    Phone   string `faker:"phone_number"`
    Age     int    `faker:"oneof: 18, 25, 30, 35, 40"`
    Address string `faker:"address"`
}

常用标签:

  • name - 姓名
  • email - 邮箱
  • phone_number - 电话号码
  • address - 地址
  • credit_card_number - 信用卡号
  • url - URL
  • username - 用户名
  • password - 密码
  • sentence - 句子
  • paragraph - 段落

长度限制

type Article struct {
    Title   string `faker:"sentence,length:10"`
    Content string `faker:"paragraph,length:100"`
}

范围限制

type Product struct {
    Price    float64 `faker:"amount,range: 10.0-1000.0"`
    Quantity int     `faker:"boundary_start: 1, boundary_end: 100"`
}

唯一值

type User struct {
    ID    string `faker:"uuid,unique"`
    Email string `faker:"email,unique"`
}

4. 安装和使用

安装:

go get github.com/go-faker/faker/v4

基本使用

1. 简单结构体

package main

import (
    "fmt"
    "github.com/go-faker/faker/v4"
)

type User struct {
    Name  string `faker:"name"`
    Email string `faker:"email"`
    Phone string `faker:"phone_number"`
    Age   int    `faker:"oneof: 18, 25, 30, 35, 40"`
}

func main() {
    var user User
    err := faker.FakeData(&user)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Printf("User: %+v\n", user)
    // 输出示例:
    // User: {Name:John Doe Email:john.doe@example.com Phone:+1-555-1234567 Age:25}
}

2. 嵌套结构体

type Address struct {
    Street string `faker:"street_address"`
    City   string `faker:"city"`
    State  string `faker:"state"`
    Zip    string `faker:"zip"`
}

type User struct {
    Name    string  `faker:"name"`
    Email   string  `faker:"email"`
    Address Address `faker:"address"`
}

func main() {
    var user User
    faker.FakeData(&user)

    fmt.Printf("User: %+v\n", user)
    fmt.Printf("Address: %+v\n", user.Address)
}

3. 切片和数组

type Company struct {
    Name      string `faker:"company"`
    Employees []User // 自动生成 3-10 个员工
}

func main() {
    var company Company
    faker.FakeData(&company)

    fmt.Printf("Company: %s\n", company.Name)
    fmt.Printf("Employees: %d\n", len(company.Employees))
}

4. Map

type Config struct {
    Settings map[string]string `faker:"word,unique"`
}

func main() {
    var config Config
    faker.FakeData(&config)

    for key, value := range config.Settings {
        fmt.Printf("%s: %s\n", key, value)
    }
}

5. 支持的假数据类型

go-faker 支持多种假数据类型。

个人信息

type Person struct {
    Name      string `faker:"name"`
    FirstName string `faker:"first_name"`
    LastName  string `faker:"last_name"`
    Gender    string `faker:"gender"`
    SSN       string `faker:"ssn"` // 社会安全号
    Phone     string `faker:"phone_number"`
    Email     string `faker:"email"`
    Contact   struct {
        Phone string `faker:"phone_number"`
        Email string `faker:"email"`
    }
}

地址信息

type Location struct {
    Address   string  `faker:"street_address"`
    City      string  `faker:"city"`
    State     string  `faker:"state"`
    Zip       string  `faker:"zip"`
    Country   string  `faker:"country"`
    Latitude  float64 `faker:"lat"`
    Longitude float64 `faker:"long"`
}

网络信息

type Internet struct {
    URL      string `faker:"url"`
    Domain   string `faker:"domain_name"`
    IP       string `faker:"ipv4"`
    IPv6     string `faker:"ipv6"`
    MAC      string `faker:"mac_address"`
    UserName string `faker:"username"`
    Password string `faker:"password"`
}

金融信息

type Finance struct {
    CreditCardNumber string  `faker:"credit_card_number"`
    CreditCardType   string  `faker:"credit_card_type"`
    Amount           float64 `faker:"amount"`
    Currency         string  `faker:"currency"`
}

公司信息

type Business struct {
    Company    string `faker:"company"`
    Department string `faker:"department"`
    JobTitle   string `faker:"job_title"`
    Industry   string `faker:"industry"`
}

时间信息

type TimeInfo struct {
    Date     time.Time `faker:"time"`
    Time     time.Time `faker:"timestamp"`
    Duration time.Duration
}

文本信息

type Content struct {
    Word      string `faker:"word"`
    Sentence  string `faker:"sentence"`
    Paragraph string `faker:"paragraph"`
    UUID      string `faker:"uuid"`
}

6. 高级功能

自定义生成器

faker.AddProvider("custom_id", func(v reflect.Value) (interface{}, error) {
    return fmt.Sprintf("ID-%d", time.Now().UnixNano()), nil
})

type User struct {
    ID   string `faker:"custom_id"`
    Name string `faker:"name"`
}

模板生成

type User struct {
    FirstName string `faker:"first_name"`
    LastName  string `faker:"last_name"`
    Email     string `faker:"email"`
    // 基于其他字段生成
    Username  string `faker:"{{.FirstName}}.{{.LastName}}"`
}

边界控制

type Product struct {
    Price    float64 `faker:"amount,range: 10.0-1000.0"`
    Quantity int     `faker:"boundary_start: 1, boundary_end: 100"`
    Rating   int     `faker:"oneof: 1, 2, 3, 4, 5"`
}

忽略某些字段

type User struct {
    Name      string `faker:"name"`
    Email     string `faker:"email"`
    SecretKey string `faker:"-"` // 忽略这个字段
}

7. 实战场景

场景一:单元测试

问题:测试用户注册功能,需要大量测试数据。

解决方案

func TestUserRegistration(t *testing.T) {
    // 生成 100 个测试用户
    var users []User
    for i := 0; i < 100; i++ {
        var user User
        err := faker.FakeData(&user)
        require.NoError(t, err)
        users = append(users, user)
    }

    // 测试注册逻辑
    for _, user := range users {
        err := RegisterUser(user)
        assert.NoError(t, err)
    }
}

效果:快速生成测试数据,覆盖各种边界情况。

场景二:演示系统

问题:需要给演示系统填充看起来真实的用户数据。

解决方案

func SeedDemoData() error {
    db := GetDB()

    // 生成 1000 个用户
    for i := 0; i < 1000; i++ {
        var user User
        faker.FakeData(&user)

        // 保存到数据库
        if err := db.Create(&user).Error; err != nil {
            return err
        }
    }

    return nil
}

效果:演示系统看起来真实可信。

场景三:性能测试

问题:需要对订单系统进行压力测试。

解决方案

func BenchmarkOrderProcessing(b *testing.B) {
    // 生成 10000 个订单
    var orders []Order
    for i := 0; i < 10000; i++ {
        var order Order
        faker.FakeData(&order)
        orders = append(orders, order)
    }

    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        ProcessOrders(orders)
    }
}

效果:大量真实数据进行性能测试。

场景四:开发环境初始化

问题:本地开发环境需要初始数据。

解决方案

// seed.go
package main

func main() {
    db := InitDB()

    // 生成用户
    var users []User
    for i := 0; i < 100; i++ {
        var user User
        faker.FakeData(&user)
        users = append(users, user)
    }
    db.Create(&users)

    // 生成商品
    var products []Product
    for i := 0; i < 50; i++ {
        var product Product
        faker.FakeData(&product)
        products = append(products, product)
    }
    db.Create(&products)

    fmt.Println("Seed data created successfully!")
}

效果:一键初始化开发环境。

8. 设计亮点

亮点一:标签驱动

通过标签配置生成规则,代码简洁。

好处:

  • 声明式配置
  • 易于理解
  • 灵活扩展

亮点二:类型安全

基于结构体生成,类型安全。

好处:

  • 编译时检查
  • IDE 支持
  • 重构友好

亮点三:嵌套支持

支持复杂的嵌套结构。

好处:

  • 真实数据结构
  • 一次生成
  • 无需手动处理

亮点四:可扩展

支持自定义生成器。

好处:

  • 业务特定数据
  • 灵活定制
  • 满足特殊需求

亮点五:零依赖

纯 Go 实现,无外部依赖。

好处:

  • 易于集成
  • 编译快
  • 跨平台

9. 和类似方案对比

vs. gofakeit

维度go-fakergofakeit
Star8601.5K
API标签驱动函数调用
灵活性
易用性

结论:go-faker 标签驱动更优雅,gofakeit 函数调用更直接。

vs. 手动生成

维度go-faker手动生成
开发效率
数据真实性
维护成本
灵活性最高

结论:go-faker 效率更高,手动生成更灵活。

vs. 数据库种子

维度go-faker数据库种子
速度
依赖数据库
复用性
真实性

结论:go-faker 更轻量,数据库种子更完整。

10. 局限性

go-faker 也有局限:

  1. Star 数少:860 Star,社区相对较小
  2. 数据真实度:生成的数据可能不够真实
  3. 中文支持:默认英文,中文需要自定义
  4. 关系数据:不支持生成关联数据
  5. 业务逻辑:无法生成符合业务逻辑的数据
  6. 性能:大量数据生成时可能较慢

11. 总结

从 go-faker 这个项目可以看到几个趋势:

  1. 测试数据是刚需:每个项目都需要测试数据
  2. 自动化是方向:手动生成太慢,自动生成是趋势
  3. 标签驱动是优雅:声明式配置,代码简洁
  4. 类型安全很重要:编译时检查,减少错误
  5. 可扩展性是必须:支持自定义,满足特殊需求

go-faker 虽然 Star 不多,但解决的是真问题。

如果还在手动生成测试数据,可以试试 go-faker。

也许有一天,Go 标准库会提供内置的假数据生成。在那之前,go-faker 可以用于生成测试数据。


参考资料

复制全文 生成海报 Go go-faker 测试 单元测试 假数据

推荐文章

程序员茄子在线接单