Call a Struct and it's method with the string name?

6,657 views
Skip to first unread message

nvcnvn

unread,
Nov 11, 2011, 8:52:35 PM11/11/11
to golang-nuts
I'm tring to call a class and its method with there name string.

*******************************************
type MyStruct struct {...............}

func (p *MyStruct) MyMethod {
println("My statement.");
}

CallFunc("MyStruct", "MyMethod");
//print out My statement."
*******************************************

Can some one show me somes ideas :)

P/s:
My aim is...build an simple MVC web application with GO (like ASP.NET
MVC or CodeIgniter in PHP....).
So my app will parse the URL (example.com/Structname/Methodname....)
in to separate strings ("Structname", "Methodname",..) after that put
it in to CallFunc().

If my plan is not efficient, can you give me the better way :D


Thanks all of you!

Anschel Schaffer-Cohen

unread,
Nov 11, 2011, 10:10:06 PM11/11/11
to golan...@googlegroups.com
You want the reflect package, and especially http://golang.org/pkg/reflect/#Value.MethodByName

nvcnvn

unread,
Nov 11, 2011, 11:17:51 PM11/11/11
to golang-nuts
So with http://golang.org/pkg/reflect/#Value.MethodByName do it need
an variable with MyStruct typed or not?

Eg:
*******************************************
type MyStruct struct {...............}
func (p *MyStruct) MyMethod {
println("My statement.");
}
func main()
{
var mys = MyStruct{};
mys.MyMethod();//print out
}
*******************************************
Not so sure but I thing that I can call MyMethod() with MethodByName()
only when "var mys = MyStruct{};" is it true?

Is there anything like StructByName()?

nvcnvn

unread,
Nov 12, 2011, 10:04:01 AM11/12/11
to golang-nuts
Can you give me an example of using that!?

On Nov 12, 10:10 am, Anschel Schaffer-Cohen <ansche...@gmail.com>
wrote:

nvcnvn

unread,
Nov 12, 2011, 4:12:21 AM11/12/11
to golang-nuts
Can you give me an example of using that function?

On 12 Tháng Mười Một, 10:10, Anschel Schaffer-Cohen

Kyle Lemons

unread,
Nov 14, 2011, 11:03:54 AM11/14/11
to nvcnvn, golang-nuts
Can you give me an example of using that function?

package main

import (
"fmt"
"reflect"
)

type Integer int
func (i *Integer) Add(delta int) {
*i += Integer(delta)
}

func main() {
i := Integer(0)
i.Add(1)
fmt.Println(i)
add := reflect.ValueOf(&i).MethodByName("Add")
add.Call([]reflect.Value{reflect.ValueOf(5)})
fmt.Println(i)
}

DEXTER

unread,
Mar 26, 2012, 6:49:25 AM3/26/12
to golan...@googlegroups.com, nvcnvn

Hi,
Can you help me with the similar, but I would like to pass struct to the function
ex:
func (i *Integer) Add(interface{}) {
    //
// *i += Integer(delta)
}

type Person struct {
  Name string
  Age int
}
func main() {
i := Integer(0)
i.Add(1)
        c = &Person{"Dexter",37}
fmt.Println(i)
add := reflect.ValueOf(&i).​MethodByName("Add")
add.Call(c)
}

How do I access the attributes of Person in the called function and how do I call the function MethodByName, with extra arguments?

Thanks
Dexter

ajventi

unread,
Mar 26, 2012, 7:16:43 AM3/26/12
to golang-nuts
Why not try a map of functions:

type methodMap map[string]func () string

