如何将.Scan()MySQL TIMESTAMP值转换为time.Time变量?

Car*_*spa 12 mysql go

我有这个Go代码:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我从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 | abcdefghhhh@gmail.com |   NULL |            0 | 2014-10-28 15:37:44 | N      |
+----+------------+-----------------------+--------+--------------+---------------------+--------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

之后.Scan(),fmt.Println(usr)打印

{1 alakhazamm abcdefghhhh@gmail.com 0 0 {0 0 <nil>} }
Run Code Online (Sandbox Code Playgroud)

结构的最后两个字段是错误的,但我不知道为什么.我试过date_registered string在struct定义中使用,但之后我得到一个空字符串.Scan().我还读过驱动程序的文档,它将?parseTime=trueMySQL DATE和DATETIME值解析为time.Time,但是他们没有提到我正在使用的TIMESTAMP.

我错过了一些重要的内容,还是图书馆的错误/缺失功能?

inc*_*ick 8

我知道这是一个老问题,但是我在Open通话中缺少此参数:

parseTime=true
Run Code Online (Sandbox Code Playgroud)

看这里


kal*_*ule 6

除了@incognick 的回答之外,您还可以这样做(添加 parseTime=true):

db, err := sqlx.Connect("mysql", "myuser:mypass@tcp(127.0.0.1:3306)/mydb?parseTime=true")
Run Code Online (Sandbox Code Playgroud)

如果时间戳/日期时间有可能为空,在这种情况下,您应该使用扫描参数作为 sql.NullTime 而不是 time.Time。

使用 sql.NullTime 将为您提供检查扫描时间是否为空或不使用var.Valid标志的选项。如果时间var.Time有效且不为空,您可以使用它。


Car*_*spa 4

我已经找到了错误的原因。

由于rating数据库中为 NULL,扫描仪给出了错误

sql:列索引 3 上的扫描错误:将字符串“nil”转换为 uint8:strconv.ParseUint:解析“nil”:语法无效

我已经更新了数据库行,现在usr.date_registered保存usr.online了正确的值。

我想我必须将 MySQL 字段设置为 NOT NULL,并仅使用 -1 来指示未初始化的值。

  • 您可以使用database/sql包中的NullInt64类型扫描可能为空的整数。http://golang.org/pkg/database/sql/#NullInt64 (2认同)