DefaultServeMux中的SQL给出错误

I am trying to do a REST API in Go. The query works when placed within the main handler (shows in terminal), but gives error in the browser when moved to the desired handler.

localhost:8080/ <------ Browser gives an error (not showing anything) and the terminal shows several error messages - one of them is:

http: panic serving [::1]:51100: runtime error: invalid memory address or nil pointer dereference

localhost:8080/getuser <---gives correct response

Getuser

package main

import (
    "fmt"
    "log"
    "net/http"
    "database/sql"
    _ "github.com/lib/pq"
)

const (
    host     = "127.0.0.1"
    port     = 5432
    user     = "test"
    password = "pw"
    dbname   = "Test"
)

var db *sql.DB

type User struct {
    USER_ID   string
    USER_NAME  string
}

func handleRequests() {
    http.HandleFunc("/", index)
    http.HandleFunc("/getuser", Getuser)
}

func index(w http.ResponseWriter, r *http.Request){
    rows, err := db.Query(`SELECT "USER_ID","USER_NAME" FROM users`)
    if err != nil {
        http.Error(w, http.StatusText(500), 500)
        return
    }
    defer rows.Close()

    for rows.Next() {
        user := User{}
        err := rows.Scan(&user.USER_ID, &user.USER_NAME) 
        if err != nil {
            http.Error(w, http.StatusText(500), 500)
    }
        fmt.Fprintf(w, "%s, %s
", user.USER_ID, user.USER_NAME)
    }

}

func Getuser(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Getuser")   // <-------------------------this works!
}

func main() {
    handleRequests()

    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
        "password=%s dbname=%s sslmode=require",
        host, port, user, password, dbname)

    db, err := sql.Open("postgres", psqlInfo)
    if err != nil {
        log.Fatalln(err)
    }

    if err != nil {
        panic(err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        panic(err)
    }

    log.Fatal(http.ListenAndServe(":8080", nil))
  }

EDIT

The complete error list in terminal

created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b 2018/03/23 08:36:39 http: panic serving [::1]:51390: runtime error: invalid memory address or nil pointer dereference goroutine 36 [running]: net/http.(*conn).serve.func1(0xc4201d80a0) /usr/local/go/src/net/http/server.go:1726 +0xd0 panic(0x1294460, 0x1471840) /usr/local/go/src/runtime/panic.go:505 +0x229 database/sql.(*DB).conn(0x0, 0x13277e0, 0xc42009e020, 0xc420028f01, 0xc4200a0218, 0xc4200a0220, 0xc4201e8b01) /usr/local/go/src/database/sql/sql.go:1015 +0x3a database/sql.(*DB).query(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x12ec601, 0x8, ...) /usr/local/go/src/database/sql/sql.go:1437 +0x66

database/sql.(*DB).QueryContext(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x10825ed, 0xc4201d0180, ...) /usr/local/go/src/database/sql/sql.go:1419 +0xd2 database/sql.(*DB).Query(0x0, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0xc4201ec070, 0x8000000000000000, 0x0) /usr/local/go/src/database/sql/sql.go:1433 +0x82 main.Getsign(0x13275a0, 0xc4202020e0, 0xc4201f4100) /Users/sibert/go/src/main/api.go:55 +0x65 net/http.HandlerFunc.ServeHTTP(0x1302020, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:1947 +0x44 net/http.(*ServeMux).ServeHTTP(0x147cc00, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:2337 +0x130 net/http.serverHandler.ServeHTTP(0xc42009b2b0, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:2694 +0xbc net/http.(*conn).serve(0xc4201d80a0, 0x13277a0, 0xc4201b4280) /usr/local/go/src/net/http/server.go:1830 +0x651 created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b 2018/03/23 08:36:39 http: panic serving [::1]:51391: runtime error: invalid memory address or nil pointer dereference goroutine 24 [running]: net/http.(*conn).serve.func1(0xc4200b4b40) /usr/local/go/src/net/http/server.go:1726 +0xd0 panic(0x1294460, 0x1471840) /usr/local/go/src/runtime/panic.go:505 +0x229 database/sql.(*DB).conn(0x0, 0x13277e0, 0xc42009e020, 0xc420024501, 0xc4200a0318, 0xc4200a0320, 0xc420052b01) /usr/local/go/src/database/sql/sql.go:1015 +0x3a database/sql.(*DB).query(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x12ec601, 0x8, ...) /usr/local/go/src/database/sql/sql.go:1437 +0x66 database/sql.(*DB).QueryContext(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x10825ed, 0xc420140480, ...) /usr/local/go/src/database/sql/sql.go:1419 +0xd2 database/sql.(*DB).Query(0x0, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0xc42009eb10, 0x8000000000000000, 0x0) /usr/local/go/src/database/sql/sql.go:1433 +0x82 main.Getsign(0x13275a0, 0xc42019e0e0, 0xc42019a300) /Users/sibert/go/src/main/api.go:55 +0x65 net/http.HandlerFunc.ServeHTTP(0x1302020, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:1947 +0x44 net/http.(*ServeMux).ServeHTTP(0x147cc00, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:2337 +0x130 net/http.serverHandler.ServeHTTP(0xc42009b2b0, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:2694 +0xbc net/http.(*conn).serve(0xc4200b4b40, 0x13277a0, 0xc4200a0780) /usr/local/go/src/net/http/server.go:1830 +0x651 created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b

What you are encountering is the classic case of variable shadowing.

The := creates a new db variable that shadows your package level db variable. The set value of db only exists within the scope of your main function while your package level db variable remains as a nil pointer, thus when you attempt to perform a method call on nil, in your index handler, you get a panic.

The reason your Getuser handler works has nothing to do with the DefaultServeMux it's simply because you aren't attempting to access a member function on a nil value.

The way to fix this is within your main function to predeclare the err variable and change the := to simple assignment =

func main() {
// ...
    var err error
    // this will now correctly set your package level variable
    db, err = sql.Open("postgres", psqlInfo)
    if err != nil {
        log.Fatalln(err)
    }
// ...
}