为什么 sql.Open() 在不应该返回 nil 作为错误时却返回了 nil?

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

Why does sql.Open() return nil as error when it should not?

问题

我正在尝试连接到一个MySQL数据库。

我试图查看如果我提供错误的连接信息是否会得到错误,但它仍然返回nil作为错误。即使我完全关闭MySQL,它仍然不会返回错误。如果这个函数不返回错误,那么检查错误的目的是什么?

这是在Windows上,我正在使用XAMPP,数据库没有密码。用户名是"root"

import (
	"database/sql"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/dbname?charset=utf8")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
}
英文:

I am trying to connect to a mysql database.

I tried to see if I would get an error if I gave it wrong connection information but it still returns nil as error. Even If I shut down mysql completely it still does not return an error. What is the point of check for errors after this function if it does not return errors?

This is on Windows, I am using XAMPP and I don't have a password for the database. Username is "root".

import (
	"database/sql"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/dbname?charset=utf8")
	if err != nil {
		log.Fatal(err)
	}
    defer db.Close()
}

答案1

得分: 7

SQL.Open只创建DB对象,但不打开与数据库的任何连接。如果您想测试连接,必须执行查询以强制打开连接。通常的方法是在DB对象上调用Ping()。

请参阅http://golang.org/pkg/database/sql/#Open和http://golang.org/pkg/database/sql/#DB.Ping。

英文:

SQL.Open only creates the DB object, but does not open any connections to the database. If you want to test your connections you have to execute a query to force opening a connection. The common way for this is to call Ping() on your DB object.

See http://golang.org/pkg/database/sql/#Open and http://golang.org/pkg/database/sql/#DB.Ping

答案2

得分: 4

sql.Open()的文档中引用:

> Open可能只是验证其参数而不创建与数据库的连接。要验证数据源名称是否有效,请调用Ping。

如上所述,Open()可能不会打开与数据库服务器的物理连接,但它会验证其参数。也就是说,如果参数有效,即使数据库服务器不可访问,或者dataSourceName所表示的主机不存在,它也可能返回nil错误。

回答你的另一个问题:

> 如果这个函数不返回错误,那么检查错误的意义是什么?

你必须检查返回的错误,因为它可能返回错误。例如,如果指定的driverName无效,将返回一个非nil的错误(见下文)。

要测试数据库服务器是否可访问,请使用DB.Ping()。但是,只有当返回的错误为nil时,才能使用它,否则返回的DB也可能为nil(因此在其上调用Ping()方法可能导致运行时恐慌):

if db, err := sql.Open("nonexistingdriver", "somesource"); err != nil {
    fmt.Println("Error creating DB:", err)
    fmt.Println("To verify, db is:", db)
} else {
    err = db.Ping()
    if err != nil {
        fmt.Println("db.Ping failed:", err)
    }
}

输出(在Go Playground上尝试):

Error creating DB: sql: unknown driver "nonexistingdriver" (forgotten import?)
To verify, db is: <nil>
英文:

Quoting from the doc of sql.Open():

> Open may just validate its arguments without creating a connection to the database. To verify that the data source name is valid, call Ping.

As stated, Open() may not open any physical connection to the database server, but it will validate its arguments. That being said if arguments are valid, it may return nil error even if the database server is not reachable, or even if the host denoted by dataSourceName does not exist.

To answer your other question:

> What is the point of check for errors after this function if it does not return errors?

You have to check returned errors because it can return errors. For example if the specified driverName is invalid, a non-nil error will be returned (see below).

To test if the database server is reachable, use DB.Ping(). But you can only use this if the returned error is nil, else the returned DB might also be nil (and thus calling the Ping() method on it may result in run-time panic):

if db, err := sql.Open(&quot;nonexistingdriver&quot;, &quot;somesource&quot;); err != nil {
	fmt.Println(&quot;Error creating DB:&quot;, err)
	fmt.Println(&quot;To verify, db is:&quot;, db)
} else {
	err = db.Ping()
	if err != nil {
		fmt.Println(&quot;db.Ping failed:&quot;, err)
	}
}

Output (try it on the Go Playground):

Error creating DB: sql: unknown driver &quot;nonexistingdriver&quot; (forgotten import?)
To verify, db is: &lt;nil&gt;

答案3

得分: 0

原来,这实际上并不立即连接到数据库。

来源:http://go-database-sql.org/accessing.html

为了检查连接的有效性,我们可以这样做:

db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/dbname?charset=utf8")
err = db.Ping() // 需要这样做来检查连接是否有效
if err != nil {
    log.Fatal(err)
}
英文:

It turns out that this does not actually connect to the database right away.

Source: http://go-database-sql.org/accessing.html

To check the validity of connection, we can do this:

db, err := sql.Open(&quot;mysql&quot;, &quot;root@tcp(127.0.0.1:3306)/dbname?charset=utf8&quot;)
err = db.Ping() // Need to do this to check that the connection is valid
if err != nil {
	log.Fatal(err)
}

huangapple
  • 本文由 发表于 2015年9月2日 13:18:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/32345124.html
匿名

发表评论

匿名网友

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

确定