【问题标题】:Error getting mysql connection using golang使用 golang 获取 mysql 连接时出错
【发布时间】:2016-10-21 07:05:29
【问题描述】:

我是 golang 和 MySQL 的新手,我正在使用开发框创建一个简单的网页,使用 golang(来自 2 个文件的代码在下面)来获取输入,将输入存储到数据库中并显示输入一个网页。目前在本地使用 MySQL 作为我的数据库,我的用户名是 root,密码是 abc,我的数据库也被命名为 abc。

在顶部我已经导入:

  import (
      _"github.com/go-sql-driver/mysql" 

      "database/sql"
  )

当我提供我的网页时,我会调用我的 connectDB 函数:

 func init(){
    INDEX_HTML , _ = ioutil.ReadFile("./templates/index.html")
    connectDb()
 }

 func connectDb(){
    //socket : var/run/mysqld/mysqld.sock
 /* connection string examples : 
  db, err := sql.Open("mysql", "user:password@/dbname")
  user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true  

  TCP using default port (3306) on localhost: 
    user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped

  Use the default protocol (tcp) and host (localhost:3306):
    user:password@/dbname

  No Database preselected:
    user:password@/
*/

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

    log.Println("DB: ", db)

    checkErr(err)

    // Open doesn't open a connection. Validate DSN data:
    checkErr(err)
 }

我的理解和根据https://github.com/go-sql-driver/mysql SQL.open 返回一个 * sql.DB,当程序遇到上面的代码时:

/* At the top of my code i have var db = *sql.DB */
log.Println("DB: ", db)

我在命令提示符中得到以下内容,上面的代码 cmets 中记录了所有类型的示例连接字符串:

数据库:&{0x99c410 root:abc@/abc 0 {0 0} [] [] 0 0xc820072180 false map[] map[] 0 0 0 }

我的 MySQL 数据库使用给定的用户名和密码通过命令行在本地运行良好,我可以通过手动插入以下查询来获取一些项目。

mysql>
mysql> select * from ListItems
     -> ;
+-------+
| items |
+-------+
| item1 |
| item2 |
+-------+

我正在尝试了解消息是什么以及如何连接到 mysql 数据库以运行查询并插入到数据库中。

也许我的连接字符串有问题?尝试插入数据库时​​的错误示例:

016/06/20 02:22:36 http: panic serving 10.1.0.5:41861: 
runtime error: invalid    
memory address or nil pointer dereference
goroutine 7 [running]:

net/http.(*conn).serve.func1(0xc82006c380)
    /usr/local/go/src/net/http/server.go:1389 +0xc1
panic(0x74ef00, 0xc82000a0c0)
    /usr/local/go/src/runtime/panic.go:443 +0x4e9
