EchoJuniorCoding
Как возвращать JSON, XML и другие форматы ответа в Echo?
Echo предоставляет c.JSON(), c.XML(), c.String(), c.HTML(), c.File(), c.Blob() и другие методы для отправки ответов разных форматов с нужным Content-Type.
Форматы ответов в Echo
Echo предоставляет набор методов на объекте echo.Context для отправки ответов в разных форматах. Каждый метод устанавливает правильный заголовок Content-Type и сериализует данные.
JSON
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
e.GET("/user", func(c echo.Context) error {
user := User{ID: 1, Name: "Alice"}
// Content-Type: application/json; charset=UTF-8
return c.JSON(http.StatusOK, user)
})
// Красивое форматирование (отступы)
e.GET("/user/pretty", func(c echo.Context) error {
user := User{ID: 1, Name: "Alice"}
return c.JSONPretty(http.StatusOK, user, " ")
})
// JSONP для кросс-доменных запросов
e.GET("/user/jsonp", func(c echo.Context) error {
user := User{ID: 1, Name: "Alice"}
callback := c.QueryParam("callback")
return c.JSONP(http.StatusOK, callback, user)
})
XML
type Product struct {
XMLName xml.Name `xml:"product"`
ID int `xml:"id"`
Title string `xml:"title"`
}
e.GET("/product", func(c echo.Context) error {
p := Product{ID: 42, Title: "Laptop"}
// Content-Type: application/xml; charset=UTF-8
return c.XML(http.StatusOK, p)
})
// С отступами
e.GET("/product/pretty", func(c echo.Context) error {
p := Product{ID: 42, Title: "Laptop"}
return c.XMLPretty(http.StatusOK, p, " ")
})
Текст и HTML
// Обычный текст — Content-Type: text/plain; charset=UTF-8
e.GET("/ping", func(c echo.Context) error {
return c.String(http.StatusOK, "pong")
})
// HTML — Content-Type: text/html; charset=UTF-8
e.GET("/hello", func(c echo.Context) error {
return c.HTML(http.StatusOK, "<h1>Hello, World!</h1>")
})
Файлы и потоки
// Отдать файл с диска
e.GET("/download", func(c echo.Context) error {
return c.File("./files/report.pdf")
})
// Файл как вложение (с заголовком Content-Disposition: attachment)
e.GET("/attach", func(c echo.Context) error {
return c.Attachment("./files/report.pdf", "report.pdf")
})
// Файл для открытия в браузере
e.GET("/inline", func(c echo.Context) error {
return c.Inline("./files/photo.jpg", "photo.jpg")
})
// Произвольный байтовый поток
e.GET("/blob", func(c echo.Context) error {
data := []byte{0x89, 0x50, 0x4E, 0x47} // PNG header
return c.Blob(http.StatusOK, "image/png", data)
})
// Стриминг из io.Reader
e.GET("/stream", func(c echo.Context) error {
reader, _ := os.Open("./large-file.csv")
defer reader.Close()
return c.Stream(http.StatusOK, "text/csv", reader)
})
Согласование формата (Content Negotiation)
e.GET("/data", func(c echo.Context) error {
data := map[string]string{"key": "value"}
accept := c.Request().Header.Get("Accept")
switch {
case strings.Contains(accept, "application/xml"):
return c.XML(http.StatusOK, data)
default:
return c.JSON(http.StatusOK, data)
}
})
Подводные камни
- Двойная запись: нельзя вызывать два метода ответа подряд (например,
c.JSON()а потомc.String()) — заголовки и тело уже отправлены после первого вызова. - Возврат nil после записи: если вы вручную пишете в
c.Response().Writer, а потом возвращаетеnil, Echo не будет отправлять дополнительного ответа — убедитесь, что не вернули ошибку случайно. - Сериализация nil-слайсов: в Go
nil-слайс сериализуется какnull, а пустой[]T{}— как[]. Используйтеmake([]T, 0)для пустых массивов в JSON. - c.File() и path traversal: передача пользовательского ввода в
c.File()без санации пути опасна — используйтеfilepath.Clean()и проверяйте, что результат находится внутри ожидаемой директории. - Большие JSON-ответы:
c.JSON()сериализует всё в память перед отправкой — для больших данных используйтеc.Stream()сjson.NewEncoder(). - Charset в Content-Type: Echo добавляет
; charset=UTF-8к JSON и XML автоматически — не переопределяйте заголовок вручную без необходимости.
Common mistakes
- Давать ответ про форматы ответов в Echo только на уровне определения, не показывая поведение в реальном приложении.
- Игнорировать границы ответственности вокруг темы «форматы ответов в Echo»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
- Не связывать форматы ответов в Echo с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.
What the interviewer is testing
- Точно объясняет, что именно делает форматы ответов в Echo и где это используется в Go-коде.
- Связывает форматы ответов в Echo с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
- Не изобретает API и опирается на реальные контракты официальной документации.