何かばかげたことをしたのか、それとも 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とfunctionの指摘された行を確認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)
まったく同じ場所で、再びパニックに陥ります。
2 回目の試行: 変数m
を間違った方法で作成しましたか? new
たぶん、最初に割り当てる必要があります。
m := new(message)
query := db.First(m, vars["id"])
まったく同じ場所で、再びパニックに陥ります。
3 回目の試行: ゴリラ/マルチプレクサが誤動作した場合に備えて、検索する ID をハードコードしただけです。
m := message{}
query := db.First(&m, 3)
まったく同じ場所で、再びパニックに陥ります。
最後に、空のデータベース テーブル、データが入力されたテーブルが存在する ID を要求するテスト、データが入力されたテーブルが存在しない ID を要求するテストを行いました。3 つのケースすべてで、同じパニックが発生します。
すべての中で最も興味深い部分は、どうやら 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"
どうしたの?このパニックはどこから来るのですか?どうすれば修正できますか?