database/sql.(*DB).conn(0x0, 0x1, 0x0, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:778 +0xac9
database/sql.(*DB).exec(0x0, 0x812b60, 0x26, 0xc82003fa70, 0x1, 0x1, 0xc82000b201, 0x0, 0x0, 0x0, ...)
    /usr/local/go/src/database/sql/sql.go:1021 +0x87
database/sql.(*DB).Exec(0x0, 0x812b60, 0x26, 0xc82003fa70, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:1009 +0xbe
main.AddListHandler(0x7f56da7ac9b0, 0xc82006f6c0, 0xc8200f21c0)
    /home/cabox/workspace/src/github.com/user/hello/main.go:26 +0x36c **<---**
net/http.HandlerFunc.ServeHTTP(0x859f70, 0x7f56da7ac9b0, 0xc82006f6c0, 0xc8200f21c0)
    /usr/local/go/src/net/http/server.go:1618 +0x3a
net/http.(*ServeMux).ServeHTTP(0xc820010b10, 0x7f56da7ac9b0, 0xc82006f6c0, 0xc8200f21c0)
    /usr/local/go/src/net/http/server.go:1910 +0x17d
net/http.serverHandler.ServeHTTP(0xc82006c180, 0x7f56da7ac9b0, 0xc82006f6c0, 0xc8200f21c0)
    /usr/local/go/src/net/http/server.go:2081 +0x19e
net/http.(*conn).serve(0xc82006c380)
    /usr/local/go/src/net/http/server.go:1472 +0xf2e
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:2137 +0x44e

当我查看 main.go 中的第 26 行时,我有:

  db.Exec("INSERT INTO ListItems(items) Values(?)" , (r.Form["item"][0]))

这是最小的代码示例:

项目/模板/index.html:

<!doctype html>

<h1>Enter item to add to list:</h1><br>
<form action="/addlist" method="post">
<input type="text" name="item" placeholder="Enter Item to add to list"><br>
<input type ="submit" class="add" value="Add To List"><br>
</form>

projects/main.go .. 使用 go build main.go

package main

import (
 "net/http"
 "fmt"
 "io/ioutil"
 "log"
_"github.com/go-sql-driver/mysql"
 "database/sql"
)

var  INDEX_HTML []byte // holds the raw html of index.html inside /templates
var db *sql.DB // pointer to sql.open which returns a sql.db 


func main(){
   fmt.Println("starting server on port 8080")
   http.HandleFunc("/", IndexHandler)
   http.HandleFunc("/addlist", AddListHandler)
   http.ListenAndServe(":8080", nil)

}

func AddListHandler(w http.ResponseWriter, r *http.Request){
  r.ParseForm()
  log.Println("adding list: ", r.Form["item"][0])
  db.Exec("INSERT INTO ListItems(items) Values(?)" , (r.Form["item"][0])) /*error*/
  if(db == nil){log.Println("DB is nill")}

  http.Redirect(w,r,"/", http.StatusTemporaryRedirect)
}

func IndexHandler(w http.ResponseWriter, r *http.Request){
  log.Println("GET /")
  w.Write(INDEX_HTML)
}

func init(){
  INDEX_HTML , _ = ioutil.ReadFile("./templates/index.html")
  connectDb()
}

func connectDb(){
  //socket : var/run/mysqld/mysqld.sock
  /* connection string examples : 
   db, err := sql.Open("mysql", "user:password@/dbname")
   user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true   
   TCP using default port (3306) on localhost: 
     user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped
  Use the default protocol (tcp) and host (localhost:3306):
    user:password@/dbname
  No Database preselected:
    user:password@/
  */

    db, err := sql.Open("mysql", "root:abc@/abc")
    log.Println("DB: ", db)
    checkErr(err)

   // Open doesn't open a connection. Validate DSN data:
    checkErr(err)
 }

 func checkErr(err error) {
    if err != nil {
      log.Println(err)
    }else{
      log.Println(err)
    }
 }

【问题讨论】:

  • 那是 golang 打印你的 DB 实例。正是您在log.Println("DB: ", db) 中要求它执行的操作。你期望看到什么?一切似乎都运行良好。
  • hmm 我以为我会看到某种形式的数据库。这是我第一次使用 golang 和 mysql。我复制了我的错误以及导致它的代码 sn-p。
  • 感谢您提供错误信息。但我还是想不通。如果您包含mcve,也许其他人可以提供帮助。
  • 感谢您的澄清。我意识到我正在查看一个数据库实例,但最后的 值开始让我感到困惑。我期待那里有代表我的数据库的东西。
  • 我已经包含了我用于此的代码示例

标签: mysql go


【解决方案1】:

问题是您通过var db *sql.DB 声明的全局db 变量从未被赋值。所以它保持默认值nil。并且试图取消引用一个 nil 指针会给你错误。

您可能认为在init 函数中,您正在为这个变量分配新创建的DB 实例。但是:= 创建了一个新的局部变量来保存新的DB 实例。全局 db 变量保持不变。见example

那就这样吧,

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

根据我使用全局变量的经验,当你可以避免它导致难以调试的错误时。 (就像这个。)我认为你可以通过让connectDb 返回一个DB 实例来避免它。

【讨论】:

  • 我做了这些改变:database, err = sql.Open("mysql", "root:abc@/abc") db = database 尽管在我的 addlisthandlerfunction() 这个查询中它没有抛出错误不插入我的数据库: log.Println("adding list: ", r.Form["item"][0])
  • 我想我的问题是如何让我的 addlisthandler 函数能够访问 sql.Open("mysql", "root:abc@/abc") 提供的实例?跨度>
  • DB.Exec 返回结果和错误。检查那些。
  • 修复了错误,现在应用程序可以工作了:D 感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 2013-12-03
  • 1970-01-01
  • 2021-07-07
  • 1970-01-01
相关资源
最近更新 更多