Golang中如何获取数据库字段的时间信息

Golang中如何获取数据库字段的时间信息 我在从数据库检索数据时遇到了问题。为什么插入和输出的 created_at 和 updated_at 结果不一致?

插入:2019-03-23 00:00:00
输出:“0001-01-01T00:00:00Z”

相关源代码如下:

结构体:

type Builder struct {
Id         int       `json:"id"`
Name       string    `json:"name"`
Created_at time.Time `json:"created_at"`
Updated_at time.Time `json:"updated_at"`
}

数据库:

CREATE TABLE test_types (
id bigint NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE now(),
PRIMARY KEY (id)
);
INSERT INTO test_types (id, name, created_at) VALUES (1, 'Welcome Screen', '2019-03-23 00:00:00');

输出:

{
"id": 1,
"name": "Welcome Screen",
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "0001-01-01T00:00:00Z"
},

Go版本:go1.11.1
数据库:Mariadb 10.3.13

我的代码有什么问题吗?谢谢。


更多关于Golang中如何获取数据库字段的时间信息的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

为了正确处理时间和MySQL驱动,您应该在连接字符串中使用parseTime参数。另一个观察是关于使用时间戳字段,这并不是一个很好的选择。如果只在一个时区工作可能没问题,但对于多个时区,请使用datetime或其他等效类型,并让客户端添加其特定时区。简而言之,在服务器上使用UTC时区。

更多关于Golang中如何获取数据库字段的时间信息的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题出现在Go结构体字段标签与数据库列名的映射上。Go的数据库/sql包默认使用蛇形命名到驼峰命名的转换,但你的结构体字段使用了蛇形命名(created_at),而数据库列名也是蛇形命名,这可能导致映射失败。

以下是解决方案:

  1. 明确指定列名映射: 在结构体标签中添加db标签来明确指定数据库列名:
type Builder struct {
    Id        int       `json:"id" db:"id"`
    Name      string    `json:"name" db:"name"`
    CreatedAt time.Time `json:"created_at" db:"created_at"`
    UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
  1. 使用SQL别名: 在查询语句中为列指定别名:
rows, err := db.Query(`
    SELECT 
        id,
        name,
        created_at as createdat,
        updated_at as updatedat 
    FROM test_types
`)
  1. 完整示例代码
package main

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

type Builder struct {
    Id        int       `json:"id" db:"id"`
    Name      string    `json:"name" db:"name"`
    CreatedAt time.Time `json:"created_at" db:"created_at"`
    UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}

func main() {
    db, err := sql.Open("mysql", "user:password@/dbname")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    var builder Builder
    err = db.QueryRow(`
        SELECT 
            id,
            name,
            created_at,
            updated_at 
        FROM test_types WHERE id = ?
    `, 1).Scan(
        &builder.Id,
        &builder.Name,
        &builder.CreatedAt,
        &builder.UpdatedAt,
    )
    
    if err != nil {
        log.Fatal(err)
    }

    jsonData, _ := json.Marshal(builder)
    fmt.Println(string(jsonData))
}
  1. 使用结构体扫描库: 考虑使用sqlx库来简化映射:
import "github.com/jmoiron/sqlx"

type Builder struct {
    Id        int       `json:"id" db:"id"`
    Name      string    `json:"name" db:"name"`
    CreatedAt time.Time `json:"created_at" db:"created_at"`
    UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}

var builder Builder
err = sqlx.Get(db, &builder, "SELECT * FROM test_types WHERE id = ?", 1)

主要问题是命名约定不匹配。Go的数据库驱动通常期望结构体字段使用驼峰命名(如CreatedAt),而数据库列使用蛇形命名(如created_at)。通过明确指定映射关系可以解决这个问题。

回到顶部