如何解决 gorm Create() 出现“无效内存地址或 nil 指针取消引用”的恐慌?

new*_*ing 1 go go-gorm go-gin

我不知道如何解决这种恐慌,因为我在 Go 方面确实是个新手,尤其是在指针方面,所以请耐心等待。我跟踪了恐慌消息,发现恐慌已经发生了Create()在我的存储库包中的 gorm 中。

这是我的数据库连接

var (
    Instance *gorm.DB
)

func Connect() {
    if err := godotenv.Load(); err != nil {
        panic(err.Error())
    }

    dbUser := os.Getenv("DB_USERNAME")
    dbPass := os.Getenv("DB_PASSWORD")
    dbHost := os.Getenv("DB_HOST")
    dbName := os.Getenv("DB_NAME")

    dsn := fmt.Sprintf("%s:%s@tcp(%s:3303)/%s?charset=utf8mb4&parseTime=True&loc=Local", dbUser, dbPass, dbHost, dbName)
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
        Logger: logger.Default.LogMode(logger.Info),
    })

    if err != nil {
        panic("Error connecting database : " + err.Error())
    }

    Instance = db
}

func CloseDB() {
    conn, err := Instance.DB()
    if err != nil {
        panic("Error closing database : " + err.Error())
    }

    conn.Close()
}
Run Code Online (Sandbox Code Playgroud)

我的身份验证存储库

type AuthRepository interface {
    Create(user *entity.User) *entity.User
}

type authConnection struct {
    db *gorm.DB
}

func NewAuthRepository(db *gorm.DB) AuthRepository {
    return &authConnection{db}
}

func (c *authConnection) Create(user *entity.User) *entity.User {
    newPassword, err := hashPassword(user)
    if err != nil {
        return nil
    }

    user.Password = newPassword
    result := c.db.Create(user)
    if result == nil {
        return nil
    }

    return user

}
Run Code Online (Sandbox Code Playgroud)

我的身份验证服务使用身份验证存储库

var authRepository = repository.NewAuthRepository(database.Instance)

type AuthService struct {
    Repository repository.AuthRepository
}

func (s *AuthService) Register(user *entity.User) (*entity.User, error) {
    newUser := s.Repository.Create(user)
    if newUser == nil {
        return nil, errors.New("failed registering user")
    }

    return newUser, nil
}

func NewAuthService() *AuthService {
    return &AuthService{
        Repository: authRepository,
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一个,我的身份验证控制器


var (
    authService = service.NewAuthService()
)

func RegisterUser(c *gin.Context) {
    var user entity.User

    if err := c.ShouldBindJSON(&user); err != nil {
        handler.BuildErrorResponse(c, err)
        return
    }

    record, err := authService.Register(&user)
    if err != nil {
        handler.BuildErrorResponse(c, err)
        return
    }

    handler.BuildCreatedResponse(c, record)
}
Run Code Online (Sandbox Code Playgroud)

然后就报错了

runtime error: invalid memory address or nil pointer dereference
/usr/lib/golang/src/runtime/panic.go:212 (0x435eda)
        panicmem: panic(memoryError)
/usr/lib/golang/src/runtime/signal_unix.go:734 (0x44e892)
        sigpanic: panicmem()
/home/thoriqadillah/Development/Golang/pkg/mod/gorm.io/gorm@v1.23.6/finisher_api.go:18 (0x5d9226)
        (*DB).Create: if db.CreateBatchSize > 0 {
/home/thoriqadillah/Development/Golang/src/jwt/repository/auth_repository.go:28 (0xa19d04)
        (*authConnection).Create: result := c.db.Create(user)
/home/thoriqadillah/Development/Golang/src/jwt/service/auth_service.go:18 (0xa19ee1)
        (*AuthService).Register: newUser := s.Repository.Create(user)
/home/thoriqadillah/Development/Golang/src/jwt/controller/auth_controller.go:22 (0xa1a0ae)
        RegisterUser: record, err := authService.Register(&user)
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x9d9e39)
        (*Context).Next: c.handlers[c.index](c)
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/recovery.go:101 (0x9d9e20)
        CustomRecoveryWithWriter.func1: c.Next()
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x9d9013)
        (*Context).Next: c.handlers[c.index](c)
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/logger.go:240 (0x9d8fd2)
        LoggerWithConfig.func1: c.Next()
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x9cedcf)
        (*Context).Next: c.handlers[c.index](c)
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:616 (0x9cedb5)
        (*Engine).handleHTTPRequest: c.Next()
/home/thoriqadillah/Development/Golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:572 (0x9ce879)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/lib/golang/src/net/http/server.go:2868 (0x7d7582)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/lib/golang/src/net/http/server.go:1933 (0x7d29ac)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/lib/golang/src/runtime/asm_amd64.s:1371 (0x46df60)
        goexit: BYTE    $0x90   // NOP
Run Code Online (Sandbox Code Playgroud)

我假设错误来自 gorm Create()。我尝试通过使用、、和给出的内存地址打印user函数内 auth 存储库中的参数来调试它。但即使我改变了它仍然不起作用。我尝试直接在控制器中使用 gorm 并且它有效,但我想学习使我的代码有点模块化fmt.Println(user)fmt.Println(&user)fmt.Println(*user)fmt.Println(&user)Create(user)Create(&user)database.Instance.Create(&user)

Ole*_*nko 5

实际上,您在字符串中遇到了错误:

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Run Code Online (Sandbox Code Playgroud)

由于运算符:=
GO 创建了一个新的局部变量db并使用它而不是全局变量。
要解决此问题,只需将此行更改为:

var err error
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Run Code Online (Sandbox Code Playgroud)

或者,就您而言,对于这个:

var err error
Instance, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Run Code Online (Sandbox Code Playgroud)