You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang Gin中编写正确的注册查询 解决创建用户报错问题

修复方案

核心错误点

  • SQL预处理用法错误:使用fmt.Sprintf拼接SQL语句,且给占位符?包裹了单引号,直接导致SQL语法错误。预处理的占位符不需要加引号,也不要手动拼接参数到SQL语句中,避免语法错误和SQL注入风险。
  • 仅预编译SQL未执行:db.Prepare()仅完成SQL预编译,没有调用Exec()传入参数执行语句,数据不会写入数据库。
  • 错误处理不合理:遇到错误直接调用log.Fatal()会终止整个服务,且仅打印自定义错误信息,没有输出原始报错,无法定位问题根因。
  • 结构体字段权限问题:User结构体中firstname、lastname、password为小写首字母的私有字段,序列化、ORM绑定时无法正常访问,后续扩展会出现异常。
  • 主键插入逻辑问题:用户表ID通常为自增主键,不需要显式插入,传入重复ID会触发唯一索引冲突报错。

修正后代码

model/user.go

package model

type User struct {
    ID        int    `json:"id"`
    Firstname string `json:"firstname"`
    Lastname  string `json:"lastname"`
    Username  string `json:"username"`
    Password  string `json:"password"`
    Isadmin   bool   `json:"is_admin"`
}

注册控制器代码

package controller

import (
    "LoginRegister/dto"
    "LoginRegister/repository"
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
)

type RegisterController struct {
}

func (lc *RegisterController) Register(c *gin.Context) {
    var registerRequest dto.RegisterRequest
    if err := c.ShouldBindJSON(&registerRequest); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{
            "message": "请求参数错误",
        })
        return
    }

    db := repository.Database
    if db == nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "数据库连接异常",
        })
        return
    }

    // 预编译SQL,占位符无需加引号
    stmt, err := db.Prepare("INSERT INTO users(`firstname`,`lastname`,`Username`,`password`,`isadmin`) VALUES (?,?,?,?,?)")
    if err != nil {
        log.Printf("SQL预编译失败: %v", err)
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "服务内部错误",
        })
        return
    }
    defer stmt.Close()

    // 执行插入操作,传入对应参数,生产环境请先对密码做bcrypt加密
    res, err := stmt.Exec(registerRequest.Firstname, registerRequest.Lastname, registerRequest.Username, registerRequest.Password, registerRequest.Isadmin)
    if err != nil {
        log.Printf("用户插入失败: %v", err)
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "创建用户失败",
        })
        return
    }

    userId, _ := res.LastInsertId()
    c.JSON(http.StatusOK, gin.H{
        "message": "注册成功",
        "user_id": userId,
    })
}

注意事项

  • 生产环境禁止明文存储用户密码,必须使用bcrypt等不可逆加密算法加密后再存入数据库
  • dto.RegisterRequest需要保证所有字段首字母大写,并添加对应的json标签,否则参数绑定会失败
  • 如果表ID不是自增主键,需要手动传入ID的话,在SQL语句中补充ID字段和对应占位符,执行时传入ID参数即可

内容的提问来源于stack exchange,提问作者Cebrayil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:36:03