2014-10-28 15 views
5

Ho questo codice Go:Come .Scan() un valore TIMESTAMP MySQL in una variabile time.Time?

package main 

import (
    "fmt" 
    "database/sql" 
    _"github.com/go-sql-driver/mysql" 
    "time" 
) 

type User struct { 
    id     uint32 
    name    string 
    email    string 
    rating    uint8 
    subscription  uint8 
    date_registered  time.Time 
    online    string 
} 

// main entry point 
func main() { 
    // setup db connection 
    db, err := sql.Open("mysql", "user:@tcp(127.0.0.1:3306)/c9?parseTime=true") 
    if err != nil { 
     fmt.Println(err) 
    } 
    defer db.Close() 

    // query 
    rows, err := db.Query("SELECT * FROM users WHERE id = ?", 1) 
    if err != nil { 
     fmt.Println(err) 
    } 
    defer rows.Close() 

    usr := User{} 
    for rows.Next() { 
     err := rows.Scan(&usr.id, &usr.name, &usr.email, &usr.rating, &usr.subscription, &usr.date_registered, &usr.online) 
     if err != nil { 
      fmt.Println(err) 
     } 
    } 
    fmt.Println(usr) 
    err = rows.Err() 
    if err != nil { 
     fmt.Println(err) 
    } 
} 

Questo è ciò che ottengo dalla console di MySQL:

mysql> describe users; 
+-----------------+---------------------+------+-----+-------------------+----------------+ 
| Field   | Type    | Null | Key | Default   | Extra   | 
+-----------------+---------------------+------+-----+-------------------+----------------+ 
| id    | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| name   | varchar(50)   | NO |  | NULL    |    | 
| email   | varchar(50)   | NO |  | NULL    |    | 
| rating   | tinyint(3) unsigned | YES |  | NULL    |    | 
| subscription | tinyint(3) unsigned | NO |  | 0     |    | 
| date_registered | timestamp   | NO |  | CURRENT_TIMESTAMP |    | 
| online   | char(1)    | NO |  | N     |    | 
+-----------------+---------------------+------+-----+-------------------+----------------+ 
7 rows in set (0.00 sec) 

mysql> SELECT * FROM users; 
+----+------------+-----------------------+--------+--------------+---------------------+--------+ 
| id | name  | email     | rating | subscription | date_registered  | online | 
+----+------------+-----------------------+--------+--------------+---------------------+--------+ 
| 1 | alakhazamm | [email protected] | NULL |   0 | 2014-10-28 15:37:44 | N  | 
+----+------------+-----------------------+--------+--------------+---------------------+--------+ 
1 row in set (0.00 sec) 

Dopo .Scan(), fmt.Println(usr) stampe

{1 alakhazamm [email protected] 0 0 {0 0 <nil>} } 

Gli ultimi due campi della struttura sono sbagliate ma non ho idea del perché. Ho provato a utilizzare date_registered string nella definizione della struct, ma ottengo una stringa vuota dopo .Scan(). Ho anche letto nei documenti del driver che ?parseTime=true analizza i valori di MySQL DATE e DATETIME in tempo. Tempo, ma non menzionano TIMESTAMP che è quello che sto attualmente usando.

Mi manca qualcosa di importante o è un bug/funzionalità mancante della libreria?

risposta

3

Ho trovato la causa dell'errore.

Dal rating è NULL nel database, lo scanner ha dato l'errore

SQL: errore di scansione su indice di colonna 3: convertire stringa "nullo" ad un uint8: strconv.ParseUint: parsing "nil" : sintassi non valida

ho aggiornato la riga di database e ora usr.date_registered e usr.online tenere i valori corretti.

Suppongo che dovrò rendere il campo MySQL NOT NULL e usare solo -1 per indicare un valore non inizializzato.

+2

È possibile eseguire la scansione di interi possibilmente nulli utilizzando il tipo NullInt64 nel pacchetto di database/SQL. http://golang.org/pkg/database/sql/#NullInt64 –

+0

Ha funzionato, grazie! –

+0

Abbiamo così tanti valori temporali nel nostro codice che possono essere nulli, che abbiamo finito semplicemente aggiungendo una semplice classe NullTime che è modellata come le altre classi null del DB. –

1

So che questa è una vecchia questione però mi mancava questo parametro nella mia chiamata aperta:

parseTime=true 

See here

Problemi correlati