Thanks for your feedback, more below: On April 21, 2014 at 8:01:32 PM, jimmy frasche (soapboxcicero@xxxxxxxxx) wrote: If you're not aware TestBusTLS fails and when tested with -race, TestBusIPC and TestBusTCP fail as well, though not always and without detecting any races. Hmmm. You’re right. I don’t know *how* committed these without checking that before. My guess is that Race is causing more dropped packets. In the case of TestBus, what’s probably happening is that we are hitting backpressure, and the message gets dropped. Without -race, the code is fast enough to keep up without dropping messages. (I could probably try to change the code to reduce the number of concurrent senders for TestBus — I wonder if I can tell if -race is in use…) So there’s no race, we’re just dropping messages due to perf. And the test suite is intentionally picky about that. From a cursory look: Use golint: https://github.com/golang/lint Yep. It doesn’t find anything (it did before). Is there something you think it should report, but doesn’t? — RemEndpoint should be RemoveEndpoint. I guess that’s a style nit. I’ll go ahead and make the change. Is there any reason all the sps are in one package? It looks like you've built a generic framework for them to implement. It would be more idiomatic if you had something like import "bitbucket.org/gdamore/mangos/req" It would have been a nice idea, and it is actually what I wanted to do (for the transports too!) But I had trouble making this work as well as I’d like, because of circular includes. In particular, I want to register all the *stock* protocols so that users don’t have to register them explicitly. The problem I had with this is that: mangos/req would depend on mangos but mangos can’t register req in the core, because if it tries to import mangos/req, circular imports and death. ... r, err := req.Dial(...) instead of import "bitbucket.org/gdamore/mangos" ... r, err := mangos.NewSocket(...) A mangos.Dial could still work if the protocols register with mangos on init. Hmm… so “init” in the package happens at import time? That could work, but it would mean that end users would need to import each protocol or transport specifically. (See below about my idea for another “all” place holder for lazy developers who want everything. :-) Additionally this would mean you could have a websocket transport without requiring every one importing the package having to link to a websocket package Hmm… so you’re proposing that the application basically encode the knowledge. I guess that would work ok, and as you notice it would shave off the big imports (a real win for TLS and websocket!), but I’m thinking that it makes it hard to write a “generic” app like nanocat, but maybe not much. Sadly, I don’t see how I can apply this strategy to the transport layer, where it would really have the most valuable impact, since the transport names are encoded in user supplied strings. Maybe I could use some intermediate package that contains a registry of all types, and apps could just do “RegisterAllTransports” in the package or something. Let me think about this some more. — Why have ProtocolFactory be an interface instead of type ProtocolFactory func() Protocol Is there every any reason for a protocol factory to have any state between calls? It doesn't seem like it should ever. It doesn’t. I should change this code. I wrote it before I started playing with function pointers in Go… interfaces seemed natural. I want to review this again to see if it can be refactored more cleanly using closures. — The uint16 for protocol numbers could be a type with a String() method. That’s a *neat* idea. The split of string to number made more sense when I had separate protocol types for X vs normal (XREP, REP, etc.) implementations. There are still the “X” names, but those could reasonably go away now that I’m using a socket optoin to set raw mode. — You may want to consider implementing io.Reader/Writer for sockets. The gorilla websocket package has a nice example for using it over a message oriented protocol: http://godoc.org/github.com/gorilla/websocket#Conn.NextReader I will look at it, but I actually considered implementing more like a net.Conn interface, and I decided that because of the semantic differences I gave up — this is really un-streamlike. Looking at the reference you gave though, it seems they just return an io.Reader for the *message*. There are some weird semantics here though… you Close() the io.Writer to send the message, you can’t have parallel accessors, and the underlying connection remains open. This feels really kind of contrived to get interface compatibility with things that want io.Reader or io.Writer. Wouldn’t it just be easier to just use bytes.Buffer on the msg.Body? Maybe the one useful addition would be send-on-close semantic. (It doesn’t look it would be very hard to do this kind of interface, I just never considered that it would be particularly useful.) This allows a great deal of interop. Can you point me at any examples of this? - Garrett