我扫描了Revel框架的Go代码,似乎指针满足了接口要求。请参阅下面的代码段。
type Result interface {
Apply(req *Request, resp *Response)
}
type RenderTextResult struct {
text string
}
func (r RenderTextResult) Apply(req *Request, resp *Response) {
resp.WriteHeader(http.StatusOK, "text/plain; charset=utf-8")
resp.Out.Write([]byte(r.text))
}
func (c *Controller) RenderText(text string, objs ...interface{}) Result {
finalText := text
if len(objs) > 0 {
finalText = fmt.Sprintf(text, objs...)
}
return &RenderTextResult{finalText}
}
这背后的原因是什么?该框架返回一个struct值而不是一个用于呈现JSON的struct指针,但是:
type RenderJsonResult struct {
obj interface{}
callback string
}
// Uses encoding/xml.Marshal to return XML to the client.
func (c *Controller) RenderXml(o interface{}) Result {
return RenderXmlResult{o}
}
我似乎无法理解微妙的(?)差异。
答案 0 :(得分:3)
是的,指针隐式具有它们指向的所有类型的方法。请参阅常见问题解答部分"Why do T and *T have different method sets?"和"Methods on values or pointers?"
答案 1 :(得分:2)
与类型相关的方法也可用于指向该类型的指针。因此,如果r
是*RenderTextResult
变量,则r.Apply(...)
相当于(*r).Apply()
。
在大多数方面,Apply
方法将像任何与*RenderTextResult
直接关联的方法一样,虽然它无法修改结构的内容,因为它接收到的副本struct而不是指向原始的指针。
这意味着RenderTextResult
上的方法可用于让*RenderTextResult
满足Result
界面。
答案 2 :(得分:1)
任何named type都可以满足接口。只要它实现了接口所需的方法,类型是指针,通道还是函数值都无关紧要。
满足接口(play)的函数示例:
type Printer interface {
Print(string)
}
type funcPrinter func() string
func (f funcPrinter) Print(s string) {
fmt.Println(s + f())
}
这就留下了为什么人们会返回一个指针而不是一个值,反之亦然。 如果你一直传递对象,那么最好使用指针 总是有一个小的固定长度而不是所有的值。
以下行导致将结构复制到调用者:
return RenderXmlResult{o}
虽然这个调用将返回一个指向放在堆中某处的struct的指针。
return &RenderXmlResult{o}