无效的内存地址或Golang中的nil指针取消引用

I'm new to go lang, I loved it so far but I came across this problem when ever I run the application :

invalid memory address or nil pointer dereference

What should I do to fix the problem?

Here is the main file syntax.go:

package main

    import (
        "blog/models"
        "fmt"
        "net/http"
    )

    func main() {
       models.DbConn()

       http.HandleFunc("/books", postsIndex)
       http.ListenAndServe(":3000", nil)

    }
    func postsIndex(w http.ResponseWriter, r *http.Request) {
        if r.Method != "GET" {
            http.Error(w, http.StatusText(405), 405)
            return
        }
        bks, err := models.AllPosts()
        if err != nil {
            http.Error(w, http.StatusText(500), 500)
            return
        }
        for _, bk := range bks {
            fmt.Fprintf(w, "%s, %s", bk.Title, bk.Description)
        }
    }

and this the database connection db.go:

package models

import (
    "fmt"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "log"
)
var db *sql.DB
func DbConn() {
    db, err := sql.Open("mysql","root:@/posts")

    if err != nil {
        log.Fatal(err)
    }else {
        fmt.Printf("this is working")
    }
    defer db.Close()
}

and this the file to get the posts posts.go:

package models

type Post struct {

    Title  string
    Description string

}

func AllPosts() ([]*Post, error) {
    rows, err := db.Query("SELECT * FROM posts")
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    bks := make([]*Post, 0)
    for rows.Next() {
        bk := new(Post)
        err := rows.Scan(&bk.Title, &bk.Description )
        if err != nil {
            return nil, err
        }
        bks = append(bks, bk)
    }
    if err = rows.Err(); err != nil {
        return nil, err
    }
    return bks, nil
}

If you look at the console where the error is shown, I guess it'll show something like posts.go:9. On that line, you're trying to execute a database query but at that point in time, the connection to the database has already been closed.

In your db.go you have the line

db, err := sql.Open("mysql","root:@/posts")

That line creates two variables for the scope of the function and assigns the values to it. By the time the function finishes, there is nothing left that uses the scoped variable db so the connection is closed. Because you've used the := new variables have been created and you haven't assigned it to the var db *sql.DB.

As a quick fix, you can change the first part of the DbConn method to

var err error
db, err = sql.Open("mysql", "root@/posts")

I've added a line for a new variable of type error and the assign now assigns the values to existing variables as opposed to creating new ones (= vs :=)