Reputation: 77
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.
Upvotes: 3
Views: 132
Reputation: 43949
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.
Upvotes: 2
Reputation: 4826
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?"
Upvotes: 3
Reputation: 57757
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}
Upvotes: 1