昨天我們把「新增待辦」煮熟了,今天要端上菜單頁:把所有任務完整列出來。沒有列表就一直寫入、看不到內容,感覺就像把日記塞抽屜卻從不翻——靈魂少一半。今天補齊!📋✨
本篇目標
• 做出 GET /todos
:一次把全部任務列出來
• 加碼 GET /todos/:id
:想點單點,也沒問題
curl
/ Postman 測試先回顧:資料結構 & 暫存
我們沿用上一篇的設定(struct + slice 暫存),直接開跑。
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
}
var todos []Todo
var nextID = 1
路由 1:GET /todos(列出全部)
要點很單純:把 todos
這個 slice 原封不動回傳成 JSON。
e.GET("/todos", func(c echo.Context) error {
return c.JSON(http.StatusOK, todos)
})
測試一下(先執行 go run main.go
):
curl http://localhost:1323/todos
若你已經新增過兩筆(例如上一篇的「寫數學作業」「倒垃圾」),回傳會像這樣:
[
{
"id": 1,
"title": "寫數學作業",
"done": false
},
{
"id": 2,
"title": "倒垃圾",
"done": false
}
]
小提醒:若你是「全新啟動、尚未新增」,就會拿到 []
(空陣列),這是正常的唷。
路由 2(加碼):GET /todos/:id(查單一筆)
有時候你只想看某一條任務,像在菜單上點單點。我們用 URL 參數 :id
來指定要找的任務號。
e.GET("/todos/:id", func(c echo.Context) error {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string:{
"error": "id must be a number",
})
}
for _, t := range todos {
if t.ID == id {
return c.JSON(http.StatusOK, t)
}
}
return c.JSON(http.StatusNotFound, map[string]string{
"error": "todo not found",
})
})
測試看看:
curl http://localhost:1323/todos/1
若存在,就會拿到:
{
"id": 1,
"title": "寫數學作業",
"done": false
}
如果你查一個不存在的 ID(例如 99),就會得到:
{
"error": "todo not found"
}
完整 main.go
(可直接複製貼上)
package main
import (
"net/http"
"strconv"
"github.com/labstack/echo/v4"
)
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
}
var todos []Todo
var nextID = 1
func main() {
e := echo.New()
// 問候 / 健康檢查
e.GET("/hello", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, TodoList!")
})
// 新增任務:POST /todos
e.POST("/todos", func(c echo.Context) error {
var newTodo Todo
if err := c.Bind(&newTodo); err != nil || newTodo.Title == "" {
return c.JSON(http.StatusBadRequest, map[string]string{
"error": "invalid request",
})
}
newTodo.ID = nextID
newTodo.Done = false
nextID++
todos = append(todos, newTodo)
return c.JSON(http.StatusOK, newTodo)
})
// 列出全部任務:GET /todos
e.GET("/todos", func(c echo.Context) error {
return c.JSON(http.StatusOK, todos)
})
// 查單一任務:GET /todos/:id
e.GET("/todos/:id", func(c echo.Context) error {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{
"error": "id must be a number",
})
}
for _, t := range todos {
if t.ID == id {
return c.JSON(http.StatusOK, t)
}
}
return c.JSON(http.StatusNotFound, map[string]string{
"error": "todo not found",
})
})
e.Logger.Fatal(e.Start(":1323"))
}
測試清單(你可以照著一步步做)
go run main.go
curl -X POST http://localhost:1323/todos -H "Content-Type: application/json" -d '{"title":"寫數學作業"}'
curl -X POST http://localhost:1323/todos -H "Content-Type: application/json" -d '{"title":"倒垃圾"}'
curl http://localhost:1323/todos
curl http://localhost:1323/todos/1
常見小坑(快速筆記)
• 回傳是 []
:代表目前沒有資料,先用 POST 新增幾筆。
• id must be a number
:URL 要用數字,例如 /todos/2
,不要 /todos/二
。
• todo not found
:你查的 id
不存在。確認有沒有新增成功或 ID 打錯。
小結
今天我們把「查詢任務」裝上去了:
GET /todos
:一次看全部GET /todos/:id
:單點精準查看curl
/Postman 測起來沒問題你的 TodoList 現在不只會「寫」也會「讀」了。資料有進有出,生命就有循環。🌱
下一篇預告
接下來,我們要學會更新狀態(把 done
勾起來或取消)與刪除任務:
PUT /todos/:id
(或 PATCH
):切換完成狀態DELETE /todos/:id
:刪除任務把 CRUD 集齊,就像神奇寶貝收集到四元素,系統就能真正自由呼吸。🎮