Golang实现简单的用户列表管理系统

推荐用 map[string]User + struct 实现内存用户列表,以ID为键、封装读写锁防并发panic,并优于slice遍历;后续可平滑对接Redis/SQL或JSON持久化。

用 map + struct 实现内存版用户列表

Go 里没有内置的“数据库”,但日常开发中常需要快速验证逻辑,直接用 map[string]User 搭配结构体是最轻量、最可控的方式。它不依赖外部服务,启动即用,适合 CLI 工具、原型或单元测试。

关键点在于:键选 ID 还是 Username?推荐用 string 类型的 ID(如 UUID 或自增字符串),避免用户名变更导致 map key 失效;同时加一层封装,隐藏底层 map 操作,防止并发 panic。

type User struct {
    ID       string `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
}

type UserManager struct {
    users map[string]User
    mu    sync.RWMutex
}

func NewUserManager() *UserManager {
    return &UserManager{
        users: make(map[string]User),
    }
}

func (um *UserManager) Add(u User) {
    um.mu.Lock()
    defer um.mu.Unlock()
    um.users[u.ID] = u
}

为什么不用 slice 而坚持用 map

有人会想:用户不多,用 []User 遍历查找也行。但实际写起来很快会遇到问题:

  • FindUserByUsername 每次都要遍历,O(n) 时间复杂度,1000 用户就明显卡顿
  • 删除操作需手动重建 slice,容易漏掉 append 或索引越界
  • 无法保证 ID 唯一性,得额外校验;而 map 赋值天然覆盖,users[id] = u 一行就完成“更新或插入”
  • 后续如果要对接 Redis 或 SQL,map 接口更容易抽象成统一的 UserRepo 接口

JSON 文件持久化时的常见坑

把内存数据存到 users.json 是进阶一步,但 Go 的 json.MarshalIndentos.WriteFile 组合容易出错:

立即学习“go语言免费学习笔记(深入)”;

  • 没加 sync.RWMutex,多 goroutine 同时写文件会导致内容被截断或乱码
  • 写入前没做 os.MkdirAll,路径不存在直接 panic
  • json.Unmarshal 读文件后,忘了检查返回的 err != nil,空 map 看似正常,实则数据丢失
  • 结构体字段没加 json: tag,导出失败(比如字段名是 EmailAddr 却期望 JSON 里是 email

建议封装一个 SaveToFile(path string) 方法,在内部统一处理这些细节。

命令行交互别硬写 switch-case

用户列表管理免不了 CLI 输入,比如输入 listadd --name alice。别从头解析 os.Args,直接用 github.com/spf13/cobra —— 它不是“大材小用”,而是省掉 80% 边界判断:

  • 自动处理 --help、未知参数报错、子命令嵌套(如 user delete --id=abc
  • 参数绑定到 struct 字段,不用手写 flag.String + 类型转换
  • 错误提示友好,比如 required flag(s) "id" not set,比自己写的 if id == "" { panic(...) } 可维护得多

哪怕只支持 3 个命令,用 cobra 也比裸写更稳——尤其当后期要加 flag 校验、配置文件支持时,架构不会推倒重来。

真正难的不是增删改查,而是决定什么时候该把 map[string]User 换成接口 UserRepo,以及第一行 go run main.go 跑起来后,是否记得加单元测试覆盖并发读写场景。