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

Gin-Gonic框架中创建用户时的空指针引用问题排查

Golang用户创建功能空指针错误排查

问题描述

我正在使用Golang实现用户创建功能,在UserImplementation结构体中定义了接收User模型指针的CreateUser()函数,用于在数据库中创建新用户记录。但运行该函数时持续出现“Nil pointer”错误,需要排查问题所在。

相关代码

CreateUser() 函数实现

func (usr *UserImplementation) CreateUser(user *models.User) (*models.User, error) {

    fmt.Println("User date", user.CreatedAt)
    fmt.Println("User name", user.FirstName)
    fmt.Println("User data", user.Password)

    pg := databaseapi.NewApiConfig{}

    params := database_utils.CreateUserParams{
        ID:           uuid.New(),
        CreatedAt:    time.Now().UTC(),
        UpdatedAt:    time.Now().UTC(),
        FirstName:    user.FirstName,
        LastName:     user.LastName,
        OtherName:    user.OtherName,
        Password:     user.Password,
        Email:        user.Email,
        ProfileImage: user.ProfileImage,
        Status:       user.Status,
        Username:     user.Username,
        IsAdmin:      user.IsAdmin,
        Role:         user.Role,
        Gender:       user.Gender,
        PhoneNumber:  user.PhoneNumber,
    }

    userResponse, err := pg.ApiConfig.DB.CreateUser(usr.ctx, params)

    if err != nil {
        return nil, fmt.Errorf("error: %v", err.Error())
    }
    return (*models.User)(&userResponse), nil

}

UserController 结构体及方法

type UserController struct {
    UserCtrl *usersimpl.UserImplementation
}

func (usrCtrl *UserController) CreateUser(ctx *gin.Context) {
    var user models.User
    
    if err := ctx.ShouldBindJSON(&user); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "Error": err.Error(),
        })
        return
    }
    
    _, err := utilities.EmailValidator(user.Email)
    
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "Error": err.Error(),
        })
        return
    }

    hashPassword, err := utilities.HashPassword(user.Password)
    
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "Error": err.Error(),
        })
    }

    user.Password = hashPassword
    
    resp, err := usrCtrl.UserCtrl.CreateUser(&user)
    
    if err != nil {
        ctx.JSON(
            http.StatusBadRequest,
            gin.H{
                "Error": err.Error(),
            },
        )
        return
    }

    ctx.JSON(http.StatusOK, gin.H{
        "response": resp,
    })

}

UserImplementation 结构体及构造函数

type UserImplementation struct {
    pg  *database_utils.Queries
    ctx context.Context
}

func NewUserService(pg *database_utils.Queries, ctx context.Context) *UserImplementation {
    return &UserImplementation{
        pg:  pg,
        ctx: ctx,
    }
}

错误原因分析

  1. 数据库实例未初始化:CreateUser函数中创建的pg := databaseapi.NewApiConfig{}是空结构体,ApiConfig.DB字段未被赋值,调用pg.ApiConfig.DB.CreateUser时触发空指针错误。
  2. 冗余的实例创建:UserImplementation结构体本身已通过构造函数注入了pg *database_utils.Queries实例,无需重新创建databaseapi.NewApiConfig,直接使用自带的pg即可。
  3. 服务实例未正确注入:如果UserController的UserCtrl字段未通过NewUserService初始化赋值,调用usrCtrl.UserCtrl.CreateUser时也会触发空指针错误。

修复方案

修正 CreateUser 函数

去掉冗余的数据库实例创建,直接使用结构体自带的pg字段:

func (usr *UserImplementation) CreateUser(user *models.User) (*models.User, error) {

    fmt.Println("User date", user.CreatedAt)
    fmt.Println("User name", user.FirstName)
    fmt.Println("User data", user.Password)

    params := database_utils.CreateUserParams{
        ID:           uuid.New(),
        CreatedAt:    time.Now().UTC(),
        UpdatedAt:    time.Now().UTC(),
        FirstName:    user.FirstName,
        LastName:     user.LastName,
        OtherName:    user.OtherName,
        Password:     user.Password,
        Email:        user.Email,
        ProfileImage: user.ProfileImage,
        Status:       user.Status,
        Username:     user.Username,
        IsAdmin:      user.IsAdmin,
        Role:         user.Role,
        Gender:       user.Gender,
        PhoneNumber:  user.PhoneNumber,
    }

    // 使用结构体自带的pg实例调用数据库方法
    userResponse, err := usr.pg.CreateUser(usr.ctx, params)

    if err != nil {
        return nil, fmt.Errorf("error: %v", err.Error())
    }
    return (*models.User)(&userResponse), nil
}

确保服务实例正确注入

初始化UserController时,必须传入通过NewUserService创建的实例:

// 假设已初始化database_utils.Queries实例dbQueries和上下文ctx
userService := usersimpl.NewUserService(dbQueries, ctx)
userController := &UserController{
    UserCtrl: userService,
}

额外检查

  • 确认database_utils.Queries实例在注入时不为nil,确保数据库连接已正确建立。
  • 检查ctx.ShouldBindJSON(&user)的绑定结果,该操作的错误已被捕获,不会直接导致空指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:52:13