Reputation: 655
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
Upvotes: 1
Views: 829
Reputation: 10564
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.
Upvotes: 2