Golang - 在将数据插入MySQL DB时意外结束流

时间:2017-05-18 05:05:34

标签: mysql go

我目前正在Golang编写代码来处理POST请求并将数据存储到MySQL数据库中。

这是我到目前为止所写的内容。

package main

import (
    "fmt"
    "os"
    "log"
    "net/http"
    "database/sql"
    "golang.org/x/crypto/bcrypt"
    _ "github.com/go-sql-driver/mysql"
)

var myLogger *log.Logger
var db *sql.DB
var err error

type UserRegistrationData struct {
    email string
    password string
}

func handler(w http.ResponseWriter, r *http.Request) {
    myLogger = log.New(os.Stdout, "INFO: ", log.LstdFlags)

    var email string = r.PostFormValue("email")
    var password string = r.PostFormValue("password")

    data := UserRegistrationData{email, password}
    jsonEncoded, _ := json.Marshal(data)

    myLogger.Println("Success")

    hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    _, err = db.Exec("INSERT INTO users (email, password) VALUES (?, ?)", email, hashedPassword)
}

func initialiseDB() {
    db, err := sql.Open("mysql", "root:@/authenticationgolang")

    if err != nil {
        panic(err.Error())
    }

    defer db.Close()
}

func main() {
    initialiseDB()
    http.HandleFunc("/call", handler)
    http.ListenAndServe(":8080", nil)
}

当我运行代码并尝试保存数据时,我不断收到以下消息。

unexpected end of stream on Connection{10.10.10.153:8080, proxy=DIRECT@hostAddress=/10.10.10.153:8080 cipherSuite=none protocol=http/1.1}

日志似乎指出这行存在问题,我想请某人解决这个问题。

_, err = db.Exec("INSERT INTO users (email, password) VALUES (?, ?)", email, hashedPassword)

已添加以下是我在控制台上收到的日志消息。

2017/05/18 14:47:52 http: panic serving 10.10.10.58:41668: runtime error: invalid memory address or nil pointer dereference
goroutine 20 [running]:
net/http.(*conn).serve.func1(0xc4201360a0)
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:1721 +0xd0
panic(0x1288b60, 0x1424e70)
    /usr/local/Cellar/go/1.8.1/libexec/src/runtime/panic.go:489 +0x2cf
database/sql.(*DB).conn(0x0, 0x14027c0, 0xc420010450, 0xc420034801, 0x10000000142ec80, 0x1600960, 0x2)
    /usr/local/Cellar/go/1.8.1/libexec/src/database/sql/sql.go:896 +0x3a
database/sql.(*DB).exec(0x0, 0x14027c0, 0xc420010450, 0x12e699d, 0x31, 0xc420045c58, 0x2, 0x2, 0x1, 0x0, ...)
    /usr/local/Cellar/go/1.8.1/libexec/src/database/sql/sql.go:1183 +0xb9
database/sql.(*DB).ExecContext(0x0, 0x14027c0, 0xc420010450, 0x12e699d, 0x31, 0xc420045c58, 0x2, 0x2, 0x126ed20, 0xc42013c440, ...)
    /usr/local/Cellar/go/1.8.1/libexec/src/database/sql/sql.go:1165 +0xbc
database/sql.(*DB).Exec(0x0, 0x12e699d, 0x31, 0xc420034c58, 0x2, 0x2, 0x3c, 0x0, 0x0, 0x0)
    /usr/local/Cellar/go/1.8.1/libexec/src/database/sql/sql.go:1179 +0x85
main.handler(0x14022c0, 0xc42014a0e0, 0xc420144100)
    /Users/marshall/documents/projects/authenticationgolang/helloworld.go:40 +0x530
net/http.HandlerFunc.ServeHTTP(0x12ea668, 0x14022c0, 0xc42014a0e0, 0xc420144100)
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:1942 +0x44
net/http.(*ServeMux).ServeHTTP(0x142e060, 0x14022c0, 0xc42014a0e0, 0xc420144100)
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:2238 +0x130
net/http.serverHandler.ServeHTTP(0xc42009a2c0, 0x14022c0, 0xc42014a0e0, 0xc420144100)
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:2568 +0x92
net/http.(*conn).serve(0xc4201360a0, 0x1402780, 0xc42011e580)
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:1825 +0x612
created by net/http.(*Server).Serve
    /usr/local/Cellar/go/1.8.1/libexec/src/net/http/server.go:2668 +0x2ce

1 个答案:

答案 0 :(得分:2)

从您收到的错误消息:

  

运行时错误:无效的内存地址或无指针取消引用   goroutine 20 [正在运行]:

db中的hanlder()变量是零,这是原因的根源。

要解决此问题,您可以删除:中的initialiseDB()。因为在这里你被分配给函数中的新变量local而不是你的全局变量。像这样:

func initialiseDB() {
    var err error
    db, err = sql.Open("mysql", "root:@/authenticationgolang")

    if err != nil {
        panic(err.Error())
    }
}

<强> 建议

然后在您的代码上,请检查函数返回的错误值,如:

data := UserRegistrationData{email, password}
    jsonEncoded, err := json.Marshal(data)
    if err !=nil {
        myLogger.Fatal(err)
    }

    myLogger.Println("Success")

    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    if err != nil {
       myLogger.Fatal(err)
    }
    _, err = db.Exec("INSERT INTO users (email, password) VALUES (?, ?)", email, hashedPassword)
   if err != nil {
       myLogger.Fatal(err)
   }

或者您可以使用Println(),以防您不想停止您的应用程序运行:

if err != nil {
   myLogger.Println(err)
   return
}

返回将停止执行代码。使用这种方法,您会注意到服务器端是否发生了某些错误,并且您知道错误发生在哪一行。

如果请求成功,请不要忘记发送您的回复:

resp := struct {
    Message string
}{
    Message : "your message",
}

// Write the response
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(resp)

希望它有所帮助。