Home > front end >  Unable to connect to psql db
Unable to connect to psql db

Time:11-20

I am trying to connect to a database, but getting an error when I make a curl request to the endpoint with the GET method. I double-checked with the user credentials and have granted full privileges and superuser permissions. Following is the error I get when curl the endpoint:

santosh@pkg*$:curl -i localhost:8080/books/show
HTTP/1.1 303 See Other
Content-Type: text/html; charset=utf-8
Location: /books
Date: Sat, 19 Nov 2022 12:09:52 GMT
Content-Length: 33

<a href="/books">See Other</a>.

The connection is established with the Database, when the request is made to the database these errors are triggered:

santosh@pkg*$:go run main.go 
Database connection successful.
2022/11/19 17:39:47 http: panic serving 127.0.0.1:44324: runtime error: invalid memory address or nil pointer dereference
goroutine 35 [running]:
net/http.(*conn).serve.func1()
        /usr/local/go/src/net/http/server.go:1850  0xbf
panic({0x6960e0, 0x8e5630})
        /usr/local/go/src/runtime/panic.go:890  0x262
database/sql.(*DB).conn(0x0, {0x7593d0, 0xc00011a000}, 0x1)
        /usr/local/go/src/database/sql/sql.go:1288  0x53
database/sql.(*DB).query(0x6?, {0x7593d0, 0xc00011a000}, {0x6da967, 0x13}, {0x0, 0x0, 0x0}, 0x68?)

The main program:

var db *sql.DB

type Books struct {
    Isbn   string
    Title  string
    Author string
    Price  float32
}

func init() {
    var err error
    args := fmt.Sprintf("host=%s port=%d dbname=%s user='%s' password=%s sslmode=%s", "localhost", 5432, "bookstore", "santosh", "dts123", "disable")
    db, err := sql.Open("postgres", args)
    if err != nil {
        fmt.Printf("Creating Database %s", err)
    }
    if err = db.Ping(); err != nil {
        panic(err)
    }
    fmt.Println("Database connection succussful.")

}

func main() {
    http.HandleFunc("/", index)
    http.HandleFunc("/books", booksIndex)
    http.ListenAndServe(":8080", nil)
}

func index(w http.ResponseWriter, r *http.Request) {
    http.Redirect(w, r, "/books", http.StatusSeeOther)
}

func booksIndex(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    rows, err := db.Query("SELECT * FROM books")
    if err != nil {
        http.Error(w, http.StatusText(500), 500)
        return
    }
    defer rows.Close()

    bks := make([]Books, 0)
    for rows.Next() {
        bk := Books{}
        err := rows.Scan(&bk.Isbn, &bk.Title, &bk.Author, &bk.Price)
        if err != nil {
            http.Error(w, http.StatusText(500), 500)
            return
        }
        bks = append(bks, bk)
    }
    if err = rows.Err(); err != nil {
        http.Error(w, http.StatusText(500), 500)
        return
    }

}

I tried double-checking user privileges and database format and for order. All are in line with the code. The connection is established but fails with panic while querying the DB.

CodePudding user response:

You are not properly initializing the package-level db variable.

The := operator, called "short variable declaration", declares and initializes a new variable in its block scope. Any variable with the same name in an outer scope will be "shadowed".

To properly initialize the package-level variable you can use plain assignment:

var db *sql.DB

func init() {
    args := fmt.Sprintf("host=%s port=%d dbname=%s user='%s' password=%s sslmode=%s", "localhost", 5432, "bookstore", "santosh", "dts123", "disable")

    var err error
    db, err = sql.Open("postgres", args)
    if err != nil {
        fmt.Printf("Creating Database %s", err)
    }
    // ...
}

Or you can use := but then use a different variable name and make sure to use that for the assignment:

var db *sql.DB

func init() {
    args := fmt.Sprintf("host=%s port=%d dbname=%s user='%s' password=%s sslmode=%s", "localhost", 5432, "bookstore", "santosh", "dts123", "disable")

    _db, err := sql.Open("postgres", args)
    if err != nil {
        fmt.Printf("Creating Database %s", err)
    }
    // ...

    db = _db // set "global"
}
  • Related