Golang博客编程中如何展示最新文章

Golang博客编程中如何展示最新文章

	eg.GET("/", func(c *gin.Context) {
		query := "SELECT id, r_id, p_id, s_id from whole ORDER BY id DESC limit 6"
		r, err := db.Query(query)
		if err != nil {
			log.Fatalln("DB Connetion ERROR occured :", err)
		}
		data := []PRS_id{}
		for r.Next() {
			var temp PRS_id
			r.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID)
			data = append(data, temp)
		}
		fmt.Println(data)
		c.HTML(http.StatusOK, "index.html", data)
	})

我正在创建自己的博客,它包含三个类别:项目、回顾、学习。 我在数据库中为每个类别创建了对应的表,同时还创建了一个名为‘whole’的表,该表与每个类别表通过外键关联,目的是为了能够查看‘最近的6篇文章’。 目前总共有9篇文章。 按照我的设想,‘data’结构应该打印出: {9,3,0,0}{8,0,3,0}{7,3,0,0}{6,0,0,3}{5,0,0,3}{4,0,3,0} 但实际上它打印出: {9,3,0,0}{8,0,0,0}{7,3,0,0}{6,0,0,0}{5,0,0,0}{4,0,0,0}

id和PID打印正常,但我不明白为什么RID和SID没有正确打印。 当我在数据库控制台中执行这个查询时,它工作得很好。 有人知道这个问题是怎么回事吗?


更多关于Golang博客编程中如何展示最新文章的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

是的,我认为在测试过程中表格被稍微修改了一下,这真的很有帮助!谢谢!

更多关于Golang博客编程中如何展示最新文章的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好 @choigonyok

  • PRS_id 这个类型是如何定义的?
  • idr_idp_ids_id 的数据类型是什么?
  • 最重要的是,r.Scan() 返回的错误值是什么?

我添加了 COALESCE 函数,问题解决了!! 我了解到 COALESCE() 以及 Go 无法处理 NULL 值。 这对我真的很有帮助。 非常感谢 @christophberger !! :)图片

为了确保我们讨论的是同一件事,你是否修改了代码来处理 r.Scan() 返回的错误?并且 r.Scan() 返回的错误始终是 nil 吗?

我之所以这样问,是因为在你的代码中,我看到的唯一错误处理是针对 db.Query() 的。

查看直接的查询结果,我推测这个问题与处理 NULL 值有关。Go 语言没有 SQL NULL 的概念,有多种方法可以弥合这种语义上的差距(例如,可以参考这篇不错的总结:在 Go 中处理 SQL NULL 值的方法 | Ekin Karadeniz)。

或许可以尝试在 SELECT 语句中使用 COALESCE:

SELECT id, COALESCE(r_id, 0), ...

你好!

首先,PRS_id 结构体定义如下:

type PRS_id struct {
	ID	int // 	'whole' table's primary key = id column
	PID     int //	'projects' table's primary key = p_id column
	SID	int //	'study' table's primary key = s_id column
	RID	int //	'review' table's primary key = r_id column
}

→ 我定义这个结构体是为了获取 whole 表的数据。

其次,所有列都是 INT 类型。 这是在终端执行该查询的 MySQL 结果。

+-----+-----+-----+-----+
| id  | p_id| r_id| s_id|
+-----+-----+-----+-----+
|   1 |   1 | NULL| NULL|
|   2 | NULL| NULL|   1 |
|   3 |   2 | NULL| NULL|
|   4 | NULL|   1 | NULL|
|   5 | NULL|   2 | NULL|
|   6 | NULL| NULL|   2 |
+-----+-----+-----+-----+

第三点, 虽然没有返回错误,但结果与我预期的完全不同,正如我写的那样。 所以我请求一些帮助!

补充一下 @christophberger 所说的内容,将这段代码:

r.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID)
data = append(data, temp)

……修改为:

if err = r.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID); err != nil {
	log.Fatalln("Problem scanning:", err)
}
data = append(data, temp)	

