What is Go's equivalent for node's Stream.on('data', callback)?

agolangf · · 527 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Learning Go, pretty fun language so far. I was just wondering how one would process the data coming into a stream? I know on Node you would use </p> <pre><code>Stream.on(&#39;data&#39;, callback) </code></pre> <p>How do I do this in Go?</p> <hr/>**评论:**<br/><br/>niosop: <pre><p>Callbacks aren&#39;t used much in Go. Just stick a blocking read into a goroutine.</p></pre>koffiezet: <pre><p>Which is also the easiest, most straight-forward way... Usually you don&#39;t even need to wrap it in a go-routine since in most scenario&#39;s, your code will probably need to block on input in the current context (which can already be a go-routine).</p></pre>emelent: <pre><p>Yes, I just want to know how one would write a function that &#34;listens&#34; to the stream and acts whenever the stream receives data. If there&#39;s a link to a quick example or an article anything at all. </p></pre>rawktron: <pre><p>You could use a channel for this? Create a channel, and then write to that from your goroutine, and have your other main thread or another goroutine &#39;listen&#39; to that channel.</p> <p><a href="https://gobyexample.com/channels" rel="nofollow">https://gobyexample.com/channels</a></p> <p>And if you need it to not block:</p> <p><a href="https://gobyexample.com/non-blocking-channel-operations" rel="nofollow">https://gobyexample.com/non-blocking-channel-operations</a></p> <p>Doesn&#39;t have to be non-blocking depending on what you&#39;re doing obviously, but that would be closer to the &#39;Go&#39; way to do it rather than callbacks.</p></pre>emelent: <pre><p>Thanks.</p></pre>jerf: <pre><p>However, bear in mind that you only use the channels if you actually need to move that data between goroutines for some reason. In Go, the standard answer is have a goroutine that simply reads from the socket and &#34;blocks&#34;, because if you&#39;re coming from Node you need to bear in mind that Node&#39;s definition of &#34;blocking&#34; and the rest of the world&#39;s do not match in a critical way. In Go, reading from a socket does block that goroutine, but it does <em>not</em> block the runtime, which will happily just schedule another goroutine in and get on with life. In Node, &#34;blocking&#34; is treated as a terrible, terrible sin because a naive blocking read from a socket will block the <em>entire runtime</em>. Node&#39;s definition of &#34;blocking&#34; is actually a very local one to the Node runtime, not a globally-applicable one.</p> <p>In Go, if you want to read from a thousand sockets, you happily spawn 1000 goroutines, each reading from their own socket, and write straightforward &#34;blocking&#34; (but not blocking the runtime) code.</p> <p>You almost certainly don&#39;t need a channel.</p> <p>You also, as <a href="/u/koffizet" rel="nofollow">/u/koffizet</a> said, probably don&#39;t need to spawn a goroutine &#34;just to read&#34;. You spawn a goroutine for the task you want to do, like &#34;read a webpage&#34; or &#34;service a socket for a network protocol&#34;, and stay blocking within it. The only exception I&#39;ve encountered is that if you&#39;re in a situation where you have a socket where either side might at any time read or write to the socket, you may need to spawn one goroutine for the &#34;reading&#34; duties while other goroutines do the writing.</p> <p>The rule of thumb here is that you should find your code refreshingly easy to write as compared to Node; if you find yourself getting confused about the goroutines you&#39;re spawning and where the channels go and why is this deadlocking, etc. etc., you&#39;ve probably got something overcomplicated there.</p></pre>tv64738: <pre><pre><code>for { var msg Message if err := dec.Decode(&amp;msg); err != nil { ... } // do something with msg } </code></pre></pre>twoism: <pre><p><a href="https://gobyexample.com/channels" rel="nofollow">https://gobyexample.com/channels</a></p></pre>mcouturier: <pre><p>Create a <code>Reader</code> middleware. A struct that implements the <code>Reader</code> interface.</p> <p>This object will receive the original stream. When <code>read</code> is called on that object, call the <code>read</code> of the original stream, inspect it then return what was returned to you to the caller.</p> <p>EDIT: example (untested, on top of my head)</p> <pre><code>type Inspector struct { src io.Reader } func NewInspector(r io.Reader) *Inspector { return &amp;Inspector{r} } func (i *Inspector) Read(p []byte) (n int, err error) { n, err = i.src.Read(p) // inspect anything here return } </code></pre> <p>Then you give that <code>Reader</code> to clients instead of the original reader. When they will read, you will see data pass through.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

527 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传