无法连接到 psql 数据库

huangapple go评论68阅读模式
英文:

Unable to connect to psql db

问题

我正在尝试连接到数据库,但是当我使用GET方法向端点发出curl请求时,出现错误。我已经仔细检查了用户凭据,并授予了完全权限和超级用户权限。
以下是当curl端点时我收到的错误:

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>.

当与数据库建立连接时,当向数据库发出请求时,会触发以下错误:

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?)

主程序:

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
	}

}

我尝试了多次检查用户权限、数据库格式和顺序,所有内容都与代码一致。连接已经建立,但在查询数据库时出现了panic错误。

英文:

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.

答案1

得分: 0

你没有正确初始化包级别的db变量。

:=运算符被称为“短变量声明”,它在其块作用域中声明并初始化一个新的变量。任何外部作用域中具有相同名称的变量将被“遮蔽”。

要正确初始化包级别的变量,你可以使用普通的赋值

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)
    }
    // ...
}

或者你可以使用:=,但是使用不同的变量名,并确保在赋值时使用该变量名:

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 // 设置“全局”变量
}
英文:

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"
}

huangapple
  • 本文由 发表于 2022年11月19日 21:50:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/74500597.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定