运行时错误:无效的内存地址或nil指针取消引用,再次[重复]

This question already has an answer here:

I am trying to use the mysqlstore backend package for gorilla sessions in a Golang web application. I am following this example and my code is identical. The code builds and runs fine but when I go to localhost:8080/ in my browser I am getting this error

runtime error: invalid memory address or nil pointer dereference

Here is my code:

package main

  import (
    "fmt"
    "github.com/srinathgs/mysqlstore"
    "net/http"
  )

  var store *mysqlstore.MySQLStore

  func sessTest(w http.ResponseWriter, r *http.Request) {
    session, err := store.Get(r, "foobar")
    session.Values["bar"] = "baz"
    session.Values["baz"] = "foo"
    err = session.Save(r, w)
    fmt.Printf("%#v
", session)
    fmt.Println(err)
  }

func main() {

    store, err := mysqlstore.NewMySQLStore("root:mypass@tcp(127.0.0.1:3306)/mydb?parseTime=true&loc=Local", "sessions", "/", 3600, []byte("<SecretKey>"))
    if err != nil {
      panic(err)
    }
    defer store.Close()

        http.HandleFunc("/", sessTest)
        http.ListenAndServe(":8080", nil)
}

Here is the full error message:

2019/02/12 02:46:43 http: panic serving [::1]:63119: runtime error: invalid memory address or nil pointer dereference goroutine 34 /usr/local/Cellar/go/1.11.5/libexec/src/net/http/server.go:1746 +0xd0 panic(0x12c9f40, 0x1560950) /usr/local/Cellar/go/1.11.5/libexec/src/runtime/panic.go:513 +0x1b9 github.com/srinathgs/mysqlstore.(*MySQLStore).New(0x0, 0xc000138000, 0x1324045, 0x6, 0x158afa0, 0xc00010a000, 0xb) /Users/Mark/go/src/github.com/srinathgs/mysqlstore/mysqlstore.go:137 +0xef github.com/gorilla/sessions.(*Registry).Get(0xc00011e0e0, 0x1376e20, 0x0, 0x1324045, 0x6, 0xc00010c100, 0x0, 0x1) /Users/Mark/go/src/github.com/gorilla/sessions/sessions.go:139 +0x142 github.com/srinathgs/mysqlstore.(*MySQLStore).Get(0x0, 0xc000138000, 0x1324045, 0x6, 0x1086222, 0xc00010a044, 0xc00010a050) /Users/Mark/go/src/github.com/srinathgs/mysqlstore/mysqlstore.go:131 +0x63 main.sessTest(0x13770a0, 0xc00013c000, 0xc000138000) /Users/Mark/go/src/testsessions/main.go:12 +0x61 net/http.HandlerFunc.ServeHTTP(0x133a680, 0x13770a0, 0xc00013c000, 0xc000138000)

<…>

</div>

the store that you are creating in your main func is not being assigned to the global store. The global store being used in your handler is still nil. This is because of how the := operator works, and the fact that you are trying to assign to a var declared elsewhere.

You could either

  1. assign to the global store correctly by not using the := and declaring var err error above that line e.g.
var err error
store, err = mysqlstore.NewMySQLStore(...
  1. Or the way that i recommend (without global vars) is to: initialize store in main as you have done, and also initialize your handler by wrapping the handler function in a closure and passing the store into that

e.g.

package main

import (
    "fmt"
    "github.com/srinathgs/mysqlstore"
    "net/http"
)

// note: this returns a http.HandlerFunc, which works because
// http.HandlerFunc is just a named type for a function which accepts http.ResponseWriter and *http.Request as args
// see the docs at https://golang.org/pkg/net/http/#HandlerFunc
// (but yea at the end of the day, this is a function which returns another function)
func makeSessTest(store *mysqlstore.MySQLStore) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        session, err := store.Get(r, "foobar")
        session.Values["bar"] = "baz"
        session.Values["baz"] = "foo"
        err = session.Save(r, w)
        fmt.Printf("%#v
", session)
        fmt.Println(err)
    }
}

func main() {
    store, err := mysqlstore.NewMySQLStore("root:mypass@tcp(127.0.0.1:3306)/mydb?parseTime=true&loc=Local", "sessions", "/", 3600, []byte("<SecretKey>"))
    if err != nil {
        panic(err)
    }
    defer store.Close()

    http.HandleFunc("/", makeSessTest(store))
    http.ListenAndServe(":8080", nil)
}