http.Handlefunc does not like methods?

1,974 views
Skip to first unread message

John

unread,
Jan 8, 2012, 2:33:50 PM1/8/12
to golang-nuts
So, I'm trying to do something slightly different from the example on
http.Handlefunc, by providing a method instead of a function, but I
always get:

"method m.(*mainServer).SayHello is not an expression, must be called"

Is there a way to do this?

=============
package main

import (
"http"
"fmt"
)

type mainServer struct {
}

func (m *mainServer) SayHello(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Hello")
}

func main() {
m := new(mainServer)
http.HandleFunc("/", m.SayHello)
http.ListenAndServe(":3457", nil)
}

David Symonds

unread,
Jan 8, 2012, 5:41:36 PM1/8/12
to John, golang-nuts
Go doesn't curry functions or methods that way. You could do something like

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
m.SayHello(w, r) })

or you could rename SayHello to ServerHTTP, and then just

http.Handle("/", m)


Dave.

John

unread,
Jan 8, 2012, 5:53:54 PM1/8/12
to golang-nuts
I'm slow, so this is probably going to be like explaining to a 5 year
old, so bear with me.

I'm not sure what "curry" functions means. I see wikipedia talking
about it, turning a function with multiple arguments into a chain of
functions. But looking at the page yields very little to my brain.

In your example, I would just pass a closure, seems reasonable.

I'm not sure why changing SayHello to ServerHTTP works....

I guess what I need to know is why say if I did this will it work vs.
using the method on an object:

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello")
}

func main() {
http.HandleFunc("/", handler)
}

Thanks David. Again, your helpful as always.

--John

David Symonds

unread,
Jan 8, 2012, 8:53:45 PM1/8/12
to John, golang-nuts
On Mon, Jan 9, 2012 at 9:53 AM, John <johns...@gmail.com> wrote:

> I'm not sure what "curry" functions means.  I see wikipedia talking
> about it, turning a function with multiple arguments into a chain of
> functions.  But looking at the page yields very little to my brain.

Yes, that is roughly right. In your original code, you put a method on
a type, and you can only normally ([1]) call methods when you have an
object of that type. You were telling the http package to run a
method, but the package doesn't know the type or have an object to
call that method.

> In your example, I would just pass a closure, seems reasonable.
>
> I'm not sure why changing SayHello to ServerHTTP works....

It's not just renaming, it's also changing which function in the http
package you're calling. http.HandleFunc takes a function with a
particular signature, whereas http.Handle takes an *interface*. Have
you learned about interfaces yet? If not, you probably want to go do
that; [2] might be a good start.


Dave.


[1] There's an exception, but it's not useful to you here. c.f.
http://golang.org/doc/go_spec.html#Method_expressions
[2] http://golang.org/doc/effective_go.html#interfaces_and_types and
http://tour.golang.org/#49

Dougx

unread,
Feb 18, 2013, 4:01:02 AM2/18/13
to golan...@googlegroups.com
This original thread was ages ago, but I thought I'd drop this here for the next person who comes hunting. You can use reflection to achieve this, like this:

package main 

import "fmt"
import r "reflect"

type Weird struct {
  Instance interface{}
  Call interface{}
}

func main() {
  var core = make(map[string] Weird)

  core["XXX"] = Weird { &XXX{}, (*XXX).thing }
  core["YYY"] = Weird { &YYY{}, (*YYY).thing }

  x := core["XXX"]; invoke(x.Call, x.Instance, 111);
  y := core["YYY"]; invoke(y.Call, y.Instance, 222);
}

func invoke(call interface{}, instance interface{}, arg int) {
  var v = r.ValueOf(call)
  var args = []r.Value { r.ValueOf(instance), r.ValueOf(arg) }
  v.Call(args)
}

type XXX struct {}
func (self *XXX) thing(x int) {
  fmt.Printf("XXX: %d\n", x)
}

type YYY struct {}
func (self *YYY) thing(x int) {
  fmt.Printf("YYY: %d\n", x)
}

Specifically, this approach does let you handle http handlers that are methods and attached to instances (eg. controller pattern).

~
Doug.
Reply all
Reply to author
Forward
0 new messages