吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2488|回复: 4
收起左侧

[已解决] 【gin+gorm】向表中添加数据时报invalid memory address or nil pointer dereference

[复制链接]
thepoy 发表于 2020-7-18 22:34
本帖最后由 thepoy 于 2020-7-19 10:07 编辑

model

type User struct {
        gorm.Model
        Username      string     `json:"username" form:"username" binding:"required" gorm:"type:varchar(20);not null;unique"`
        Password      string     `json:"password" form:"password" binding:"required" gorm:"not null"`
        Email         string     `json:"email" form:"email" binding:"required" gorm:"type:varchar(60);not null;unique"`
        Phone         string     `json:"phone" form:"phone" binding:"required" gorm:"type:varchar(20);not null;unique"`
        RegisterIP    string     `json:"register_ip" gorm:"type:varchar(15);not null"`
        LastLoginTime *time.Time `json:"last_login_time"`
        LastLoginIP   string     `json:"last_login_ip" gorm:"type:varchar(15)"`
        Blogs         []Blog
}

db

var db *gorm.DB

func init() {
        db, err := gorm.Open("mysql", "go:000aaa@tcp(127.0.0.1:3306)/blog")
        if err != nil {
                panic("Connecting database failed:" + err.Error())
        }
        db.DB().SetMaxOpenConns(100)
        db.DB().SetMaxIdleConns(20)
        db.AutoMigrate(&models.Blog{}, &models.User{}, &models.BlogType{})
        db.Model(&models.Blog{}).AddUniqueIndex("title", "user_id", "blog_type_id")
}
func GetDB() *gorm.DB {
        return db
}

handler

func Regsiter(c *gin.Context) {
        var form models.User
        if err := c.ShouldBindWith(&form, binding.Form); err != nil {
                c.JSON(http.StatusBadRequest, gin.H{
                        "error": err.Error(),
                })
                return
        }
        db := utils.GetDB()

        // 定义一个user实例
        user := models.User{
                Username:   form.Username,
                Password:   form.Password,
                Email:      form.Email,
                Phone:      form.Phone,
                RegisterIP: c.Request.RemoteAddr,
        }
        user.CreatedAt = time.Now()

        fmt.Printf("%p", &user)

        db.Create(&user)   // 此行报错,但&user应该是能查到的有效指针才对,是user定义时出问题了吗?

        c.JSON(http.StatusCreated, gin.H{
                "msg":      "register successful",
                "username": form.Username,
        })
}

运行后访问register,填好required的数据,报空指针或无效指针:

2020/07/18 22:08:12 [Recovery] 2020/07/18 - 22:08:12 panic recovered:
POST /register HTTP/1.1
Host: localhost:8080
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 434
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFnAqpmWULl4CibNl
Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Postman-Token: d06a2054-81f0-0c9c-7ba7-03ab09a993b2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: none
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36

runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:212 (0x44aa19)
        panicmem: panic(memoryError)
/usr/local/go/src/runtime/signal_unix.go:695 (0x44a868)
        sigpanic: panicmem()
/home/thepoy/go/pkg/mod/github.com/jinzhu/gorm@v1.9.14/main.go:848 (0x57ccd6)
        (*DB).clone: dialect:           newDialect(s.dialect.GetName(), s.db),
/home/thepoy/go/pkg/mod/github.com/jinzhu/gorm@v1.9.14/main.go:204 (0x575d8e)
        (*DB).NewScope: dbClone := s.clone()
/home/thepoy/go/pkg/mod/github.com/jinzhu/gorm@v1.9.14/main.go:482 (0x579ed2)
        (*DB).Create: scope := s.NewScope(value)
/media/thepoy/软件/OneDrive - WULEL/code/go/src/go_blog_api/api/user.go:34 (0x9794c3)
        Regsiter: db.Create(&user)
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/context.go:161 (0x96449a)
        (*Context).Next: c.handlers[c.index](c)
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/recovery.go:83 (0x977b9f)
        RecoveryWithWriter.func1: c.Next()
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/context.go:161 (0x96449a)
        (*Context).Next: c.handlers[c.index](c)
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/logger.go:241 (0x976cd0)
        LoggerWithConfig.func1: c.Next()
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/context.go:161 (0x96449a)
        (*Context).Next: c.handlers[c.index](c)
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/gin.go:409 (0x96e275)
        (*Engine).handleHTTPRequest: c.Next()
/home/thepoy/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/gin.go:367 (0x96d98c)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2836 (0x78b082)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1924 (0x7869eb)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1373 (0x464270)
        goexit: BYTE        $0x90        // NOP

