当前位置: 首页 > 面试题库 >

Gorm总是返回值为nil的结构

葛雨华
2023-03-14
问题内容

我正在使用Gorm构建Go Web API,作为Amazon
RDS中Postgresql数据库的ORM。问题是,尽管数据库中已经填充了数据,但Gorm总是会返回一片全为零的结构。切片中的结构数量适当,具体取决于LIMIT我给的。

我也尝试过使用database/sql内置包直接查询SQL
,在rows.Next()循环内手动插入变量,它没有问题。我用3个不同的表(具有3个不同的结构)尝试了此操作(显然),结果都是相同的。所以我想这在Gorm方面是个问题。该表之一如下所示。

结构结构

type gameCenterLog struct {
    tm      time.Time
    seq     int
    uid     int
    partner int
    token   sql.NullString
    bounty  int
    path1   sql.NullString
    path2   sql.NullString
    path3   sql.NullString
    action  sql.NullString
    value1  sql.NullString
    value2  sql.NullString
    value3  sql.NullString
    value4  sql.NullString
    value5  sql.NullString
}
func (log *gameCenterLog) TableName() string {
    return "gamecenter_log"
}

Gorm查询的示例

func testGorm() {
    connString := fmt.Sprintf("host=%v port=%v user=%v password=%v dbname=%v", host, port, user, pass, schema)
    db, err := gorm.Open("postgres", connString)
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    var logs []gameCenterLog

    today := time.Now().UTC()
    lastWeek := time.Now().Add(-7 * 24 * time.Hour).UTC()

    db.Debug().Where("tm BETWEEN ? AND ?", lastWeek, today).Order("tm desc").Limit(limit).Find(&logs)
    fmt.Printf("Error: %+v\n", db.Error)
    for _, result := range logs {
        fmt.Printf("%+v\n", result)
    }
}

政府结果

[2018-08-15 09:57:15]  [1429.58ms]  SELECT * FROM "gamecenter_log"  WHERE (tm BETWEEN '2018-08-08 02:57:14' AND '2018-08-15 02:57:14') ORDER BY tm desc LIMIT 10  
[10 rows affected or returned ] 
Error: <nil>
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:0 loc:<nil>} seq:0 uid:0 partner:0 token:{String: Valid:false} bounty:0 path1:{String: Valid:false} path2:{String: Valid:false} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}

请注意,所有结果均为零,结果没有错误…

现在用database/sql

func testSQL() {
    connString := fmt.Sprintf("host=%v port=%v user=%v password=%v dbname=%v", host, port, user, pass, schema)
    db, err := sql.Open("postgres", connString)
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    today := time.Now().UTC()
    lastWeek := time.Now().Add(-7 * 24 * time.Hour).UTC()

    query := fmt.Sprintf("SELECT * FROM \"%v\" WHERE (%v BETWEEN '%d-%02d-%02d %02d:%02d:%02d' AND '%d-%02d-%02d %02d:%02d:%02d') ORDER BY %v LIMIT %v",
        "gamecenter_log", "tm",
        lastWeek.Year(), lastWeek.Month(), lastWeek.Day(), lastWeek.Hour(), lastWeek.Minute(), lastWeek.Second(),
        today.Year(), today.Month(), today.Day(), today.Hour(), today.Minute(), today.Second(),
        "tm desc", limit)
    fmt.Println(query)
    rows, err := db.Query(query)
    if err != nil {
        panic(err.Error())
    }

    results := []gameCenterLog{}
    for rows.Next() {
        result := gameCenterLog{}
        err := rows.Scan(
            &result.tm, &result.seq, &result.uid,
            &result.partner, &result.token, &result.bounty,
            &result.path1, &result.path2, &result.path3, &result.action,
            &result.value1, &result.value2, &result.value3, &result.value4, &result.value5,
        )
        if err != nil {
            panic(err.Error())
        }
        results = append(results, result)
    }
    for _, result := range results {
        fmt.Printf("%+v\n", result)
    }
}

在这里,我appendresult结构手动results切片

原始SQL结果

