当前位置: 首页 > 面试题库 >

为什么gorm db.First()会因“无效的内存地址或取消引用nil指针”而出现紧急情况?

鲁霄
2023-03-14
问题内容

我无法弄清楚我是否做了一些愚蠢的事情,或者是否发现了gorm中的错误。尽管我很清楚“无效的内存地址或nil指针取消引用”的含义,但是我完全不知道为什么它出现在这里。

简而言之,我打电话给db.First()我,没有明显原因,我感到恐慌。

我的代码的相关位:

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/jinzhu/gorm"
    "net/http"
    "os"
)

type message struct {
    gorm.Model
    Title string
    Body  string `sql:"size:0"` // blob
}

var db = gorm.DB{} // garbage

func messageHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    m := message{}
    query := db.First(&m, vars["id"])
    if query.Error != nil {
        if query.Error == gorm.RecordNotFound {
            notFoundHandler(w, r)
            return
        } else {
            fmt.Fprintf(os.Stderr, "database query failed: %v", query.Error)
            internalServerErrorHandler(w, r)
            return
        }
    }

    // actually do something useful
}

func main() {
    db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
    // ...
}

db``main()在包中打开,并存储为包变量。这似乎不太干净,但似乎可以正常工作…

恐慌:

2015/07/16 20:56:12 http: panic serving [::1]:37326: runtime error: invalid memory address or nil pointer dereference
goroutine 26 [running]:
net/http.func·011()
        /usr/lib/golang/src/net/http/server.go:1130 +0xbb
github.com/jinzhu/gorm.(*DB).First(0xd28720, 0x79f220, 0xc2080b2600, 0xc2080ef220, 0x1, 0x1, 0xd)
        /home/error/go/src/github.com/jinzhu/gorm/main.go:200 +0x154
main.messageHandler(0x7f4f2e785bd8, 0xc208051c20, 0xc208035790)
        /home/error/go/src/myproject/messages.go:28 +0x2c1
net/http.HandlerFunc.ServeHTTP(0x9c3948, 0x7f4f2e785bd8, 0xc208051c20, 0xc208035790)
        /usr/lib/golang/src/net/http/server.go:1265 +0x41
github.com/gorilla/mux.(*Router).ServeHTTP(0xc2080d9630, 0x7f4f2e785bd8, 0xc208051c20, 0xc208035790)
        /home/error/go/src/github.com/gorilla/mux/mux.go:98 +0x297
net/http.serverHandler.ServeHTTP(0xc2080890e0, 0x7f4f2e785bd8, 0xc208051c20, 0xc208035790)
        /usr/lib/golang/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc208051b80)
        /usr/lib/golang/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
        /usr/lib/golang/src/net/http/server.go:1751 +0x35e

…我的代码的第28行在哪里 query := db.First(&m, vars["id"])

我检查了gorm和First()函数中的注释行,但这并不是很明显。

    return newScope.Set("gorm:order_by_primary_key", "ASC").
        inlineCondition(where...).callCallbacks(s.parent.callback.queries).db

为了弄清楚到底发生了什么,我对代码进行了以下更改:

第一次尝试:是否抱怨传递字符串?让我们给它一个整数。毕竟,该示例使用整数。

    id, _ := strconv.Atoi(vars["id"])
    query := db.First(&m, id)

在完全相同的地方再次出现恐慌。

第二次尝试:我是否m以错误的方式创建了变量?也许确实需要首先分配它new

    m := new(message)
    query := db.First(m, vars["id"])

在完全相同的地方再次出现恐慌。

第三次尝试:我只是将要查找的ID硬编码,以防万一大猩猩/多路复用器行为异常。

    m := message{}
    query := db.First(&m, 3)

在完全相同的地方再次出现恐慌。

最后,我用一个空的数据库表进行了测试,其中一个填充的表要求一个存在的ID,而一个填充的表要求一个不存在的ID。在这三种情况下,我都会感到同样的恐慌。

最有趣的部分是,显然net / http正在恢复恐慌,然后notFoundHandler()运行并在浏览器中看到其模板输出。

我目前正在使用mattn / go-sqlite3驱动程序。

我的环境是Fedora RPM软件包中提供的带有cgo 1.4.2的Fedora 22 x86_64。

$ go version
go version go1.4.2 linux/amd64

$ go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/error/go"
GORACE=""
GOROOT="/usr/lib/golang"
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

这是怎么回事?恐慌是从哪里来的?我如何解决它?


问题答案:

您正在隐藏全局db变量:

var db = gorm.DB{} // garbage

您的初始化main()应更改为:

var err error
// Note the assignment and not initialise + assign operator
db, err = gorm.Open("sqlite3", "/tmp/gorm.db")

否则,dbnil导致恐慌。



 类似资料:
  • 问题内容: 当运行我的Go程序时,它会慌张并返回以下内容: 我查看了其他人对相同异常的响应,但看不到任何简单的响应(即未处理的错误)。 我在无法访问代码中列出的API服务器的机器上运行它,但我希望它会返回适当的错误(因为我试图捕获这种错误)。 问题答案: 根据文档: “如果是由客户端策略(例如CheckRedirect)引起的,或者存在HTTP协议错误,则会返回错误。非2xx响应不会导致错误。 当

  • 我是gccgo新手,我需要编译/运行以下代码的帮助(这在“标准”go编译器中可以正常工作(抱歉,我不知道正确的名称)): 我的gcc: 我的第一个文件: 我的第二个文件: 我的编译错误: 我做错了什么?

  • 问题内容: 我是新手,尝试制作一个简单的网络爬虫。我不断收到“紧急情况:运行时错误:无效的内存地址或nil指针取消引用”,并且不知道如何解决该问题。我有一个“ advancedFetcher”功能和一个“basicFetcher”功能,在任何一个下都出现相同的错误。这个答案建议检查每个错误(我认为是错误),但仍然出现错误。谢谢! 编辑#1: 问题答案: 您的程序在惊慌之前打印错误吗?如果没有记错,

  • 我收到一个无效内存地址的运行时错误。 channel.go看起来像这样: 第36行怎么可能导致这种情况?m是否有可能为零?如果是,如何? 注意:哈希定义为字符串

  • 我正在尝试使用带有自定义分隔符的Go html/模板。 但是,我可以解析并执行我的“index.html”文件,每当我试图更改模板分隔符时,我都会遇到以下错误: 这是我的代码: 如果我尝试以下任何一种: 或: 一切正常。我甚至试图捕捉ParseFiles错误。但仍然没有运气: 我看不出我做错了什么。如果你们中的任何人能在这个问题上帮助我,我将不胜感激。 更新1: 这就是恐慌:

  • 调用原子。结构字段上的AddInt64会恐慌,但当我们重新排列字段顺序时不会;为什么? 使用此类型: 并调用