如何访问接口的属性

huangapple go评论84阅读模式
英文:

How to access attribute of interface

问题

我的翻译如下:

我的意图是在两个响应结构体的头部和主体中都使用HTTP状态码。但是,为了避免冗余,我不想在函数参数和结构体中都设置状态码两次。

JSON()函数的参数response是一个接口,允许接受两个结构体。编译器抛出以下异常:

response.Status undefined (type interface {} has no field or method Status)

这是因为响应字段不能有状态属性。有没有其他方法可以避免设置状态码两次?

type Response struct {
    Status int         `json:"status"`
    Data   interface{} `json:"data"`
}

type ErrorResponse struct {
    Status int      `json:"status"`
    Errors []string `json:"errors"`
}

func JSON(rw http.ResponseWriter, response interface{}) {
    payload, _ := json.MarshalIndent(response, "", "    ")
    rw.WriteHeader(response.Status)
    ...
}
英文:

It was my intention to use the HTTP status codes both in the header and the body of the two response structs. Bu that without setting the status code twice as function parameter and again for the struct to avoid redundancy.

The parameter response of JSON() is an interface to allow both structs to be accepted. The compiler throws the following exception:

response.Status undefined (type interface {} has no field or method Status)

because the response field must not have a status attribute. Is there an alternative way to avoid setting the status code twice?

<!-- language: go-lang -->

type Response struct {
	Status int         `json:&quot;status&quot;`
	Data   interface{} `json:&quot;data&quot;`
}

type ErrorResponse struct {
	Status int      `json:&quot;status&quot;`
	Errors []string `json:&quot;errors&quot;`
}

func JSON(rw http.ResponseWriter, response interface{}) {
	payload, _ := json.MarshalIndent(response, &quot;&quot;, &quot;    &quot;)
	rw.WriteHeader(response.Status)
	...
}

答案1

得分: 5

在Go语言中,rw.WriteHeader(response.Status)中的response类型是interface{}。你需要显式断言底层结构的类型,然后访问字段:

func JSON(rw http.ResponseWriter, response interface{}) {
    payload, _ := json.MarshalIndent(response, "", "    ")
    switch r := response.(type) {
    case ErrorResponse:
        rw.WriteHeader(r.Status)
    case Response:
        rw.WriteHeader(r.Status) 
    }
    ...
}

然而,更好且更常用的方法是为你的响应定义一个公共接口,该接口具有获取响应状态的方法:

type Statuser interface {
    Status() int
}

// 你需要重命名字段以避免名称冲突。
func (r Response) Status() int { return r.ResStatus }
func (r ErrorResponse) Status() int { return r.ResStatus }

func JSON(rw http.ResponseWriter, response Statuser) {
    payload, _ := json.MarshalIndent(response, "", "    ")
    rw.WriteHeader(response.Status())
    ...
}

在我看来,将Response重命名为DataResponse,将ResponseInterface重命名为Response会更好。

英文:

The type response in rw.WriteHeader(response.Status) is interface{}. In Go, you need to explicitly assert the type of the underlying struct and then access the field:

func JSON(rw http.ResponseWriter, response interface{}) {
    payload, _ := json.MarshalIndent(response, &quot;&quot;, &quot;    &quot;)
    switch r := response.(type) {
    case ErrorResponse:
        rw.WriteHeader(r.Status)
    case Response:
        rw.WriteHeader(r.Status) 
    }
    ...
}

A better and the preferred way to do this however is to define a common interface for your responses, that has a method for getting the status of the response:

type Statuser interface {
    Status() int
}

// You need to rename the fields to avoid name collision.
func (r Response) Status() int { return r.ResStatus }
func (r ErrorResponse) Status() int { return r.ResStatus }

func JSON(rw http.ResponseWriter, response Statuser) {
    payload, _ := json.MarshalIndent(response, &quot;&quot;, &quot;    &quot;)
    rw.WriteHeader(response.Status())
    ...
}

And it's better to rename Response to DataResponse and ResponseInterface to Response, IMO.

答案2

得分: 1

接口没有属性,所以你需要从接口中提取结构体。为了做到这一点,你可以使用类型断言。

if response, ok := response.(ErrorResponse); ok {
    rw.WriteHeader(response.Status)
    ...
}

更多信息请参考 类型断言

英文:

Interfaces don't have attributes, so you need to extract the struct from the interface. To do this you use a type assertion

if response, ok := response.(ErrorResponse); ok {
    rw.WriteHeader(response.Status)
    ...

huangapple
  • 本文由 发表于 2015年5月21日 01:32:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/30356592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定