Context上下文 #

一、Context概述 #

Context是Echo框架的核心对象,封装了HTTP请求和响应的所有信息。

1.1 Context结构 #

go
type Context interface {
    Request() *http.Request
    Response() *http.Response
    ...
}

1.2 Context作用 #

text
┌─────────────────────────────────────────────────────────┐
│                    Context作用                           │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  请求信息                                                │
│  ├── 获取请求参数                                        │
│  ├── 获取请求头                                          │
│  ├── 获取请求体                                          │
│  └── 获取Cookie                                          │
│                                                         │
│  响应操作                                                │
│  ├── 设置响应内容                                        │
│  ├── 设置响应头                                          │
│  ├── 设置Cookie                                          │
│  └── 设置状态码                                          │
│                                                         │
│  数据传递                                                │
│  ├── 中间件间传递数据                                    │
│  └── 存储请求相关数据                                    │
│                                                         │
└─────────────────────────────────────────────────────────┘

二、请求信息 #

2.1 获取Request对象 #

go
e.GET("/", func(c echo.Context) error {
    req := c.Request()
    
    method := req.Method
    url := req.URL.String()
    host := req.Host
    proto := req.Proto
    
    return c.JSON(http.StatusOK, map[string]string{
        "method": method,
        "url":    url,
        "host":   host,
        "proto":  proto,
    })
})

2.2 获取请求头 #

go
e.GET("/headers", func(c echo.Context) error {
    auth := c.Request().Header.Get("Authorization")
    contentType := c.Request().Header.Get("Content-Type")
    userAgent := c.Request().UserAgent()
    
    return c.JSON(http.StatusOK, map[string]string{
        "authorization": auth,
        "content-type":  contentType,
        "user-agent":    userAgent,
    })
})

2.3 获取客户端信息 #

go
e.GET("/client", func(c echo.Context) error {
    realIP := c.RealIP()
    remoteAddr := c.Request().RemoteAddr
    scheme := c.Scheme()
    isTLS := c.IsTLS()
    
    return c.JSON(http.StatusOK, map[string]interface{}{
        "realIP":     realIP,
        "remoteAddr": remoteAddr,
        "scheme":     scheme,
        "isTLS":      isTLS,
    })
})

2.4 获取路径信息 #

go
e.GET("/path/*", func(c echo.Context) error {
    path := c.Path()
    param := c.Param("*")
    
    return c.JSON(http.StatusOK, map[string]string{
        "path":  path,
        "param": param,
    })
})

三、响应操作 #

3.1 获取Response对象 #

go
e.GET("/", func(c echo.Context) error {
    res := c.Response()
    
    res.Header().Set("X-Custom", "value")
    res.WriteHeader(http.StatusOK)
    
    return nil
})

3.2 设置响应头 #

go
e.GET("/headers", func(c echo.Context) error {
    c.Response().Header().Set("X-Request-ID", "12345")
    c.Response().Header().Add("X-Custom", "value1")
    c.Response().Header().Add("X-Custom", "value2")
    
    return c.String(http.StatusOK, "OK")
})

3.3 设置状态码 #

go
e.GET("/status", func(c echo.Context) error {
    return c.String(http.StatusCreated, "Created")
})

四、参数获取 #

4.1 路径参数 #

go
e.GET("/users/:id", func(c echo.Context) error {
    id := c.Param("id")
    return c.String(http.StatusOK, "User ID: "+id)
})

4.2 查询参数 #

go
e.GET("/search", func(c echo.Context) error {
    q := c.QueryParam("q")
    page := c.QueryParam("page")
    
    return c.JSON(http.StatusOK, map[string]string{
        "q":    q,
        "page": page,
    })
})

4.3 表单参数 #

go
e.POST("/login", func(c echo.Context) error {
    username := c.FormValue("username")
    password := c.FormValue("password")
    
    return c.JSON(http.StatusOK, map[string]string{
        "username": username,
    })
})

4.4 绑定参数 #

go
type User struct {
    Name  string `json:"name" form:"name" query:"name"`
    Email string `json:"email" form:"email" query:"email"`
}

