ข้ามไปยังเนื้อหา

Routing และ Handler

ใน Express handler รับ (req, res, next) ส่วนใน Echo ทุก handler ใช้ signature มาตรฐานเดียวกัน:

func(c *echo.Context) error

*echo.Context รวม request, response writer, path parameter, query parameter และ helper method ไว้ด้วยกัน คืน nil เมื่อสำเร็จ หรือคืน error เพื่อให้ Echo จัดการ response กรณีล้มเหลว

TypeScript
// Express handler
app.get('/books/:id', (req, res, next) => {
const id = req.params.id;
const book = findBook(id);
if (!book) return res.status(404).json({ message: 'not found' });
res.json(book);
});
Go
// Echo handler
func getBook(c *echo.Context) error {
id := c.Param("id")
book, err := findBook(id)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "not found")
}
return c.JSON(http.StatusOK, book)
}

Routing API ของ Echo คล้าย Express มาก ชื่อ method แมปตรงกับ HTTP verb

TypeScript
// Express
app.get('/books', listBooks);
app.post('/books', createBook);
app.get('/books/:id', getBook);
app.put('/books/:id', updateBook);
app.delete('/books/:id', deleteBook);
Go
// Echo
e.GET("/books", listBooks)
e.POST("/books", createBook)
e.GET("/books/:id", getBook)
e.PUT("/books/:id", updateBook)
e.DELETE("/books/:id", deleteBook)

c.Param("name") คืนค่า string ของ segment ที่ตั้งชื่อไว้ ใช้ colon :name เหมือนกับ Express

TypeScript
// Express
app.get('/users/:id/posts/:postId', (req, res) => {
const { id, postId } = req.params;
res.json({ userId: id, postId });
});
Go
// Echo
e.GET("/users/:id/posts/:postId", func(c *echo.Context) error {
userID := c.Param("id")
postID := c.Param("postId")
return c.JSON(http.StatusOK, map[string]string{
"userId": userID,
"postId": postID,
})
})

c.QueryParam("name") อ่านค่า query ตัวเดียว ส่วน c.QueryParams() คืนทั้งหมดเป็น url.Values (คือ map[string][]string) และ c.QueryParamOr("page", "1") ใช้ใส่ค่า default

TypeScript
// Express
app.get('/books', (req, res) => {
const { page = '1', limit = '10' } = req.query;
res.json({ page, limit });
});
Go
// Echo
e.GET("/books", func(c *echo.Context) error {
page := c.QueryParamOr("page", "1")
limit := c.QueryParamOr("limit", "10")
return c.JSON(http.StatusOK, map[string]string{
"page": page, "limit": limit,
})
})

ใน Express คุณต้องแปลง req.params.id เอง Echo v5 มี generic helper ที่ parse และตรวจสอบให้ในครั้งเดียว แล้วคืน error ที่คุณเอาไปตอบ 400 ได้เลย:

e.GET("/items/:id", func(c *echo.Context) error {
id, err := echo.PathParam[int](c, "id")
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "id must be an integer")
}
limit, err := echo.QueryParamOr[int](c, "limit", 10)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "limit must be an integer")
}
return c.JSON(http.StatusOK, map[string]int{"id": id, "limit": limit})
})

มีครบทุกแหล่งข้อมูล: echo.QueryParam[T], echo.QueryParams[T] (key ซ้ำหลายค่า), echo.FormValue[T] และ echo.PathParamOr[T]

NestJS controller เป็น class ส่วนใน Go รูปแบบ idiomatic คือ struct ที่มี method เป็นตัว handler แล้วทำ dependency injection ผ่าน field ของ struct

TypeScript
// NestJS controller
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Get(':id')
findOne(@Param('id') id: string) {
return this.booksService.findOne(id);
}
}
Go
// Echo — handler struct (manual DI)
type BookHandler struct {
store BookStore
}
func NewBookHandler(s BookStore) *BookHandler {
return &BookHandler{store: s}
}
func (h *BookHandler) Get(c *echo.Context) error {
id := c.Param("id")
book, err := h.store.FindByID(c.Request().Context(), id)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error())
}
return c.JSON(http.StatusOK, book)
}
// Registration in main.go:
// bh := NewBookHandler(store)
// e.GET("/books/:id", bh.Get)

รันบนเครื่องของคุณ — ต้องการ Echo module และ network port

Echo handler คืนค่าชนิดใด?
อ่าน path parameter ชื่อ "id" ใน Echo อย่างไร?
อ่าน query string ชื่อ "page" ใน Echo อย่างไร?
รูปแบบ idiomatic ของ Go ที่เทียบเท่า NestJS controller class คืออะไร?