I'm taking my first crack at using golang to query a MySQL database but I get the following error when I run the command go run main.go
.
2017/10/22 21:06:58 sql: Scan error on column index 4: unsupported Scan, storing driver.Value type into type *string exit status 1
Here's my main.go
main.go
package main
import (
"log"
"database/sql"
)
import _ "github.com/go-sql-driver/mysql"
var db *sql.DB
var err error
// main function to boot up everything
func main() {
var dbField,dbType,dbNull,dbKey,dbDefault,dbExtra string
// Create an sql.DB and check for errors
db, err = sql.Open("mysql", "username:password@/mydatabase")
if err != nil {
panic(err.Error())
}
rows, err := db.Query("DESCRIBE t_user")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&dbField,&dbType,&dbNull,&dbKey,&dbDefault,&dbExtra)
if err != nil {
log.Fatal(err)
}
log.Println(dbField,dbType,dbNull,dbKey,dbDefault,dbExtra)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
// sql.DB should be long lived "defer" closes it once this function ends
defer db.Close()
}
When I run the DESCRIBE t_user
from mysql terminal, I get these results:
+------------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+---------------------+------+-----+---------+----------------+
| user_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| first_name | varchar(50) | NO | | NULL | |
| middle_name | varchar(50) | NO | | NULL | |
| last_name | varchar(50) | NO | | NULL | |
| email | varchar(50) | NO | UNI | NULL | |
+------------------------+---------------------+------+-----+---------+----------------+
I can't seem to figure out what's causing the issue. Is it because the columns key, default, extra sometimes returns empty string or null values? I tried to do something like var dbNull nil
but the compiler says nil
is not a type, so if the issue is related to dbNull
needing to accept nullable values, how does golang address this situation? If that isn't the problem, I appreciate any other insight
Index 4 is the Default
column, which is nullable. You are giving it the address to place a string, but it needs to place NULL. The solution would be to use something like sql.NullString
instead of just a string.
As Gavin
mentioned,
you need to use a type that handles null values such as sql.NullString
.
As an alternative you can also have a new type that implements the db.Scanner
interface that handles nulls.
type dbNullString string
func (v *dbNullString) Scan(value interface{}) error {
if value == nil {
*v = ""
return nil
}
if str, ok := value.(string); ok {
*v = dbNullString(str)
return nil
}
return errors.New("failed to scan dbNullString")
}
Also note that you need to implement the driver.Valuer
interface to insert values using this type.