func NewRouterChanneler(endpoints string) *Channeler {
	return newChanneler(Router, endpoints, "")
}
NewRouterChanneler creates a new Channeler wrapping
a Router socket. The socket will Bind by default.
package goczmq
import "C"
import (
	"fmt"
	"math/rand"
	"strings"
)
type Channeler struct {
	id          int64
	sockType    int
	endpoints   string
	subscribe   *string
	commandAddr string
	proxyAddr   string
	commandChan chan<- string
	SendChan    chan<- [][]byte
	RecvChan    <-chan [][]byte
}
func (c *Channeler) Destroy() {
	c.commandChan <- "destroy"
}
func (c *Channeler) Subscribe(topic string) {
	c.commandChan <- fmt.Sprintf("subscribe %s", topic)
}
func (c *Channeler) Unsubscribe(topic string) {
	c.commandChan <- fmt.Sprintf("unsubscribe %s", topic)
}
func (c *Channeler) actor(recvChan chan<- [][]byte) {
	pipe, err := NewPair(fmt.Sprintf(">%s", c.commandAddr))
	if err != nil {
		panic(err)
	}
	defer pipe.Destroy()
	defer close(recvChan)
	pull, err := NewPull(c.proxyAddr)
	if err != nil {
		panic(err)
	}
	defer pull.Destroy()
	sock := NewSock(c.sockType)
	defer sock.Destroy()
	switch c.sockType {
	case Pub, Rep, Pull, Router, XPub:
		err = sock.Attach(c.endpoints, true)
		if err != nil {
			panic(err)
		}
	case Req, Push, Dealer, Pair, Stream, XSub:
		err = sock.Attach(c.endpoints, false)
		if err != nil {
			panic(err)
		}
	case Sub:
		if c.subscribe != nil {
			subscriptions := strings.Split(*c.subscribe, ",")
			for _, topic := range subscriptions {
				sock.SetSubscribe(topic)
			}
		}
		err = sock.Attach(c.endpoints, false)
		if err != nil {
			panic(err)
		}
	default:
		panic(ErrInvalidSockType)
	}
	poller, err := NewPoller(sock, pull, pipe)
	if err != nil {
		panic(err)
	}
	defer poller.Destroy()
	for {
		s := poller.Wait(-1)
		switch s {
		case pipe:
			cmd, err := pipe.RecvMessage()
			if err != nil {
				panic(err)
			}
			switch string(cmd[0]) {
			case "destroy":
				disconnect := strings.Split(c.endpoints, ",")
				for _, endpoint := range disconnect {
					sock.Disconnect(endpoint)
				}
				pipe.SendMessage([][]byte{[]byte("ok")})
				goto ExitActor
			case "subscribe":
				topic := string(cmd[1])
				sock.SetSubscribe(topic)
				pipe.SendMessage([][]byte{[]byte("ok")})
			case "unsubscribe":
				topic := string(cmd[1])
				sock.SetUnsubscribe(topic)
				pipe.SendMessage([][]byte{[]byte("ok")})
			}
		case sock:
			msg, err := s.RecvMessage()
			if err != nil {
				panic(err)
			}
			recvChan <- msg
		case pull:
			msg, err := pull.RecvMessage()
			if err != nil {
				panic(err)
			}
			err = sock.SendMessage(msg)
			if err != nil {
				panic(err)
			}
		}
	}
ExitActor:
}
func (c *Channeler) channeler(commandChan <-chan string, sendChan <-chan [][]byte) {
	push, err := NewPush(c.proxyAddr)
	if err != nil {
		panic(err)
	}
	defer push.Destroy()
	pipe, err := NewPair(fmt.Sprintf("@%s", c.commandAddr))
	if err != nil {
		panic(err)
	}
	defer pipe.Destroy()
	for {
		select {
		case cmd := <-commandChan:
			switch cmd {
			case "destroy":
				err = pipe.SendFrame([]byte("destroy"), FlagNone)
				if err != nil {
					panic(err)
				}
				_, err = pipe.RecvMessage()
				if err != nil {
					panic(err)
				}
				goto ExitChanneler
			default:
				parts := strings.Split(cmd, " ")
				numParts := len(parts)
				message := make([][]byte, numParts, numParts)
				for i, p := range parts {
					message[i] = []byte(p)
				}
				err := pipe.SendMessage(message)
				if err != nil {
					panic(err)
				}
				_, err = pipe.RecvMessage()
				if err != nil {
					panic(err)
				}
			}
		case msg := <-sendChan:
			err := push.SendMessage(msg)
			if err != nil {
				panic(err)
			}
		}
	}
ExitChanneler:
}
func newChanneler(sockType int, endpoints string, subscribe ...string) *Channeler {
	commandChan := make(chan string)
	sendChan := make(chan [][]byte)
	recvChan := make(chan [][]byte)
	C.Sock_init()
	c := &Channeler{
		id:          rand.Int63(),
		endpoints:   endpoints,
		sockType:    sockType,
		commandChan: commandChan,
		SendChan:    sendChan,
		RecvChan:    recvChan,
	}
	c.commandAddr = fmt.Sprintf("inproc://actorcontrol%d", c.id)
	c.proxyAddr = fmt.Sprintf("inproc://proxy%d", c.id)
	if len(subscribe) > 0 {
		topics := strings.Join(subscribe, ",")
		c.subscribe = &topics
	}
	go c.channeler(commandChan, sendChan)
	go c.actor(recvChan)
	return c
}
func NewPubChanneler(endpoints string) *Channeler {
	return newChanneler(Pub, endpoints, "")
}
func NewSubChanneler(endpoints string, subscribe ...string) *Channeler {
	return newChanneler(Sub, endpoints, subscribe...)
}
func NewRepChanneler(endpoints string) *Channeler {
	return newChanneler(Rep, endpoints, "")
}
func NewReqChanneler(endpoints string) *Channeler {
	return newChanneler(Req, endpoints, "")
}
func NewPullChanneler(endpoints string) *Channeler {
	return newChanneler(Pull, endpoints, "")
}
func NewPushChanneler(endpoints string) *Channeler {
	return newChanneler(Push, endpoints, "")
}