FAQ
Hello gophers,

I recently started learning Go and wanted to write a small
WebSocket-Framework. I finished a basic version
of the framework calling functions associated with events and delivering
the sent data as interface{}.

To illustrate, what I mean, this is the current API design:

func echo(conn *Connection, data *map[string]interface{}) {
fmt.Println(data["test"].(string)) // example data access
conn.Emit("echoSuccess", data)
}

func main() {

myrouter := NewRouter()
myrouter.On("echo", echo)

http.Handle("/", http.FileServer(http.Dir("./public")))
http.Handle("/ws", myrouter.Handler())

if err := http.ListenAndServe(*address, nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}

On the client-side I can then simply emit the echo event and send data
along with it.

What I dislike about this approach is how the data in the echo function is
handled. Since
I am using JSON I could also pass a json.RawMessage to the echo function
instead of a
map[string]interface{}, but unmarshalling it for every type of event is
also a very repetitive
approach. Although I could pass in then struct and access it more properly.

Provisional nice API design:
type EchoData struct {
msg string
}

func echo(conn *Connection, data *EchoData) {
fmt.Println(data.msg) // example data access
conn.Emit("echoSuccess", data)
}

So the quesion is basically is there a way to determine the argument types
of a function using reflection?
I would then simply save the type information and try to unmarshall the
received data accordingly.

Thanks in advance,
Niklas




--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Andrew Gallant at May 16, 2013 at 2:25 am
    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.

    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 1:56 pm
    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Andrew Gallant at May 16, 2013 at 4:39 pm
    Remember, `reflect.New(TYPE)` is equivalent to `new(TYPE)`. So it returns a
    pointer to `TYPE`. e.g., http://play.golang.org/p/SJ6TZ92CtN

    So if your `reflect.New` call is a pointer to TYPE but the function expects
    just TYPE, then you'll probably need a call to `Elem` in there somewhere.

    N.B. I didn't look too closely---in a rush. I can help more if that doesn't
    work.
    On Thursday, May 16, 2013 9:36:42 AM UTC-4, nikla...@gmail.com wrote:

    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and
    delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 8:12 pm
    Thanks in theory it's working now:
    http://play.golang.org/p/O1VCEicJka

    But I seem to have hit the limit of the json marshalling capabilities.
    Either there is a way to marshal into an reflect.Type considering the
    represented actual type or
    need to write a small simple unmarshaller for reflect.Type, that represent
    structs...

    Any ideas?


    On Thursday, 16 May 2013 17:39:21 UTC+1, Andrew Gallant wrote:

    Remember, `reflect.New(TYPE)` is equivalent to `new(TYPE)`. So it returns
    a pointer to `TYPE`. e.g., http://play.golang.org/p/SJ6TZ92CtN

    So if your `reflect.New` call is a pointer to TYPE but the function
    expects just TYPE, then you'll probably need a call to `Elem` in there
    somewhere.

    N.B. I didn't look too closely---in a rush. I can help more if that
    doesn't work.
    On Thursday, May 16, 2013 9:36:42 AM UTC-4, nikla...@gmail.com wrote:

    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and
    delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo
    function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 8:12 pm
    Here is a snippet illustrating the problem:
    http://play.golang.org/p/O1VCEicJka
    On Thursday, 16 May 2013 14:36:42 UTC+1, nikla...@gmail.com wrote:

    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and
    delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 8:12 pm
    I narrowed down the problem in this snippet, that successfully compiles and
    runs, but the unmarshalling seems to be the problem,
    since the structs msg is empty:

    http://play.golang.org/p/O1VCEicJka

    On Thursday, 16 May 2013 14:36:42 UTC+1, nikla...@gmail.com wrote:

    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and
    delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dan Kortschak at May 16, 2013 at 8:26 pm
    encoding/json depends on reflect, so fields must be exported, and you want to decode in the Go type, not a reflect type representing it.

    http://play.golang.org/p/vLVDDD74YG

    On 17/05/2013, at 5:42 AM, "niklas.voss@gmail.com " wrote:

    I narrowed down the problem in this snippet, that successfully compiles and runs, but the unmarshalling seems to be the problem,
    since the structs msg is empty:

    http://play.golang.org/p/O1VCEicJka


    On Thursday, 16 May 2013 14:36:42 UTC+1, nikla...@gmail.com wrote:
    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692<http://127.0.0.1:58692>: reflect: Call using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas



    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:
    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.

    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com .
    For more options, visit https://groups.google.com/groups/opt_out.


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 9:38 pm
    Thank you so much Andrew Gallard and kortschak with your help I was able to
    resolve all issues.
    On Thursday, 16 May 2013 21:26:46 UTC+1, kortschak wrote:

    encoding/json depends on reflect, so fields must be exported, and you
    want to decode in the Go type, not a reflect type representing it.

    http://play.golang.org/p/vLVDDD74YG

    On 17/05/2013, at 5:42 AM, "nikla...@gmail.com <javascript:>" <
    nikla...@gmail.com <javascript:>> wrote:

    I narrowed down the problem in this snippet, that successfully compiles
    and runs, but the unmarshalling seems to be the problem,
    since the structs msg is empty:

    http://play.golang.org/p/O1VCEicJka

    On Thursday, 16 May 2013 14:36:42 UTC+1, nikla...@gmail.com wrote:

    The On method of Router is now implemented as follows:

    func (router *Router) On(name string, cb interface{}) {

    cbValue := reflect.ValueOf(cb)

    cbDataType := reflect.TypeOf(cb).In(1)

    pre := func(conn *Connection, data *json.RawMessage) {
    decoded := reflect.New(cbDataType)

    err := json.Unmarshal(*data, &decoded)
    if err == nil {
    args := []reflect.Value{reflect.ValueOf(conn), decoded}
    cbValue.Call(args)
    } else {
    fmt.Println("[JSON-FORWARD]", data, err) // TODO: Proper debug output!
    }
    }
    router.callbacks[name] = pre
    }

    The problem now is if I send data the program panics:
    2013/05/16 14:28:54 http: panic serving 127.0.0.1:58692: reflect: Call
    using **main.ChatMessage as type *main.ChatMessage

    I am struggling to figure out how to get rid of this problem though...

    Thanks for the great help so far,
    Niklas


    On Thursday, 16 May 2013 03:25:39 UTC+1, Andrew Gallant wrote:

    http://play.golang.org/p/41MuXxwkAS
    On May 15, 5:15 pm, niklas.v...@gmail.com wrote:
    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and
    delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)

    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)

    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo
    function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.
    Provisional nice API design:
    type EchoData struct {
    msg string

    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)

    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Niklas Voss at May 16, 2013 at 1:42 pm
    Thanks a lot,
    that was exactly what I was looking for!

    Can't believe I overlooked that. I was digging through the docs all night.
    On Wednesday, 15 May 2013 22:15:17 UTC+1, nikla...@gmail.com wrote:

    Hello gophers,

    I recently started learning Go and wanted to write a small
    WebSocket-Framework. I finished a basic version
    of the framework calling functions associated with events and delivering
    the sent data as interface{}.

    To illustrate, what I mean, this is the current API design:

    func echo(conn *Connection, data *map[string]interface{}) {
    fmt.Println(data["test"].(string)) // example data access
    conn.Emit("echoSuccess", data)
    }

    func main() {

    myrouter := NewRouter()
    myrouter.On("echo", echo)

    http.Handle("/", http.FileServer(http.Dir("./public")))
    http.Handle("/ws", myrouter.Handler())

    if err := http.ListenAndServe(*address, nil); err != nil {
    log.Fatal("ListenAndServe:", err)
    }
    }

    On the client-side I can then simply emit the echo event and send data
    along with it.

    What I dislike about this approach is how the data in the echo function is
    handled. Since
    I am using JSON I could also pass a json.RawMessage to the echo function
    instead of a
    map[string]interface{}, but unmarshalling it for every type of event is
    also a very repetitive
    approach. Although I could pass in then struct and access it more properly.

    Provisional nice API design:
    type EchoData struct {
    msg string
    }

    func echo(conn *Connection, data *EchoData) {
    fmt.Println(data.msg) // example data access
    conn.Emit("echoSuccess", data)
    }

    So the quesion is basically is there a way to determine the argument types
    of a function using reflection?
    I would then simply save the type information and try to unmarshall the
    received data accordingly.

    Thanks in advance,
    Niklas



    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 15, '13 at 10:27p
activeMay 16, '13 at 9:38p
posts10
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase