上下文(Context)

Context将net/http的*RequestResponseWriter对象及其对应的方法封装到单个对象中,方便调用处理请求和响应的方法。

Field

名字 类型 描述
Request *http.Request 原生net/http的 *Request对象
ResponseWriter http.ResponseWriter 原生net/http的ResponseWriter对象
Method string http请求方式
URL *url.URL http请求的URL对象
Path string http请求的路径
Header http.Header http请求头部
Keys map[string]interface{} 主要用于中间件之间数据传递,通过GetSet方法使用
Handled bool 是否绕过goa的响应处理

Next

Next() 用于调用下一个中间件。

不同于koajs,Next方法写在了Context对象中,koajs的next()实际上是dispatch(i + 1),我们这样做的好处是可以节省dispatch函数传递带来的内存占用,更加高效的同时也可以让代码更加简洁。

// next() 这种方法在v0.4.0移除
app.Use(func(c *goa.Context, next func()) {
  // do sth
  next()
  // do sth
})

// c.Next()
app.Use(func(c *goa.Context) {
  // do sth
  c.Next()
  // do sth
})

当应用程序中绑定了多个中间件,除了最后一个中间件,c.Next()是必须调用的,否则goa只会执行第一个中间件。

app.Use(func(c *goa.Context) {
  fmt.Println(1)
  c.Next()
  fmt.Println(6)
})
app.Use(func(c *goa.Context) {
  fmt.Println(2)
  c.Next()
  fmt.Println(5)
})
app.Use(func(c *goa.Context) {
  fmt.Println(3)
  //c.Next() 此处可以省略c.Next()
  fmt.Println(4)
})

如果这是你第一次接触中间件,查看更多关于中间件

Set

Set(key string, value interface{}) 设定Keys。

Get

Get(key string) (value interface{}, exists bool) 获取指定Keys。

c.Set("key", "value")
value := c.Get("key").(string)

Query

Query(key string) (value string) 获取query指定key的value,若key不存在则返回""。

若Query复杂或需要类型转换,推荐使用ParseQuery

GetQuery

GetQuery(key string) (value string, exists bool)Query, 额外返回是否存在。

GetQueryArray

GetQueryArray(key string) ((value []string, exists bool) 获取query指定key的value数组和是否存在。

PostForm

PostForm(key string) (value string) 获取query指定key的value,若key不存在则返回""。

若form复杂或需要类型转换,推荐使用ParseForm

FormFile

FormFile(name string) (multipart.File, *multipart.FileHeader, error)c.Request.FormFile

Param

Param(key string) (value string) 获取路由中的参数,若不存在则返回""。

需配合router或其他路由中间件使用:

r := router.New()
r.GET("/example/:key", func(c *goa.Context) {
  key := c.Param("key")
  ...
})

ParseJSON

ParseJSON(pointer interface{}) error 解析请求body中的json,pointer必须为指针。

type Person struct {
  Name    string `json:"name"`
  Age     int    `json:"age"`
  Married bool   `json:"-"` // "-"为忽略
}

p := &Person{}
c.ParseJSON(p)
...

ParseXML

ParseXML(pointer interface{}) error 解析请求body中的xml。同ParseJSON

ParseString

ParseString() (string, error) 读取请求的body。

ParseQuery

ParseQuery(pointer interface{}) error 解析Query为结构体。若需要使用tag,tag名为query。

type Person struct {
  Name    string `query:"name"`
  Age     int    `query:"age"`
  Married bool   `query:"-"` // "-"为忽略
}

p := &Person{}
c.ParseQuery(p)

ParseForm

ParseForm(pointer interface{}) error 解析form为结构体,标签名为form。同ParseQuery

Cookie(name string) (string, error) 解析请求中携带的cookie,若对应名称的cookie 不存在则返回ErrNoCookie

SetCookie

SetCookie(cookie *http.Cookie) 设定cookie,需使用http包。

  c.SetCookie(&http.Cookie{
    Name:     "user",
    Value:    "goa",
    MaxAge:   1,
    Path:     "/",
    Domain:   "localhost",
    Secure:   true,
    HttpOnly: true,
  })

Status

Status(code int) 设置http状态码。

当没设定状态码时,若正常响应,则会自动设定为200,否则默认为404。

GetStatus

GetStatus() (code int) 获取当前设定的状态码,不一定是最后响应的状态码, 再次设定状态码或者 c.Error(...) 都可以改变最后响应的状态码。

JSON

JSON(json interface{}) 响应json数据,会自动响应200状态码、自动设置http响应头部的Content-Type

type obj struct {
  Key string `json:"key"`
}
o := obj{
  Key: "value",
}

c.JSON(o)

还可以通过goa.M使用,实际上goa.M只是map[string]interface{}

c.JSON(goa.M{
  "key": "value",
})

XML

XML(xml interface{}) 响应xml数据,同JSON

String

String(str string) 响应字符串,http头部的Content-Type会被设置为text/plain; charset=utf-8

HTML

HTML(html string) 响应html,与c.String类似,但http头部的Content-Type会被设置为text/html; charset=utf-8

Redirect

Redirect(code int, url string) 重定向,会绕过goa的响应处理。

SetHeader

SetHeader(key string, value string) 设置http响应头部。

Error

Error(code int, msg string) 抛出http错误,并且会被goa捕捉来响应错误。

c.Error(500, http.StatusText(500))
// 在这之后的操作都会跳过
c.Status(200) // 这不会起作用。
c.String("Hello World") // 这也不会起作用。