我正在使用 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
}
我正在關注官方檔案。奇怪的是第一次(在服務器啟動后)它成功更新了用戶,下一次沒有。
編輯:添加了錯誤轉儲:
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 $0x90 // 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
}
我究竟做錯了什么?
uj5u.com熱心網友回復:
該函式UpdateUser在回傳時關閉資料庫。這是個大問題!UpdateUser由于函式呼叫已關閉資料庫上的方法,因此隨后呼叫panic。
洗掉這行代碼以解決問題。
defer service.db.Close()
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/424127.html
