MySQL DB Panic Error invalid memory address or nil pointer dereference

Hi,

I am facing error when trying to access MySQL DB, please let me know what needs to be changed.

Enviornment details:
$: go version
go version go1.7.1 linux/amd64
OS Details:
$: uname -a
Linux poc 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
MySQL
Your MySQL connection id is 90
Server version: 5.5.52-0ubuntu0.14.04.1 (Ubuntu)

Error Msg:

db$ go run DBMain.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x40118c]

goroutine 1 [running]:
panic(0x5ad3e0, 0xc42000c100)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.getUserDetails(0x5ddc7f, 0xa)
/home/service-rest-api/service/db/DBMain.go:39 +0x13c
main.main()
/home/service-rest-api/service/db/DBMain.go:24 +0x36
exit status 2

package main

import (
“database/sql”
“fmt”
_ “github.com/go-sql-driver/mysql”
“log”
)
func main() {
getUserDetails(“9”);

}

func getUserDetails(id string) {

dsn := "service:password@tcp(localhost:3306)/service?charset=utf8"
db, err := sql.Open("mysql", dsn)
if err != nil {
	log.Fatal(err.Error())

	panic(err.Error())
}
defer db.Close()
iss := db.Ping()
fmt.Println("Ping status %s", iss.Error())
if iss != nil {
	log.Fatal("Error for db conn")
	log.Fatal(iss.Error())
}
var (
	name string
	 
)
rows, err := db.Query("select name from user where id = ?", id)
if err != nil {
	log.Fatal(err)
}
fmt.Println("DB rows %s", rows)
defer rows.Close()
for rows.Next() {
	err := rows.Scan(&name)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Name of student,%s", name)
}
err = rows.Err()
if err != nil {
	log.Fatal(err)
}

}

You can use sql.NullString instead string in query.

var (
name sql.NullString
)

Problem is I am not getting to connect the database so how to overcome this problem. I am facing same error


Hey @swaroopjayanthi

Try replacing this:

fmt.Println("Ping status %s", iss.Error())

With:

fmt.Println("Ping status %s", iss)

If your error is nil, you can not call Error() on it or you will get a nil pointer dereference panic like you’re receiving :slight_smile:

Normally I would write something like this:

if err := db.Ping(); err != nil {
	log.Fatalln(err)
}
1 Like

Thanks @radovksyb, I have tried with the approach you mentioned
$: go run DBMain.go //below is the ouptput
Welcome
DB rows %s &{0xc4200202a0 0x4622d0 0xc420010a00 false [] 0xc420014db0}

Can you let me know how to retrieve each row from the rows returned by Query result set

And the ping status is >nil>

go run DBMain.go
Ping status
Welcome
DB rows %s &{0xc4200202a0 0x4623e0 0xc420010a20 false 0xc420014db0}

I’m currently out at the moment and won’t be home for about 4 hours, so if
no one else has helped you before I get home, then I will be more than
happy to help you then :slight_smile:

You can set grants properly for your mysql user and test your connection in console.
Also you can check localhost recognized properly in your system

Thanks oleg578, I have given full permissions of service user in mysql database. But can you please let me know how to verify localhost reachable or recognized or not? Can you please let me know

I am able to ping the localhost from shell prompt.

I have cleaned up my environment reconfigured/reinstalled Go, MySQL

Hey again @swaroopjayanthi,

Here’s a simple example to show you what you need to do to retrieve a single row from the database using mysql (with what you were doing, you want to use QueryRow instead of Query since you are retrieving information from 1 single user and not many):

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	dsn := "username:password@tcp(127.0.0.1:3306)/mydb"

	// Open the database.
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatalln(err)
	}
	defer db.Close()

	// Ping the database to verify that the connection is valid.
	if err := db.Ping(); err != nil {
		log.Fatalln(err)
	}

	// Use QueryRow instead of Query as you are only retrieving a
	// single row from the database.
	row := db.QueryRow("select name from users where id = ?", id)

	// Scan in the name from the row.
	var name string
	if err := row.Scan(&username); err != nil {
		log.Fatalln(err)
	}

	// Print out the name.
	fmt.Println(name)
}

Lastly, here is one more example, showing you how to use Query instead of my other example that uses QueryRow, so you can see how to scan in multiple users at a time.

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

// A User describes a user from the database.
type User struct {
	Id       int
	Username string
	Password string
}

