Golang Mysql扫描返回零,什么时候有数据?

fan*_*tly 1 mysql go

有一个令人头疼的时刻。我有以下结构:

type Room struct {
    ID              int
    Name            string
    RoomType        int
    CreatedAt       time.Time
    UpdatedAt       time.Time
    DeletedAt       time.Time
    GroupId         int
    BlockId         int
    ProjectId       int
    RoomLength      float64
    RoomWidth       float64
    CeilingHeight   float64
    CeilingColorHex string
    WallColorHex    string
    FloorColorHex   string
    CeilingColorRgb string
    WallColorRgb    string
    FloorColorRgb   string
}
Run Code Online (Sandbox Code Playgroud)

在rest api中读取它:

database := db.New()
stmt, err := database.Prepare("SELECT * FROM room WHERE block_id = ?")
if err != nil {
    panic(err)
}
defer stmt.Close()

rows, err := stmt.Query(c.Param("id"))
if err != nil {
    panic(err)
}
defer rows.Close()

var rooms []common.Room
for rows.Next() {
    var r common.Room
    err := rows.Scan(&r.ID, &r.Name, &r.RoomType, &r.CreatedAt, &r.UpdatedAt, &r.DeletedAt,
        &r.GroupId, &r.BlockId, &r.ProjectId, &r.RoomLength, &r.RoomWidth, &r.CeilingHeight,
        &r.CeilingColorHex, &r.WallColorHex, &r.FloorColorHex, &r.CeilingColorRgb, &r.WallColorRgb,
        &r.FloorColorRgb)
    if err = rows.Err(); err != nil {
        panic(err)
    }

    fmt.Printf("Found: %v", r)
    rooms = append(rooms, r)
}
Run Code Online (Sandbox Code Playgroud)

然而,由此产生的有效载荷是:

{3 Loki #1 3 2018-09-25 08:42:38 +0000 UTC 2018-09-25 14:52:39 +0000 UTC 0001-01-01 00:00:00 +0000 UTC 0 0 0 0 0 0      }
Run Code Online (Sandbox Code Playgroud)

我特别关注长度/宽度,其中(上面)是 0。然而在数据库中:

mysql> select * from room where id = 3 \G
*************************** 1. row ***************************
               id: 3
             name: Loki #1
        room_type: 3
       created_at: 2018-09-25 08:42:38
       updated_at: 2018-09-25 14:52:39
       deleted_at: NULL
         group_id: 0
         block_id: 1
       project_id: 0
      room_length: 10
       room_width: 7
   ceiling_height: 4
ceiling_color_hex: #c0c0c0
   wall_color_hex: #a9a9a9
  floor_color_hex: #708090
ceiling_color_rgb: 192,192,192
   wall_color_rgb: 169,169,169
  floor_color_rgb: 112,128,144
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我认为这可能与不同的类型有关,但是在数据库中更改它们之后,然后在代码中,没有更改。谁能解释为什么.Scan不选择某些值?

谢谢!

xia*_*omi 6

首先,检查来自rows.Scan()的错误。您只检查来自rows.Err()的错误,这是一种不同类型的错误,与扫描无关。

err := rows.Scan(&r.ID, &r.Name, &r.RoomType, &r.CreatedAt, &r.UpdatedAt, &r.DeletedAt,
    &r.GroupId, &r.BlockId, &r.ProjectId, &r.RoomLength, &r.RoomWidth, &r.CeilingHeight,
    &r.CeilingColorHex, &r.WallColorHex, &r.FloorColorHex, &r.CeilingColorRgb, &r.WallColorRgb,
    &r.FloorColorRgb)
if err != nil {
    panic(err) // Error related to the scan
}
if err = rows.Err(); err != nil {
    panic(err) // Error related to the iteration of rows
}
Run Code Online (Sandbox Code Playgroud)

当 from 的值deleted_at返回 as 时NULL,Scan 将返回一个错误,例如,unsupported Scan, storing driver.Value type <nil> into type *time.Time结构的其余部分将获得零值

这意味着您的房间结构必须更改以使用指向时间的指针。

CreatedAt       *time.Time
UpdatedAt       *time.Time
DeletedAt       *time.Time
Run Code Online (Sandbox Code Playgroud)

但是,您可能需要在 sql.Open() 中添加参数 parseTime sql.Open("mysql", "user:password@/dbname?parseTime=true)以正确解析 mysql 的时间。

然后你应该收到一个有效的 *time.Time 当它被设置时,或者当它为 NULL 时为零。