From 79023de6ce8ebc48ac63956d1d3e7e588bbd1006 Mon Sep 17 00:00:00 2001 From: Gennadii Kovalev Date: Sun, 22 May 2016 20:04:25 +0200 Subject: [PATCH] caller. handler's args are optional. --- README.md | 8 +++++--- caller.go | 32 +++++++++++++++++++++----------- examples/client.go | 4 ++-- examples/server.go | 5 +++-- handler.go | 23 ++++++++++++++++++----- 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index a4063b7..fdc3f03 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Examples directory contains simple client and server. server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport()) //handle connected - server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) { + server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) { log.Println("New client connected") //join them to room c.Join("chat") @@ -89,7 +89,9 @@ var socket = io('ws://yourdomain.com', {transports: ['websocket']}); log.Println(len(channels), "clients in room") }) //on disconnection handler, if client hangs connection unexpectedly, it will still occurs - server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel, args interface{}) { + //you can omit function args if you do not need them + //you can return string value for ack, or return nothing for emit + server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) { //this is not necessary, client will be removed from rooms //automatically on disconnect //but you can remove client from room whenever you need to @@ -98,7 +100,7 @@ var socket = io('ws://yourdomain.com', {transports: ['websocket']}); log.Println("Disconnected") }) //error catching handler - server.On(gosocketio.OnError, func(c *gosocketio.Channel, args interface{}) { + server.On(gosocketio.OnError, func(c *gosocketio.Channel) { log.Println("Error occurs") }) diff --git a/caller.go b/caller.go index 7671947..8e5acef 100644 --- a/caller.go +++ b/caller.go @@ -6,14 +6,15 @@ import ( ) type caller struct { - Func reflect.Value - Args reflect.Type - Out bool + Func reflect.Value + Args reflect.Type + ArgsPresent bool + Out bool } var ( ErrorCallerNotFunc = errors.New("f is not function") - ErrorCallerNot2Args = errors.New("f should have 2 args") + ErrorCallerNot2Args = errors.New("f should have 1 or 2 args") ErrorCallerMaxOneValue = errors.New("f should return not more than one value") ) @@ -28,19 +29,25 @@ func newCaller(f interface{}) (*caller, error) { } fType := fVal.Type() - if fType.NumIn() != 2 { - return nil, ErrorCallerNot2Args - } - if fType.NumOut() > 1 { return nil, ErrorCallerMaxOneValue } - return &caller{ + curCaller := &caller{ Func: fVal, - Args: fType.In(1), Out: fType.NumOut() == 1, - }, nil + } + if fType.NumIn() == 1 { + curCaller.Args = nil + curCaller.ArgsPresent = false + } else if fType.NumIn() == 2 { + curCaller.Args = fType.In(1) + curCaller.ArgsPresent = true + } else { + return nil, ErrorCallerNot2Args + } + + return curCaller, nil } /** @@ -55,6 +62,9 @@ calls function with given arguments from its representation using reflection */ func (c *caller) callFunc(h *Channel, args interface{}) []reflect.Value { a := []reflect.Value{reflect.ValueOf(h), reflect.ValueOf(args).Elem()} + if !c.ArgsPresent { + a = a[0:1] + } return c.Func.Call(a) } diff --git a/examples/client.go b/examples/client.go index e92c374..6d1063d 100644 --- a/examples/client.go +++ b/examples/client.go @@ -45,14 +45,14 @@ func main() { log.Fatal(err) } - err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel, args interface{}) { + err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) { log.Fatal("Disconnected") }) if err != nil { log.Fatal(err) } - err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel, args interface{}) { + err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel) { log.Println("Connected") }) if err != nil { diff --git a/examples/server.go b/examples/server.go index 3f951a7..340949e 100644 --- a/examples/server.go +++ b/examples/server.go @@ -21,7 +21,7 @@ type Message struct { func main() { server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport()) - server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) { + server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) { log.Println("Connected") c.Emit("/message", Message{10, "main", "using emit"}) @@ -29,12 +29,13 @@ func main() { c.Join("test") c.BroadcastTo("test", "/message", Message{10, "main", "using broadcast"}) }) - server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel, args interface{}) { + server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) { log.Println("Disconnected") }) server.On("/join", func(c *gosocketio.Channel, channel Channel) string { time.Sleep(2 * time.Second) + log.Println("Client joined to ", channel.Channel) return "joined to " + channel.Channel }) diff --git a/handler.go b/handler.go index ca143ce..78c3636 100644 --- a/handler.go +++ b/handler.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/graarh/golang-socketio/protocol" "sync" + "reflect" ) const ( @@ -92,6 +93,11 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) { return } + if !f.ArgsPresent { + f.callFunc(c, &struct{}{}) + return + } + data := f.getArgs() err := json.Unmarshal([]byte(msg.Args), &data) if err != nil { @@ -106,13 +112,20 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) { return } - data := f.getArgs() - err := json.Unmarshal([]byte(msg.Args), &data) - if err != nil { - return + var result []reflect.Value + if f.ArgsPresent { + //data type should be defined for unmarshall + data := f.getArgs() + err := json.Unmarshal([]byte(msg.Args), &data) + if err != nil { + return + } + + result = f.callFunc(c, data) + } else { + result = f.callFunc(c, &struct{}{}) } - result := f.callFunc(c, data) ack := &protocol.Message{ Type: protocol.MessageTypeAckResponse, AckId: msg.AckId,