func main() {
	// Repace username, password and the database name.
	dsn := "username:username@tcp(127.0.0.1:3306)/mydb"

	// Open the database.
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatalln(err)
	}
	defer db.Close()

	// Ping the database to verify that the connection is valid.
	if err := db.Ping(); err != nil {
		log.Fatalln(err)
	}

	// Use Query to retrieve all users from the database;
	rows, err := db.Query("select * from users")
	if err != nil {
		log.Fatalln(err)
	}
	defer rows.Close()

	// Iterate over all of the rows returned from the database.
	for rows.Next() {
		// Create a new user object.
		u := new(User)

		// Scan in the user's information from the row into u.
		if err := rows.Scan(&u.Id, &u.Username, &u.Password); err != nil {
			log.Fatalln(err)
		}

		// Print out the user.
		fmt.Println(u)
	}

	// Make sure there were no errors whilst scanning in the users
	// from the database.
	if err := rows.Err(); err != nil {
		log.Fatalln(err)
	}
}

Hi @radovskyb

Thanks for your quick help, I have tried with QueryRow and below is the outcome. Ping status is “Nil” error ,

Go command line output
go run DBMain.go
Ping status
2016/10/17 08:15:39 sql: no rows in result set
exit status 1

package main

import (
“database/sql”
“fmt”
_ “github.com/go-sql-driver/mysql”
“log”
)

func main() {
getUserDetails(“9”)
}

func getUserDetails(mobileNumber string) {
dsn := "service:password@tcp(127.0.0.1:3306)/service"
db, err := sql.Open(“mysql”, dsn)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
// Ping the database to verify that the connection is valid.
if err := db.Ping(); err != nil {
log.Fatalln(err)
}
fmt.Println("Ping status ", db.Ping())
if err := db.Ping(); err != nil {
log.Fatalln(err)
}
var (
first_name string
)
// Use QueryRow instead of Query as you are only retrieving a
// single row from the database.
row := db.QueryRow(“select first_name from user_details where mobile_number= ?”, mobileNumber)
if err := row.Scan(&first_name); err != nil {
log.Fatalln(err)
}
// Print out the name.
fmt.Println(first_name)
}

MySQL DB:

select * from user_details where mobile_number=‘9’;
±--------------±--------------±----------±-----------±----------±--------±--------±--------±--------±--------±--------±--------------±---------+
| mobile_number | email_id | user_type | first_name | last_name | street1 | street2 | street3 | city | country | pincode | login_session | password |
±--------------±--------------±----------±-----------±----------±--------±--------±--------±--------±--------±--------±--------------±---------+
| 9 | sai@gmail.com | society | Sadguru | Sai | | | | Shiridi | INDIA | 560043 | | |
±--------------±--------------±----------±-----------±----------±--------±--------±--------±--------±--------±--------±--------------±---------+

A nil ping error is what you want. Ping only returns a value other than nil if there is an actual error.

Edit: You also don’t need to ping the database twice like you are doing and also don’t need to be writing a ping status message. However, if you are doing this for a specific reason, then just write this instead:

// Ping the database to verify that the connection is valid.
if err := db.Ping(); err != nil {
	log.Fatalln(err)
} else {
	fmt.Println("Ping status: OK")
}

Also, I’m not sure if you are using a database with a different encoding, but there isn’t anything technically wrong with your sql statement, so you should be receiving a value if there is actually a value in your database that matches that sql statement.

What happens if you log in to your service database and type this?
select first_name from user_details where mobile_number= 9;

If you are using a separate encoding then specify it inside of your dsn.

@radovskyb

Thanks a lot , I am able to get the data with QueryRow, but I have hardcoded the query param in the calling method I am able to get the data.
But if I passes the data from request parameter, I am not able to get the data.

func getUserDetails(mobileNumber string) {
dsn := "ekservice:password@tcp(127.0.0.1:3306)/ekservice"
db, err := sql.Open(“mysql”, dsn)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
// Ping the database to verify that the connection is valid.
if err := db.Ping(); err != nil {
log.Fatalln(err)
}
fmt.Println("Ping status ", db.Ping())
if err := db.Ping(); err != nil {
log.Fatalln(err)
}
var (
first_name string
)
// Use QueryRow instead of Query as you are only retrieving a
// single row from the database.
city := "9632969969"
row := db.QueryRow(“select first_name from user_details where mobile_number = ?”, city)
if err := row.Scan(&first_name); err != nil {
log.Fatalln(err)
}
// Print out the name.
fmt.Println(first_name)
}

Not totally sure what you mean, but good to hear that it’s working now :slight_smile:

In Linux you can use nslookup (I think in Windows also)

$nslookup localhost
Server:		192.168.1.1
Address:	192.168.1.1#53

Name:	localhost
Address: 127.0.0.1
Name:	localhost
Address: ::1

If you can’t get normal response, you can edit your /etc/hosts

@radovskyb

Thanks a lot it got resolved


Thanks and Regards
–Swaroop

No problem! Anytime! :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.