duandu1049 2017-05-17 21:05
浏览 91
已采纳

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

I'm currently writing a code in Golang that handles POST requests and store data into the MySQL database.

Here's what I've written so far.

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

As I run the code and try to save the data, I keep getting the following message.

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}

The log seems to point out that this line has a problem, and I would like to ask somebody for fixing this out.

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

Added Here's the log message I get on the console.

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条回答 默认 最新

  • douge3830 2017-05-17 21:30
    关注

    From error message that you got :

    runtime error: invalid memory address or nil pointer dereference goroutine 20 [running]:

    Your db varible in your hanlder() is nil that's the root of the cause.

    to fix this you can remove your : in your initialiseDB(). Because here you are assign to new variable local in the function not to your global variable. Like this :

    func initialiseDB() {
        var err error
        db, err = sql.Open("mysql", "root:@/authenticationgolang")
    
        if err != nil {
            panic(err.Error())
        }
    }
    

    Suggestion

    And then on your code please check the error value returned by the function like :

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

    Or you can use Println() in case you don't want to stop your application to run like this :

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

    The return will stop the execution of the code. Using this approach you will notice if somethings error happens on your server side and you know which line the error happened.

    And don't forget to send your response if the request success like :

    resp := struct {
        Message string
    }{
        Message : "your message",
    }
    
    // Write the response
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(resp)
    

    Hope it helps.

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部