首页 文章

使用golang获取mysql连接时出错

提问于
浏览
0

我是golang和MySQL的新手,我正在使用开发框创建一个简单的网页,使用golang(来自下面两个文件的代码)来获取输入,将输入存储到数据库并在网页上显示输入 . 目前在本地使用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)

我在命令提示符中获得以下代码注释中注明的所有类型的示例连接字符串:

DB: &{0x99c410 root:abc@/abc 0 {0 0} [] [] 0 0xc820072180 false map[] map[] 0 0 0 < nil >}

我的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]))

Here is the minimal code sample:

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

1 回答

  • 0

    问题是由 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 实例来避免它 .

相关问题