使用Golang API获取数据的实现方法
使用Golang API获取数据的实现方法 我正在使用 Golang Gin 框架的 REST API 创建一个博客。当我通过 ID 调用博客时,博客内容可以无错误地显示在屏幕上,但当我调用数据中的所有博客时,会出现无效日期错误。
main.go:
type Blog struct {
ID int `db:"id" json:"id"`
Title string `db:"title" json:"title"`
Body string `db:"body" json:"body"`
ImageURL string `db:"image" json:"image"`
Date *time.Time `db:"date" json:"date"`
}
// get blog by ID
r.GET("/blog/:id", func(c *gin.Context) {
var blog Blog
id := c.Param("id")
// get blog from database
err := db.Get(&blog, "SELECT * FROM blogs WHERE id=$1", id)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{"error": "blog not found"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blog"})
}
return
}
c.JSON(http.StatusOK, blog)
})
// get all blogs
r.GET("/blogs", func(c *gin.Context) {
var blogs []Blog
// get all blogs from database
err := db.Select(&blogs, "SELECT * FROM blogs")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blogs"})
return
}
c.JSON(http.StatusOK, blogs)
})
app.js:
useEffect(() => {
async function fetchData() {
try {
const response = await axios.get('http://localhost:8000/blog/1'); //this is working
setFirstPost(response.data);
} catch (error) {
setError(error.message);
}
}
fetchData();
async function fetchSecondData() {
try {
const response = await axios.get('http://localhost:8000/blogs');//not working
setSecondPost(response.data);
} catch (error) {
setError(error.message);
}
}
fetchSecondData();
}, []);
return (
<div className="blog">
<div className='blog-page'>
<h1> BLOG</h1>
</div>
{firstPost && (
<div className="blog-first">
<div className="blog-firstpage">
<img src={firstPost.image} alt={firstPost.title} />
</div>
<div className="blog-text">
<h2>{firstPost.title}</h2>
<h3>{new Date(firstPost.date).toLocaleString('en-US', { dateStyle: 'medium' })}</h3>
<p>{firstPost.body}</p>
</div>
</div>
)}
{secondPost && (
<div className="blog">
<div className="blog-secondpage">
<img src={secondPost.image} alt={secondPost.title} />
</div>
<div className="blog-text">
<h2>{secondPost.title}</h2>
<h3>{new Date(secondPost.date).toLocaleString('en-US', { dateStyle: 'medium' })}</h3>
<p>{secondPost.body}</p>
</div>
</div>
)}
{error && <p>{error}</p>}
</div>
);
}
export default Blog;
更多关于使用Golang API获取数据的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
4 回复
没有错误,运行正常,但显示的是无效日期。
更多关于使用Golang API获取数据的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
错误是… 只需用以下代码展示:
err := db.Select(&blogs, "SELECT * FROM blogs")
if err != nil {
log.Println("Error getting blogs:", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blogs"})
return
}
问题出现在日期字段的处理上。当查询单个博客时,数据库返回的日期字段能被正确解析为 *time.Time 类型。但查询所有博客时,如果数据库中存在 NULL 日期值,Go 会尝试将 NULL 解析为 time.Time 类型导致错误。
以下是修复方案:
// 修改 Blog 结构体,使用 sql.NullTime 处理可能为 NULL 的日期
type Blog struct {
ID int `db:"id" json:"id"`
Title string `db:"title" json:"title"`
Body string `db:"body" json:"body"`
ImageURL string `db:"image" json:"image"`
Date sql.NullTime `db:"date" json:"date"`
}
// 修改获取单个博客的接口,处理 NullTime
r.GET("/blog/:id", func(c *gin.Context) {
var blog Blog
id := c.Param("id")
err := db.Get(&blog, "SELECT * FROM blogs WHERE id=$1", id)
if err != nil {
if err == sql.ErrNoRows {
c.JSON(http.StatusNotFound, gin.H{"error": "blog not found"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blog"})
}
return
}
// 手动构建响应,处理日期字段
response := map[string]interface{}{
"id": blog.ID,
"title": blog.Title,
"body": blog.Body,
"image": blog.ImageURL,
"date": nil,
}
if blog.Date.Valid {
response["date"] = blog.Date.Time
}
c.JSON(http.StatusOK, response)
})
// 修改获取所有博客的接口
r.GET("/blogs", func(c *gin.Context) {
var blogs []Blog
err := db.Select(&blogs, "SELECT * FROM blogs")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blogs"})
return
}
// 处理每个博客的日期字段
var response []map[string]interface{}
for _, blog := range blogs {
item := map[string]interface{}{
"id": blog.ID,
"title": blog.Title,
"body": blog.Body,
"image": blog.ImageURL,
"date": nil,
}
if blog.Date.Valid {
item["date"] = blog.Date.Time
}
response = append(response, item)
}
c.JSON(http.StatusOK, response)
})
或者,如果希望保持 *time.Time 类型,可以在查询时排除 NULL 值或使用 COALESCE:
// 方法二:修改 SQL 查询,处理 NULL 日期
r.GET("/blogs", func(c *gin.Context) {
var blogs []Blog
// 使用 COALESCE 或排除 NULL 值
err := db.Select(&blogs, "SELECT id, title, body, image, date FROM blogs WHERE date IS NOT NULL")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get blogs"})
return
}
c.JSON(http.StatusOK, blogs)
})
前端也需要相应调整,处理可能的 null 日期:
// 在 app.js 中修改日期显示逻辑
{secondPost && secondPost.date && (
<h3>{new Date(secondPost.date).toLocaleString('en-US', { dateStyle: 'medium' })}</h3>
)}
使用 sql.NullTime 是推荐的方法,因为它能正确处理数据库中的 NULL 值,避免解析错误。