var methods = methodMap{
"index": func () { ....},

DEXTER

unread,
Mar 26, 2012, 7:39:59 AM3/26/12
to golan...@googlegroups.com
Can you provide me with sample code ?

André Moraes

unread,
Mar 26, 2012, 8:01:24 AM3/26/12
to DEXTER, golan...@googlegroups.com, nvcnvn
> type Person struct {
>   Name string
>   Age int
> }
> func main() {
> i := Integer(0)
> i.Add(1)
>         c = &Person{"Dexter",37}
> fmt.Println(i)
> add := reflect.ValueOf(&i).MethodByName("Add")
> add.Call(c)
> }
>
> How do I access the attributes of Person in the called function and how do I

From the called function point of view, it's just another call. No
special treatment here. So you don't have to do nothing special in the
Add function.

This works because you called MethodByName on a reflect.Value and not
in a reflect.Type, this way, the receiver is already defined.

> call the function MethodByName, with extra arguments?

You don't.

The MethodByName return the pointer to the function (bound to the &i object).
You pass the parameters in the add.Call method.

See: http://weekly.golang.org/pkg/reflect/#Value.Call

For each argument you need to pass, you add them to a []reflect.Value
slice and them pass the slice to add.Call

pseudo-code:

add := reflect.ValueOf(&i).MethodByName("Add")

a := int(0)
params := make([]reflect.Value,0)
params = append(params, reflect.ValueOf(a))
add.Call(params)

This will call the Add method passing the int "a" to it

--
André Moraes
http://andredevchannel.blogspot.com/

DEXTER

unread,
Mar 26, 2012, 8:42:27 PM3/26/12
to golan...@googlegroups.com, DEXTER, nvcnvn
Hi,
The below code works without any errors, but when I try to pass a pointer to a function, it throws up errors
Any help?

package main

import "fmt"
import "reflect"

type T struct {}

func (t *T) Foo() {
    fmt.Println("foo")
}

type MyStruct struct {
    id int
}

func (t *T) Bar() {
    fmt.Println("foo")
}

func main() {
    var t T
    reflect.ValueOf(&t).MethodByName("Foo").Call([]reflect.Value{})
}

/modified main () that throws errors
func main() {
    var t T
   bar := reflect.ValueOf(&t).​MethodByName("Bar")
  ms := &MyStruct{5}

   params := make([]reflect.Value,0)
   params = append(params, reflect.ValueOf(ms))
  bar.Call(params)
}

Message has been deleted

DEXTER

unread,
Mar 27, 2012, 2:50:50 AM3/27/12
to golan...@googlegroups.com, DEXTER, nvcnvn
Thanks,
Now I could get it to work with any errors


package main

import "fmt"
import "reflect"

type T struct {}

func (t *T) Foo() {
    fmt.Println("foo")
}

type MyStruct struct {
    id int
}

type Person struct {
    Name string
    Age int
}

func (t *T) Bar(ms * MyStruct, p * Person) {
    fmt.Println("foo", ms.id, p.Name, p.Age)

}

func main() {
    var t T
    reflect.ValueOf(&t).MethodByName("Foo").Call([]reflect.Value{})
    reflect.ValueOf(&t).MethodByName("Bar").Call([]reflect.Value{reflect.ValueOf(&MyStruct{15}),  reflect.ValueOf(&Person{"Dexter", 15})})
}

DEXTER

unread,
Mar 27, 2012, 3:06:19 AM3/27/12
to golan...@googlegroups.com
Hi,
How do I create instance of Struct from string
I am trying something similar to zend controller /action
In my handler function, I have 2 strings, controller name & action.
Can some one point me to code to create instance of struct from a string
Dexter

chris dollin

unread,
Mar 27, 2012, 3:10:01 AM3/27/12
to DEXTER, golan...@googlegroups.com
On 27 March 2012 08:06, DEXTER <djc...@gmail.com> wrote:
> Hi,
> How do I create instance of Struct from string
> I am trying something similar to zend controller /action
> In my handler function, I have 2 strings, controller name & action.
> Can some one point me to code to create instance of struct from a string

Why not just set up a map from strings to constructor functions and
use that?

Chris

(Yes, one could use reflection and seach for things of the right type and
go through the reflection API and and and and ... but why not go the
utterly straightforward route?)

Chris

--
Chris "allusive" Dollin

André Moraes

unread,
Mar 27, 2012, 8:48:02 AM3/27/12
to DEXTER, golan...@googlegroups.com
On Tue, Mar 27, 2012 at 4:06 AM, DEXTER <djc...@gmail.com> wrote:
> Hi,
> How do I create instance of Struct from string
> I am trying something similar to zend controller /action

I already did something similar to that in one of my projects.

I can sent you the source code when I get home for lunch.

But the road is:

Get access to the type of the handler, the easy way is to pass a
zero-value of the hadler &MyHandler{} and find the type using reflect.
Associate the Type object with an String inside a Map.
Then, when receiving the request, create a new instace of the Type and
call the desired Method.

André Moraes

unread,
Mar 27, 2012, 12:57:39 PM3/27/12
to DEXTER, golan...@googlegroups.com
>> Hi,
>> How do I create instance of Struct from string
>> I am trying something similar to zend controller /action
>
> I already did something similar to that in one of my projects.

// this method return a function that any time is called (with
http.Request and ResponseWriter)
// will create a new instance with the same type as "sample" parameter
// and invoke the "method"
func RestDispatchMeth(sample interface{}, method string) http.HandlerFunc {
t := reflect.ValueOf(sample).Type()
return func(w http.ResponseWriter, req *http.Request) {
v := reflect.New(t)
log.Printf("Controller: %v", t.Name())

callControllerMethod(method, v, w, req)
}
}

// this function receiveis the controler "cont" and the "methodName" parameters
// together with the ResponseWriter and Request
// If it is able to find the method it call's the method.
func callControllerMethod(methodName string, cont reflect.Value, w
http.ResponseWriter, req *http.Request) {
// check if the method is valid
if method := cont.MethodByName(methodName); method.IsValid() {
vw := reflect.ValueOf(w)
vreq := reflect.ValueOf(req)
log.Printf("Method: %v", methodName)
// call it with the rigth parameters.
method.Call([]reflect.Value{0: vw, 1: vreq})

// Calls the after request handler
// If one is defined
if AfterRequest != nil {
AfterRequest.ServeHTTP(w, req)
}

} else {
log.Printf("Unable to find method: %v", methodName)

Reply all
Reply to author
Forward
0 new messages