Service fails randomly: "runtime error: invalid memory address or nil pointer dereference"
Service fails randomly: "runtime error: invalid memory address or nil pointer dereference"
我正在 Restful API 服务器上工作,我不得不从 MongoDB 迁移到 MySQL。团队选择的 ORM 是 upper/db。我的问题是我的服务有时会失败,有时不会。
错误本身:runtime error: invalid memory address or nil pointer dereference
这是有时会给我错误的服务函数:
func (service *UserService) UpdateUser(req UpdateUserRequest) (response UpdateUserResponse, err error) {
var user models.User
defer service.db.Close()
collection := service.db.Collection("users")
result := collection.Find(req.ID)
err = result.One(&user) // this is line 104
if err != nil {
return
}
count, err := result.Count()
if err != nil {
return
}
if count == 0 {
err = errors.New("couldn't find user")
return
}
if req.FirstName != "" && req.FirstName != user.FirstName {
user.FirstName = req.FirstName
}
if req.LastName != "" && req.LastName != user.LastName {
user.LastName = req.LastName
}
if req.UserType != "" && req.UserType != user.UserType {
user.UserType = req.UserType
}
if req.Status != "" && req.Status != user.Status {
user.Status = req.Status
}
user.UpdatedAt = time.Now()
if err = result.Update(user); err != nil {
return
}
user.Password = ""
response.User = user
return
}
我正在关注official documentation。奇怪的是第一次(服务器启动后)它成功更新了用户,下一次就没有了。
编辑:添加了错误转储:
runtime error: invalid memory address or nil pointer dereference
C:/Program Files/Go/src/runtime/panic.go:221 (0xfe993c)
panicmem: panic(memoryError)
C:/Program Files/Go/src/runtime/signal_windows.go:254 (0xfe990c)
sigpanic: panicmem()
C:/Program Files/Go/src/database/sql/sql.go:1260 (0x14452d3)
(*DB).conn: db.mu.Lock()
C:/Program Files/Go/src/database/sql/sql.go:1695 (0x144831c)
(*DB).query: dc, err := db.conn(ctx, strategy)
C:/Program Files/Go/src/database/sql/sql.go:1674 (0x144807e)
(*DB).QueryContext: rows, err = db.query(ctx, query, args, cachedOrNewConn)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/compat/query_go18.go:39 (0x1486730)
QueryContext: return p.QueryContext(ctx, query, args...)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/session.go:823 (0x14866eb)
(*session).StatementQuery: rows, err = compat.QueryContext(sess.sqlDB, ctx, query, args)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/select.go:480 (0x147304f)
(*selector).IteratorContext: rows, err := sess.StatementQuery(ctx, sq.statement(), sq.arguments()...)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/select.go:470 (0x1472d9a)
(*selector).Iterator: return sel.IteratorContext(sel.SQL().sess.Context())
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/paginate.go:176 (0x146d932)
(*paginator).Iterator: return pq.sel.Iterator()
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/result.go:243 (0x14809b5)
(*Result).One: err = query.Iterator().One(dst)
C:/Users/user/go/src/github.com/myrepo/service/services/user_service.go:104 (0x15135be)
(*UserService).UpdateUser: err = result.One(&user)
C:/Users/user/go/src/github.com/myrepo/service/handlers/users_handler.go:39 (0x1518e3c)
handleUpdateUser.func1: user, err := service.UpdateUser(req)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1515ff6)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/tpkeeper/gin-dump@v1.0.1/gindump.go:98 (0x15153b4)
DumpWithOptions.func1: ctx.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x14311a6)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/logger.go:241 (0x1431189)
LoggerWithConfig.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1431f41)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/recovery.go:99 (0x1431f2c)
CustomRecoveryWithWriter.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1430730)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:555 (0x1430398)
(*Engine).handleHTTPRequest: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:511 (0x142fed1)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2879 (0x120959a)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1930 (0x1204c47)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1581 (0x1004640)
goexit: BYTE [=11=]x90 // NOP
编辑 2:添加了数据库连接
func Open(settings db.ConnectionURL) (db.Session, error) {
db, err := mysql.Open(settings)
if err != nil {
return nil, err
}
if db.Ping() != nil {
return nil, errors.New("error al conectar la base de datos")
}
return db, nil
}
我做错了什么?
函数 UpdateUser
在 return 上关闭了数据库。那是个大问题!对 UpdateUser
的后续调用出现恐慌,因为该函数在已关闭的数据库上调用方法。
删除这行代码以解决问题。
defer service.db.Close()
我正在 Restful API 服务器上工作,我不得不从 MongoDB 迁移到 MySQL。团队选择的 ORM 是 upper/db。我的问题是我的服务有时会失败,有时不会。
错误本身:runtime error: invalid memory address or nil pointer dereference
这是有时会给我错误的服务函数:
func (service *UserService) UpdateUser(req UpdateUserRequest) (response UpdateUserResponse, err error) {
var user models.User
defer service.db.Close()
collection := service.db.Collection("users")
result := collection.Find(req.ID)
err = result.One(&user) // this is line 104
if err != nil {
return
}
count, err := result.Count()
if err != nil {
return
}
if count == 0 {
err = errors.New("couldn't find user")
return
}
if req.FirstName != "" && req.FirstName != user.FirstName {
user.FirstName = req.FirstName
}
if req.LastName != "" && req.LastName != user.LastName {
user.LastName = req.LastName
}
if req.UserType != "" && req.UserType != user.UserType {
user.UserType = req.UserType
}
if req.Status != "" && req.Status != user.Status {
user.Status = req.Status
}
user.UpdatedAt = time.Now()
if err = result.Update(user); err != nil {
return
}
user.Password = ""
response.User = user
return
}
我正在关注official documentation。奇怪的是第一次(服务器启动后)它成功更新了用户,下一次就没有了。
编辑:添加了错误转储:
runtime error: invalid memory address or nil pointer dereference
C:/Program Files/Go/src/runtime/panic.go:221 (0xfe993c)
panicmem: panic(memoryError)
C:/Program Files/Go/src/runtime/signal_windows.go:254 (0xfe990c)
sigpanic: panicmem()
C:/Program Files/Go/src/database/sql/sql.go:1260 (0x14452d3)
(*DB).conn: db.mu.Lock()
C:/Program Files/Go/src/database/sql/sql.go:1695 (0x144831c)
(*DB).query: dc, err := db.conn(ctx, strategy)
C:/Program Files/Go/src/database/sql/sql.go:1674 (0x144807e)
(*DB).QueryContext: rows, err = db.query(ctx, query, args, cachedOrNewConn)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/compat/query_go18.go:39 (0x1486730)
QueryContext: return p.QueryContext(ctx, query, args...)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/session.go:823 (0x14866eb)
(*session).StatementQuery: rows, err = compat.QueryContext(sess.sqlDB, ctx, query, args)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/select.go:480 (0x147304f)
(*selector).IteratorContext: rows, err := sess.StatementQuery(ctx, sq.statement(), sq.arguments()...)
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/select.go:470 (0x1472d9a)
(*selector).Iterator: return sel.IteratorContext(sel.SQL().sess.Context())
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqlbuilder/paginate.go:176 (0x146d932)
(*paginator).Iterator: return pq.sel.Iterator()
C:/Users/user/go/pkg/mod/github.com/upper/db/v4@v4.5.0/internal/sqladapter/result.go:243 (0x14809b5)
(*Result).One: err = query.Iterator().One(dst)
C:/Users/user/go/src/github.com/myrepo/service/services/user_service.go:104 (0x15135be)
(*UserService).UpdateUser: err = result.One(&user)
C:/Users/user/go/src/github.com/myrepo/service/handlers/users_handler.go:39 (0x1518e3c)
handleUpdateUser.func1: user, err := service.UpdateUser(req)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1515ff6)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/tpkeeper/gin-dump@v1.0.1/gindump.go:98 (0x15153b4)
DumpWithOptions.func1: ctx.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x14311a6)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/logger.go:241 (0x1431189)
LoggerWithConfig.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1431f41)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/recovery.go:99 (0x1431f2c)
CustomRecoveryWithWriter.func1: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1430730)
(*Context).Next: c.handlers[c.index](c)
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:555 (0x1430398)
(*Engine).handleHTTPRequest: c.Next()
C:/Users/user/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:511 (0x142fed1)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2879 (0x120959a)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1930 (0x1204c47)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1581 (0x1004640)
goexit: BYTE [=11=]x90 // NOP
编辑 2:添加了数据库连接
func Open(settings db.ConnectionURL) (db.Session, error) {
db, err := mysql.Open(settings)
if err != nil {
return nil, err
}
if db.Ping() != nil {
return nil, errors.New("error al conectar la base de datos")
}
return db, nil
}
我做错了什么?
函数 UpdateUser
在 return 上关闭了数据库。那是个大问题!对 UpdateUser
的后续调用出现恐慌,因为该函数在已关闭的数据库上调用方法。
删除这行代码以解决问题。
defer service.db.Close()