e.POST("/users", func(c echo.Context) error {
    u := new(User)
    if err := c.Bind(u); err != nil {
        return err
    }
    
    return c.JSON(http.StatusCreated, u)
})

五、Cookie操作 #

5.1 获取Cookie #

go
e.GET("/cookie", func(c echo.Context) error {
    cookie, err := c.Cookie("session")
    if err != nil {
        return c.String(http.StatusOK, "No cookie")
    }
    
    return c.String(http.StatusOK, "Session: "+cookie.Value)
})

5.2 设置Cookie #

go
e.GET("/set-cookie", func(c echo.Context) error {
    cookie := &http.Cookie{
        Name:     "session",
        Value:    "abc123",
        Path:     "/",
        HttpOnly: true,
        Secure:   true,
        MaxAge:   3600,
    }
    
    c.SetCookie(cookie)
    
    return c.String(http.StatusOK, "Cookie set")
})

5.3 删除Cookie #

go
e.GET("/delete-cookie", func(c echo.Context) error {
    cookie := &http.Cookie{
        Name:   "session",
        Value:  "",
        Path:   "/",
        MaxAge: -1,
    }
    
    c.SetCookie(cookie)
    
    return c.String(http.StatusOK, "Cookie deleted")
})

5.4 获取所有Cookie #

go
e.GET("/cookies", func(c echo.Context) error {
    cookies := c.Cookies()
    
    result := make(map[string]string)
    for _, cookie := range cookies {
        result[cookie.Name] = cookie.Value
    }
    
    return c.JSON(http.StatusOK, result)
})

六、数据存储 #

6.1 Set/Get #

go
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        user := &User{ID: 1, Name: "张三"}
        c.Set("user", user)
        return next(c)
    }
}

e.GET("/profile", func(c echo.Context) error {
    user := c.Get("user").(*User)
    return c.JSON(http.StatusOK, user)
})

6.2 类型安全获取 #

go
func getUser(c echo.Context) *User {
    if user, ok := c.Get("user").(*User); ok {
        return user
    }
    return nil
}

6.3 存储多个值 #

go
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        c.Set("requestID", uuid.New().String())
        c.Set("startTime", time.Now())
        c.Set("userID", "123")
        
        return next(c)
    }
})

七、响应方法 #

7.1 String响应 #

go
e.GET("/", func(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
})

7.2 JSON响应 #

go
e.GET("/json", func(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]string{
        "message": "Hello",
    })
})

7.3 JSONP响应 #

go
e.GET("/jsonp", func(c echo.Context) error {
    callback := c.QueryParam("callback")
    return c.JSONP(http.StatusOK, callback, map[string]string{
        "message": "Hello",
    })
})

7.4 XML响应 #

go
e.GET("/xml", func(c echo.Context) error {
    return c.XML(http.StatusOK, map[string]string{
        "message": "Hello",
    })
})

7.5 HTML响应 #

go
e.GET("/html", func(c echo.Context) error {
    return c.HTML(http.StatusOK, "<h1>Hello, World!</h1>")
})

7.6 文件响应 #

go
e.GET("/file", func(c echo.Context) error {
    return c.File("static/hello.txt")
})

7.7 附件下载 #

go
e.GET("/download", func(c echo.Context) error {
    return c.Attachment("files/report.pdf", "report.pdf")
})

7.8 内联文件 #

go
e.GET("/inline", func(c echo.Context) error {
    return c.Inline("files/document.pdf", "document.pdf")
})

7.9 Blob响应 #

go
e.GET("/blob", func(c echo.Context) error {
    data := []byte("Hello, World!")
    return c.Blob(http.StatusOK, "text/plain", data)
})

7.10 Stream响应 #

go
e.GET("/stream", func(c echo.Context) error {
    reader := strings.NewReader("Hello, World!")
    return c.Stream(http.StatusOK, "text/plain", reader)
})

7.11 重定向 #

go
e.GET("/redirect", func(c echo.Context) error {
    return c.Redirect(http.StatusFound, "/new-path")
})