添加数据的代码,在单独测试时能够正常添加,放到gin里就报这个错。
请问是哪里的问题呢?

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

540558233 发表于 2020-7-19 00:21
你的db实例有问题吧  ,db, err := gorm.Open("mysql", "go:000aaa@tcp(127.0.0.1:3306)/blog")这一行的 := 赋值的变量db是局部变量,不能赋值给上面的全局变量,用 = 号直接赋值试试

免费评分

参与人数 1吾爱币 +1 收起 理由
thepoy + 1 又一次成功地入了:=的坑

查看全部评分

lm93129 发表于 2020-7-19 01:45


初始化数据库这块应该这样写,定一个全局可用的DB指针,初始化db之后赋值给这个全局可用的DB
[Golang] 纯文本查看 复制代码
var DB *gorm.DB

// Database 在中间件中初始化mysql链接
func Database() {

	db, err := gorm.Open("mysql", "go:000aaa@tcp(127.0.0.1:3306)/blog")

	if err != nil {
		util.Log().Panic("连接数据库不成功", err)
	}

	if gin.Mode() == gin.ReleaseMode {
		db.LogMode(false)
	} else {
		db.LogMode(true)
	}

	db.SingularTable(true)
	//设置连接池
	//空闲
	db.DB().SetMaxIdleConns(50)
	//打开
	db.DB().SetMaxOpenConns(100)
	//超时
	db.DB().SetConnMaxLifetime(time.Second * 30)

	DB = db

	// 同步数据
	migration()
}


使用的时候,使用这个全局可以用的DB就可以了,使用的示例如下:
[Golang] 纯文本查看 复制代码
func  Show(id string) {
	var statistic model.AppManage
	// 这个model.DB 就是初始化的那个全局变量DB
	err := model.DB.Model(&statistic).
	Select("project_id ,COUNT(*)").
	Group("project_id").Where("created_at BETWEEN ? AND ?", server.StarTime, server.EndTime).
	Scan(&results).Error

	if err != nil {
		return serializer.DBErr("", err)
	}
}
myxy999 发表于 2020-7-19 07:39
lm93129 发表于 2020-7-19 01:45
初始化数据库这块应该这样写,定一个全局可用的DB指针,初始化db之后赋值给这个全局可用的DB[mw_shl_co ...

他写了一个专门获取db的方法,所以不是这个问题
myxy999 发表于 2020-7-19 08:07
我测试了下没啥问题啊
[Golang] 纯文本查看 复制代码
func GetDB() *gorm.DB {
        db, err := gorm.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/blog")
        if err != nil {
                panic("Connecting database failed:" + err.Error())
        }
        db.DB().SetMaxOpenConns(100)
        db.DB().SetMaxIdleConns(20)
        db.AutoMigrate(&User{})
        return db
}

type User struct {
        gorm.Model
        Username      string     `json:"username" form:"username" binding:"required" gorm:"type:varchar(20);not null;unique"`
        Password      string     `json:"password" form:"password" binding:"required" gorm:"not null"`
        Email         string     `json:"email" form:"email" binding:"required" gorm:"type:varchar(60);not null;unique"`
        Phone         string     `json:"phone" form:"phone" binding:"required" gorm:"type:varchar(20);not null;unique"`
        RegisterIP    string     `json:"register_ip" gorm:"type:varchar(15);not null"`
        LastLoginTime *time.Time `json:"last_login_time"`
        LastLoginIP   string     `json:"last_login_ip" gorm:"type:varchar(15)"`
}

func TestRegsiter(t *testing.T) {
        app := gin.Default()
        db := GetDB()
        app.POST("/regsiter", func(c *gin.Context) {
                var form User
                if err := c.ShouldBindWith(&form, binding.Form); err != nil {
                        c.JSON(http.StatusBadRequest, gin.H{
                                "error": err.Error(),
                        })
                        return
                }
                // 定义一个user实例
                user := User{
                        Username:   form.Username,
                        Password:   form.Password,
                        Email:      form.Email,
                        Phone:      form.Phone,
                        RegisterIP: c.Request.RemoteAddr,
                }
                user.CreatedAt = time.Now()

                fmt.Printf("%p", &user)

                db.Create(&user) // 此行报错,但&user应该是能查到的有效指针才对,是user定义时出问题了吗?

                c.JSON(http.StatusCreated, gin.H{
                        "msg":      "register successful",
                        "username": form.Username,
                })
        })
        _ = app.Run(":8888")
}


QQ截图20200719080715.png

免费评分

参与人数 1热心值 +1 收起 理由
thepoy + 1 是db的init函数中定义db时又用了:=导致全局变量db是空指针,不是handler代.

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 14:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表