指向结构体的指针满足接口。

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

Pointer to struct satisfy interface

问题

我扫描了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}
}

这样做的原因是什么?然而,该框架在渲染JSON时返回的是一个结构体值,而不是结构体指针:

type RenderJsonResult struct {
    obj      interface{}
    callback string
}

// 使用encoding/xml.Marshal将XML返回给客户端。
func (c *Controller) RenderXml(o interface{}) Result {
    return RenderXmlResult{o}
}

我似乎无法理解这些微妙的差异。

英文:

I scanned the Revel framework's Go code and it seems that pointers satisfy interface requirements. See the snippets below.

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}
}

What's the reasoning behind this? The framework is returning a struct value instead of a struct pointer for rendering JSON, though:

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}
}

I can't seem to grasp the subtle (?) differences.

答案1

得分: 3

是的,指针隐式地具有它们所指向类型的所有方法。请参阅FAQ部分中的"为什么T和*T具有不同的方法集?""值或指针上的方法?"

英文:

Yes, pointers implicitly have all the methods of the type they point to. See the FAQ sections "Why do T and *T have different method sets?" and "Methods on values or pointers?"

答案2

得分: 2

与类型相关联的方法也可以在指向该类型的指针上使用。所以如果r是一个*RenderTextResult变量,那么r.Apply(...)等同于(*r).Apply()

在大多数情况下,Apply方法的行为与直接与*RenderTextResult相关联的方法相似,尽管它无法修改结构体的内容,因为它接收的是结构体的副本而不是指向原始结构体的指针。

这意味着可以使用RenderTextResult上的方法来使*RenderTextResult满足Result接口。

英文:

Methods associated with a type are also available on pointers to that type. So if r is a *RenderTextResult variable, then r.Apply(...) is equivalent to (*r).Apply().

In most respects, the Apply method will act like any method associated with *RenderTextResult directly, although it won't be able to modify the contents of the struct, since it receives a copy of the struct rather than a pointer to the original.

This means that the methods on RenderTextResult can be used to let *RenderTextResult satisfy the Result interface.

答案3

得分: 1

任何命名类型都可以满足一个接口。无论类型是指针、通道还是函数值,只要它实现了接口要求的方法即可。

以下是一个满足接口的函数示例(play):

type Printer interface {
    Print(string)
}

type funcPrinter func() string

func (f funcPrinter) Print(s string) {
    fmt.Println(s + f())
}

这引出了一个问题,为什么要返回指针而不是值,或者反过来。如果你一直在传递对象,那么使用指针是一个好主意,因为它们始终具有固定的小长度,而不是所有的值。

以下代码将导致将结构体复制到调用者:

return RenderXmlResult{o}

而这个调用将返回指向堆中某个位置的结构体指针:

return &RenderXmlResult{o}
英文:

Any named type can satisfy an interface. It does not matter whether the type is a pointer, a channel or a function value as long as it implements the methods the interface demands.

Example of a function satisfying an interface (play):

type Printer interface {
	Print(string)
}

type funcPrinter func() string

func (f funcPrinter) Print(s string) { 
     fmt.Println(s + f()) 
}

This leaves the question why one would return a pointer rather than a value or vice versa.
If you pass objects around all the time then it is a good idea to use pointers as they are
always of a small fixed length instead of all the values.

The following line results in having the struct copied to the caller:

return RenderXmlResult{o}

While this call will return a pointer to the struct placed somewhere in the heap.

return &RenderXmlResult{o}

huangapple
  • 本文由 发表于 2013年12月13日 09:41:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/20557673.html
匿名

发表评论

匿名网友

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

确定