第一个应用 #
一、创建项目 #
1.1 项目初始化 #
bash
mkdir hello-echo
cd hello-echo
go mod init hello-echo
go get github.com/labstack/echo/v4
1.2 项目结构 #
text
hello-echo/
├── main.go
├── go.mod
└── go.sum
二、Hello World #
2.1 最简示例 #
创建 main.go:
go
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Start(":8080")
}
2.2 运行应用 #
bash
go run main.go
输出:
text
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.11.1
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080
2.3 测试访问 #
bash
curl http://localhost:8080
Hello, World!
三、代码解析 #
3.1 创建Echo实例 #
go
e := echo.New()
创建一个Echo应用实例,这是所有功能的入口点。
3.2 定义路由 #
go
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
| 部分 | 说明 |
|---|---|
e.GET |
注册GET路由 |
"/" |
路由路径 |
func(c echo.Context) error |
处理函数 |
c.String() |
返回字符串响应 |
http.StatusOK |
HTTP状态码200 |
3.3 启动服务器 #
go
e.Start(":8080")
在8080端口启动HTTP服务器。
四、多种响应类型 #
4.1 JSON响应 #
go
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
e := echo.New()
e.GET("/json", func(c echo.Context) error {
user := User{
ID: 1,
Name: "张三",
}
return c.JSON(http.StatusOK, user)
})
e.Start(":8080")
}
测试:
bash
curl http://localhost:8080/json
{"id":1,"name":"张三"}
4.2 JSON数组响应 #
go
e.GET("/users", func(c echo.Context) error {
users := []User{
{ID: 1, Name: "张三"},
{ID: 2, Name: "李四"},
{ID: 3, Name: "王五"},
}
return c.JSON(http.StatusOK, users)
})
4.3 HTML响应 #
go
e.GET("/html", func(c echo.Context) error {
html := `<html>
<head><title>Hello</title></head>
<body><h1>Hello, Echo!</h1></body>
</html>`
return c.HTML(http.StatusOK, html)
})
4.4 文件响应 #
go
e.GET("/file", func(c echo.Context) error {
return c.File("static/hello.txt")
})
4.5 附件下载 #
go
e.GET("/download", func(c echo.Context) error {
return c.Attachment("files/report.pdf", "report.pdf")
})
4.6 重定向 #
go
e.GET("/redirect", func(c echo.Context) error {
return c.Redirect(http.StatusFound, "/json")
})
4.7 无内容响应 #
go
e.DELETE("/users/:id", func(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
})
五、多路由示例 #
5.1 完整示例 #
go
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", home)
e.GET("/users", getUsers)
e.GET("/users/:id", getUser)
e.POST("/users", createUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)
e.Start(":8080")
}
func home(c echo.Context) error {
return c.String(http.StatusOK, "Welcome to Echo!")
}
func getUsers(c echo.Context) error {
return c.JSON(http.StatusOK, []map[string]interface{}{
{"id": 1, "name": "张三"},
{"id": 2, "name": "李四"},
})
}
func getUser(c echo.Context) error {
id := c.Param("id")
return c.JSON(http.StatusOK, map[string]string{
"id": id,
"name": "用户" + id,
})
}
func createUser(c echo.Context) error {
type User struct {
Name string `json:"name"`
}
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusCreated, map[string]string{
"id": "3",
"name": u.Name,
})
}
func updateUser(c echo.Context) error {
id := c.Param("id")
type User struct {
Name string `json:"name"`
}
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusOK, map[string]string{
"id": id,
"name": u.Name,
})
}
func deleteUser(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
5.2 测试API #
bash
curl http://localhost:8080/
curl http://localhost:8080/users
curl http://localhost:8080/users/1
curl -X POST -H "Content-Type: application/json" -d '{"name":"王五"}' http://localhost:8080/users
curl -X PUT -H "Content-Type: application/json" -d '{"name":"赵六"}' http://localhost:8080/users/1
curl -X DELETE http://localhost:8080/users/1
六、处理函数 #
6.1 匿名函数 #
go
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello")
})
6.2 命名函数 #
go
func hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello")
}
e.GET("/", hello)
6.3 方法绑定 #
go
type Handler struct{}
func (h *Handler) Hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello")
}
func main() {
e := echo.New()
h := &Handler{}
e.GET("/", h.Hello)
e.Start(":8080")
}
6.4 函数返回 #
go
func helloHandler(msg string) echo.HandlerFunc {
return func(c echo.Context) error {
return c.String(http.StatusOK, msg)
}
}
e.GET("/", helloHandler("Hello"))
e.GET("/hi", helloHandler("Hi"))
七、路由参数 #
7.1 路径参数 #
go
e.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
return c.String(http.StatusOK, "User ID: "+id)
})
7.2 查询参数 #
go
e.GET("/search", func(c echo.Context) error {
q := c.QueryParam("q")
page := c.QueryParam("page")
return c.String(http.StatusOK, "Search: "+q+", Page: "+page)
})
测试:
bash
curl "http://localhost:8080/search?q=echo&page=1"
Search: echo, Page: 1
7.3 表单参数 #
go
e.POST("/login", func(c echo.Context) error {
username := c.FormValue("username")
password := c.FormValue("password")
return c.String(http.StatusOK, "Login: "+username)
})
测试:
bash
curl -X POST -d "username=admin&password=123456" http://localhost:8080/login
Login: admin
八、请求头处理 #
8.1 获取请求头 #
go
e.GET("/headers", func(c echo.Context) error {
auth := c.Request().Header.Get("Authorization")
contentType := c.Request().Header.Get("Content-Type")
return c.JSON(http.StatusOK, map[string]string{
"authorization": auth,
"content-type": contentType,
})
})
8.2 设置响应头 #
go
e.GET("/custom-header", func(c echo.Context) error {
c.Response().Header().Set("X-Custom-Header", "value")
return c.String(http.StatusOK, "OK")
})
九、错误处理 #
9.1 返回错误 #
go
e.GET("/error", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "参数错误")
})
9.2 自定义错误页面 #
go
e.HTTPErrorHandler = func(err error, c echo.Context) {
code := http.StatusInternalServerError
if he, ok := err.(*echo.HTTPError); ok {
code = he.Code
}
c.HTML(code, fmt.Sprintf("<h1>Error %d</h1>", code))
}
十、优雅关闭 #
10.1 使用信号 #
go
package main
import (
"context"
"net/http"
"os"
"os/signal"
"time"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
go func() {
if err := e.Start(":8080"); err != nil && err != http.ErrServerClosed {
e.Logger.Fatal("shutting down the server")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := e.Shutdown(ctx); err != nil {
e.Logger.Fatal(err)
}
}
10.2 关闭流程 #
text
1. 收到中断信号 (Ctrl+C)
2. 停止接受新请求
3. 等待现有请求完成
4. 关闭服务器
十一、完整示例 #
go
package main
import (
"context"
"net/http"
"os"
"os/signal"
"time"
"github.com/labstack/echo/v4"
)
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, Response{
Code: 0,
Message: "success",
Data: "Hello, Echo!",
})
})
e.GET("/health", func(c echo.Context) error {
return c.JSON(http.StatusOK, Response{
Code: 0,
Message: "healthy",
})
})
go func() {
if err := e.Start(":8080"); err != nil && err != http.ErrServerClosed {
e.Logger.Fatal("shutting down the server")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := e.Shutdown(ctx); err != nil {
e.Logger.Fatal(err)
}
}
十二、总结 #
第一个应用要点:
| 概念 | 说明 |
|---|---|
| Echo实例 | echo.New() 创建应用 |
| 路由 | e.GET/POST/PUT/DELETE 注册路由 |
| Context | 封装请求和响应 |
| 响应类型 | JSON、HTML、String、File等 |
| 参数获取 | Param、QueryParam、FormValue |
| 优雅关闭 | 监听信号,调用Shutdown |
准备好学习应用结构了吗?让我们进入下一章!
最后更新:2026-03-28