<story><title>Building a Streaming Platform in Go for Postgres</title><url>https://blog.peerdb.io/building-a-streaming-platform-in-go-for-postgres</url></story><parent_chain><item><author>cauchyk</author><text>Author of the blog here, curious what a better alternative would be in this context. The channel has to be passed around for the producer and consumer to interface with each other. Are there better patterns for this?</text></item><item><author>earthboundkid</author><text>Moving to channels seems like a weird choice. Channels should basically always be an implementation detail not exposed in public APIs.</text></item></parent_chain><comment><author>atombender</author><text>Not the parent, but I personally dislike it when Go libraries use channels in their public APIs, as it forces a specific concurrency model on the consumer; in particular, channels are quite slow, being protected by an internal mutex, so you&amp;#x27;re always paying for the overhead no matter if you need it or not.&lt;p&gt;You also have to be very careful about managing the channel lifecycle. If you&amp;#x27;re not pulling (selecting from) the channel, the library will be permanently stuck. So you must now have a way to tell the library to stop sending, and it must cancel any in-flight send operations if you call producer.Stop() or whatever. In my experience libraries often have bugs in their channel code. It&amp;#x27;s far too easy to get deadlocks with channels that have interdependencies, and you have to be very careful about buffered versus unbuffered channels, as they behave differently.&lt;p&gt;A better API, in my opinion, is to offer a callback or single-method interface. Then the implementer of that callback or interface can choose to use channels internally if they desire, or they can use something else. You get the same backpressure support since you can treat it as synchronous.&lt;p&gt;After all, a channel&amp;#x27;s send interface is essentially just:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    type Channel[T any] interface {
        Send(T)
    }
&lt;/code&gt;&lt;/pre&gt;
But a &amp;quot;chan T&amp;quot; doesn&amp;#x27;t offer this flexibility.&lt;p&gt;My rule of thumb for channels is that they&amp;#x27;re goroutine glue, not an API primitive. Build APIs out of interfaces, not channels. The only thing that uses channels should be the one that&amp;#x27;s controlling the goroutines, because it&amp;#x27;s the thing that orchestrates them.&lt;p&gt;That said, it&amp;#x27;s not a hard rule. There are places where channels may have their place in a public API, though I&amp;#x27;m not sure I can think of any examples off-hand.</text></comment>
<story><title>Building a Streaming Platform in Go for Postgres</title><url>https://blog.peerdb.io/building-a-streaming-platform-in-go-for-postgres</url></story><parent_chain><item><author>cauchyk</author><text>Author of the blog here, curious what a better alternative would be in this context. The channel has to be passed around for the producer and consumer to interface with each other. Are there better patterns for this?</text></item><item><author>earthboundkid</author><text>Moving to channels seems like a weird choice. Channels should basically always be an implementation detail not exposed in public APIs.</text></item></parent_chain><comment><author>JyB</author><text>Please see this great talk by Bryan C. Mills touching on the subject:
&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;youtu.be&amp;#x2F;5zXAHh5tJqQ?t=421&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;youtu.be&amp;#x2F;5zXAHh5tJqQ?t=421&lt;/a&gt;</text></comment>