另外,我对数据有点困惑,因为在你的第一个评论中,你希望看到的表格和代码中重叠ID的示例是这样的:

{6,0,0,3}{5,0,0,3}{4,0,3,0}

但如果你看一下你发布的表格,你会发现原始查询返回的结果并非如此:

| 4 | NULL | 1 | NULL |
| 5 | NULL | 2 | NULL |
| 6 | NULL | NULL | 2 |

难道你实际上期望看到的是下面这样吗?

{6,0,0,2}{5,0,2,0}{4,0,1,0}

无论如何,我怀疑Christopher是对的,问题出在空值上。一旦你修改了上面的那行代码,我怀疑你会看到一个错误。另一个解决方案是查看 sql.NullInt64

sql package - database/sql - Go Packages

在我看来,sql.Null 的易用性稍微有些笨拙(特别是在序列化为JSON等操作时),所以我通常自己采用指针的方式。或者为我想要使用的 sql.Null 类型编写自定义的marshal/unmarshal函数。

你的查询语句只从 whole 表中选择了 id, r_id, p_id, s_id 字段,但根据你的描述,这些字段是外键,关联到其他类别表。如果 r_ids_id 在数据库中的值正确,但代码中打印为0,可能是数据类型映射问题或数据扫描错误。

检查 PRS_id 结构体的字段类型是否与数据库中的列类型匹配。例如,如果数据库中 r_ids_id 是整数类型(如 INT),但结构体中对应字段是 string 或其他类型,Scan 可能会失败并赋零值。

以下是修正后的示例代码,确保结构体字段类型正确,并添加错误处理:

type PRS_id struct {
    ID  int `json:"id"`
    RID int `json:"r_id"`
    PID int `json:"p_id"`
    SID int `json:"s_id"`
}

eg.GET("/", func(c *gin.Context) {
    query := "SELECT id, r_id, p_id, s_id FROM whole ORDER BY id DESC LIMIT 6"
    rows, err := db.Query(query)
    if err != nil {
        log.Printf("查询失败: %v", err)
        c.HTML(http.StatusInternalServerError, "error.html", nil)
        return
    }
    defer rows.Close()

    var data []PRS_id
    for rows.Next() {
        var temp PRS_id
        if err := rows.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID); err != nil {
            log.Printf("扫描行失败: %v", err)
            continue
        }
        data = append(data, temp)
    }
    if err := rows.Err(); err != nil {
        log.Printf("遍历行时出错: %v", err)
    }

    fmt.Println(data)
    c.HTML(http.StatusOK, "index.html", data)
})

如果问题仍然存在,直接在代码中打印查询结果,并检查数据库中的实际值。例如,在 Scan 后添加调试输出:

for rows.Next() {
    var temp PRS_id
    if err := rows.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID); err != nil {
        log.Printf("扫描行失败: %v", err)
        continue
    }
    log.Printf("扫描结果: ID=%d, RID=%d, PID=%d, SID=%d", temp.ID, temp.RID, temp.PID, temp.SID)
    data = append(data, temp)
}

这有助于确认数据是否从数据库正确读取。如果 RIDSID 在数据库中为 NULL,Go 的 Scan 可能会将其映射为0(对于整数类型)。确保数据库中没有 NULL 值,或使用 sql.NullInt64 类型处理可能为 NULL 的列:

type PRS_id struct {
    ID  int           `json:"id"`
    RID sql.NullInt64 `json:"r_id"`
    PID int           `json:"p_id"`
    SID sql.NullInt64 `json:"s_id"`
}

然后在扫描后检查值:

for rows.Next() {
    var temp PRS_id
    if err := rows.Scan(&temp.ID, &temp.RID, &temp.PID, &temp.SID); err != nil {
        log.Printf("扫描行失败: %v", err)
        continue
    }
    // 处理可能为 NULL 的值
    if temp.RID.Valid {
        // 使用 temp.RID.Int64
    }
    data = append(data, temp)
}
回到顶部