7.12 无内容 #

go
e.DELETE("/users/:id", func(c echo.Context) error {
    return c.NoContent(http.StatusNoContent)
})

八、路径和路由 #

8.1 获取路径 #

go
e.GET("/api/users/:id", func(c echo.Context) error {
    path := c.Path()
    return c.String(http.StatusOK, "Path: "+path)
})

输出:

text
Path: /api/users/:id

8.2 路由名称 #

go
e.GET("/users/:id", func(c echo.Context) error {
    return c.String(http.StatusOK, "User")
}).Name = "user.get"

e.GET("/url", func(c echo.Context) error {
    url := c.Echo().Reverse("user.get", "123")
    return c.String(http.StatusOK, "URL: "+url)
})

输出:

text
URL: /users/123

九、Context扩展 #

9.1 自定义Context #

go
type CustomContext struct {
    echo.Context
}

func (cc *CustomContext) Foo() string {
    return "foo"
}

func (cc *CustomContext) Bar() string {
    return "bar"
}

func main() {
    e := echo.New()
    
    e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
            cc := &CustomContext{c}
            return next(cc)
        }
    })
    
    e.GET("/", func(c echo.Context) error {
        cc := c.(*CustomContext)
        return c.String(http.StatusOK, cc.Foo())
    })
    
    e.Start(":8080")
}

9.2 Context方法扩展 #

go
func (cc *CustomContext) GetUserID() string {
    if userID, ok := cc.Get("userID").(string); ok {
        return userID
    }
    return ""
}

func (cc *CustomContext) IsAuthenticated() bool {
    return cc.Get("user") != nil
}

十、完整示例 #

go
package main

import (
    "net/http"
    "time"
    "github.com/google/uuid"
    "github.com/labstack/echo/v4"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func main() {
    e := echo.New()
    
    e.Use(contextMiddleware)
    
    e.GET("/", home)
    e.GET("/info", info)
    e.GET("/cookies", handleCookies)
    e.POST("/users", createUser)
    
    e.Logger.Fatal(e.Start(":8080"))
}

func contextMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        c.Set("requestID", uuid.New().String())
        c.Set("startTime", time.Now())
        
        return next(c)
    }
}

func home(c echo.Context) error {
    requestID := c.Get("requestID").(string)
    
    c.Response().Header().Set("X-Request-ID", requestID)
    
    return c.JSON(http.StatusOK, map[string]string{
        "message":   "Welcome",
        "requestID": requestID,
    })
}

func info(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]interface{}{
        "method":    c.Request().Method,
        "path":      c.Path(),
        "realIP":    c.RealIP(),
        "scheme":    c.Scheme(),
        "isTLS":     c.IsTLS(),
        "requestID": c.Get("requestID"),
    })
}

func handleCookies(c echo.Context) error {
    if c.Request().Method == http.MethodGet {
        cookie, err := c.Cookie("visit")
        if err != nil {
            cookie = &http.Cookie{
                Name:    "visit",
                Value:   "1",
                Expires: time.Now().Add(24 * time.Hour),
            }
            c.SetCookie(cookie)
            return c.String(http.StatusOK, "First visit")
        }
        return c.String(http.StatusOK, "Visit count: "+cookie.Value)
    }
    return c.NoContent(http.StatusMethodNotAllowed)
}

func createUser(c echo.Context) error {
    u := new(User)
    if err := c.Bind(u); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, err.Error())
    }
    
    u.ID = 1
    
    return c.JSON(http.StatusCreated, u)
}

十一、总结 #

Context方法要点:

方法 用途
Request() 获取请求对象
Response() 获取响应对象
Param() 获取路径参数
QueryParam() 获取查询参数
FormValue() 获取表单参数
Bind() 绑定数据
Cookie() 获取Cookie
SetCookie() 设置Cookie
Set() 存储数据
Get() 获取数据
JSON() JSON响应
String() 字符串响应
HTML() HTML响应

准备好学习请求处理了吗?让我们进入下一章!

最后更新:2026-03-28