<pre><code>package main
import "fmt"
type Fn func(string)(int)
func (f Fn) glork(s string) int {
fmt.Printf("Reached glork(%q)\n", s)
x := f(s)
return x
}
func example(s string) int {
fmt.Printf("Reached example(%q)\n", s)
return len(s)
}
func main() {
var fx Fn
fx = example // This assignment makes it work.
n := fx.glork("calling glork")
fmt.Printf("Got back %d from calling fx.glork()\n", n)
}
</code></pre>
<hr/>**评论:**<br/><br/>robpike: <pre><p>See the explanation of HandlerFunc in <a href="https://golang.org/doc/effective_go.html">https://golang.org/doc/effective_go.html</a>, which is just <a href="https://golang.org/pkg/net/http/#HandlerFunc">https://golang.org/pkg/net/http/#HandlerFunc</a>.</p></pre>IanS_5: <pre><p>That's an interesting way to implement it. I kinda want to try something like that now :P</p></pre>chmikes: <pre><p>What is the purpose of this construct ? No web programming tutorial or book I could find explains the purpose of HandlerFunc. </p></pre>cavaliercoder: <pre><p>In the context of HTTP handlers, one benefit is that you can implement the <code>http.Handler</code> interface simply by wrapping a function with <code>HandlerFunc</code>. Alternatively, you would have to define a struct (probably empty) and adorn it with your function implementation.</p>
<p>You can also create your own handler call signatures (maybe to include request, response writer and a db connection or next middleware) and conveniently wrap them for consumption by the http stdlib. Negroni does this. <a href="https://github.com/urfave/negroni">https://github.com/urfave/negroni</a></p></pre>mcouturier: <pre><p>If the interface you want to implement only has one function and likely no state, instead of defining an empty struct that implement that interface, a HandlerFunc is provided to implement that interface solely by providing a function. This is a time saving technique to implement an interface that has one function using a function.</p>
<p>I know I said function a lot :)</p></pre>earthboundkid: <pre><p>It lets you decide if you want to use a type+method to implement the <code>ServeHTTP</code> method and thereby implement the <code>Handler</code> interface, or just make a quick function to implement it. It adds flexibility to the architecture.</p></pre>lattakia: <pre><p>Are you the Rob Pike that I think you are ?</p></pre>eggnot: <pre><p>Idea: create grammar/vocabulary profile based on known Rob Pike sources, then plug in comment history of this account to generate confidence rating. Even if it's not Rob, and they're just really good at pretending to be him, you can just act like it is and refer back to your confidence rating if that's ever called into question.</p>
<p>Who needs truth when you have math?</p></pre>TangZero: <pre><p>Yes we can!</p></pre>ianbezo: <pre><p>Yes. For the full picture this example is missing an interface because this is especially useful in combination with a <strong>single function interface</strong> (like http.Handler). With this pattern in order to write various handlers implementations we don't need to create named struct for every case. It's enough to write a function and wrap it in the adapter (like http.HanderFunc, in the example above Fn).</p></pre>gentleman_tech: <pre><p>functions are first-class types. No different from strings, integers, structs, or maps. You can add methods to all of them, too :)</p></pre>jocull: <pre><p>Is they considered dirty, like changing the primitive prototypes in JS?</p></pre>Redundancy_: <pre><p>You can't do </p>
<pre><code>func (s string) Foo() {
}
</code></pre>
<p>You have to have a local type to do it, so you're never adding methods a type that's not from your package.
What you can do is create a new type that's analagous:</p>
<pre><code>type Goo string
func (s Goo) Foo() {
//valid
}
</code></pre>
<p>So there's nothing dirty involved.</p></pre>gentleman_tech: <pre><p>what they said :)</p>
<p>in fact, this is generally looked on as A Good Thing.</p></pre>lattakia: <pre><p>So creating new types with <code>type</code> is not just aliasing ?</p></pre>carsncode: <pre><p>Not <em>just</em> aliasing, no. When you create a new type this way, any methods that exist for the base type are not available on the new type, but new methods can be attached to the new type. There's also no implicit casting, only explicit casting, making it even less alias-like, and making it useful for things like enumerations.</p></pre>Redundancy_: <pre><p><a href="https://golang.org/ref/spec#Type_declarations" rel="nofollow">https://golang.org/ref/spec#Type_declarations</a></p>
<p>It an take a bit of work to understand clearly, but:</p>
<pre><code>type A string
func (a A) Foo() {}
func S(s string){}
type B A
// B does not have Foo()
// You cannot use B in S(...)
// You CAN convert B to string or A
</code></pre></pre>dilap: <pre><p>Nope, it creates a new type. This is actually handy for getting type errors on purpose when mixing up types.</p>
<p>E.g., </p>
<blockquote>
<p>type FooId uint32</p>
</blockquote>
<p>or whatever.</p>
<p>The next version of Go will add aliases:</p>
<blockquote>
<p>type OtherInt = int</p>
</blockquote>
<p>OtherInt and int will be two different ways to write down the same type.</p></pre>bupku5: <pre><p>yes this is basically how http handlers are structured...it really feels like this feature was added to address some brittleness in the applicability of the handler interface</p></pre>robpike: <pre><p>Not at all. It's not even a feature, just something that fell out of an orthogonal language design. Any concrete type can have a method. A function is a concrete type. Therefore functions can have methods.</p></pre>negbie: <pre><p>Not so unusual when u are working with json and you want to implement the marshaller for your own types.</p>
<p>func (y *YourType) MarshalJSON() ([]byte, error) { </p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传