SELECT * FROM "gamecenter_log" WHERE (tm BETWEEN '2018-08-08 03:03:41' AND '2018-08-15 03:03:41') ORDER BY tm desc LIMIT 10
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846269 uid:16199265 partner:1 token:{String:1534274713356-bb09968a07 Valid:true} bounty:3 path1:{String:result Valid:true} path2:{String:Win Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846278 uid:16060021 partner:15 token:{String:1534272218332-2a6a0a3263 Valid:true} bounty:2 path1:{String:result Valid:true} path2:{String:Win Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String:102012 Valid:true} value2:{String:68368886 Valid:true} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846275 uid:14565958 partner:6 token:{String:1534277021722-d2f5a72098 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:PlayStart Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846279 uid:16060021 partner:15 token:{String:1534272218332-2a6a0a3263 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:PlayEnd Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String:68368886 Valid:true} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846268 uid:16199265 partner:1 token:{String:1534274713356-bb09968a07 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:PlayEnd Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String: Valid:false} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846270 uid:16199265 partner:1 token:{String:1534274713356-bb09968a07 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:Custom Valid:true} path3:{String: Valid:false} action:{String:PemulaGameWin Valid:true} value1:{String:9700600 Valid:true} value2:{String:20000 Valid:true} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846280 uid:7627835 partner:15 token:{String:1534256412228-80b0aacd5b Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:PlayStart Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String:66729274 Valid:true} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899021 loc:0xc420113c20} seq:1534276846277 uid:10212903 partner:4 token:{String:1534270203280-7875331136 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:Custom Valid:true} path3:{String: Valid:false} action:{String:ExpertLose Valid:true} value1:{String:+9.50K Valid:true} value2:{String:5000 Valid:true} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899020 loc:0xc420113c20} seq:1534276846208 uid:13016587 partner:15 token:{String:1534265134142-ed98a488f1 Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:PlayStart Valid:true} path3:{String: Valid:false} action:{String: Valid:false} value1:{String:67935379 Valid:true} value2:{String: Valid:false} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}
{tm:{wall:0 ext:63669899020 loc:0xc420113c20} seq:1534276846265 uid:15125780 partner:1 token:{String:1534267652681-cfb8846eae Valid:true} bounty:0 path1:{String:track Valid:true} path2:{String:Custom Valid:true} path3:{String: Valid:false} action:{String:AhliGameLose Valid:true} value1:{String:-1000000 Valid:true} value2:{String:1000000 Valid:true} value3:{String: Valid:false} value4:{String: Valid:false} value5:{String: Valid:false}}

结果出来没问题。


问题答案:

gameCenterlog结构中的所有字段均为小写,因此不会导出。非导出字段对反射不可见,因此Gorm对它们不可见。

如果将字段大写:

type gameCenterLog struct {
    Tm      time.Time
    Seq     int
    Uid     int
    ...

然后Gorm将能够看到它们给出的值。Gorm应该能够弄清楚从PostgreSQL中的列名到Go中的struct字段的映射,但是如果没有,则可以使用gorm:"column:..."
struct标记。



 类似资料:
  • 问题内容: 我目前正在制作照片编辑应用。 用户选择了照片后,将使用以下代码将其自动转换为黑白: 我在这段代码中遇到的问题是,我不断收到此错误: 我的代码配置稍有不同,但是到本节时仍然会中断。 是否有任何方法可以从CIImage获取PNG或JPEG数据以用于图像视图(通常仅是UIImage)? 其他任何方法都没有详细说明应使用什么代码。 问题答案: 只需开始一个新的图形上下文并在那里绘制您的灰度图像

  • 问题内容: 我创建了一个自定义错误类型来包装错误,以便更轻松地在Golang中进行调试。当有打印错误时它可以工作,但是现在引起了恐慌。 演示版 当我调用一个函数时,它不会返回错误,我仍然应该能够包装该错误。 预期的行为是,如果错误为nil,则应该简单地忽略它,不幸的是,它会做相反的事情。 我希望它能打印出来。而是即使错误为nil也会打印。 问题答案: 正在将err变量与nil进行比较,但实际上它是

  • 初学者问题,很抱歉,如果这不是一个合适的地方,请尝试学习在中逻辑是如何工作的,我无法理解这一点 我希望它会说“是的!”如果是A、A、D或D,而是z,但出于某种原因,它会说“是的!”无论第一个符号是什么,都会断开,并且只检查第二个符号是否为z。

  • 问题内容: 如果我运行查询,例如: 即使查询与任何记录都不匹配,它也会始终返回结果吗?还是我需要验证并确保结果返回一行? 问题答案: 是的,因为它是一个聚合并且返回零。除非您添加GROUP BY,否则由于没有组,因此没有结果… 除非您添加GROUP BY,然后没有任何行,否则MAX / SUM等将返回NULL。只有COUNT传回没有结果的数字 编辑,有点晚:SUM会像MAX一样返回NULL 编辑,

  • 问题内容: 我正在使用CIFilters将图像转换为灰度并应用一些图像处理效果。在UIImageView中显示输出有效;图像将显示,并且已按预期进行了修改。 但是,每次调用UIImageJPEGRepresentation似乎都不返回任何数据。它永远都行不通。使用原始彩色图像调用UIImageJPEGRepresentation效果很好。 这里发生了什么?为什么在显示图像时jpeg转换会失败?不会

  • 你可以写出返回结构的函数。如,findCenter函数把一个Rectangle类型作为参数,返回一个Point类型的值,其中包含着该矩形中心的坐标: Point findCenter (Rectangle& box) { double x = box.corner.x + box.width/2; double y = box.corner.y + box.height/2;