<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('data', callback)
</code></pre>
<p>How do I do this in Go?</p>
<hr/>**评论:**<br/><br/>niosop: <pre><p>Callbacks aren'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't even need to wrap it in a go-routine since in most scenario'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 "listens" to the stream and acts whenever the stream receives data. If there'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 'listen' 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't have to be non-blocking depending on what you're doing obviously, but that would be closer to the 'Go' 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 "blocks", because if you're coming from Node you need to bear in mind that Node's definition of "blocking" and the rest of the world'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, "blocking" is treated as a terrible, terrible sin because a naive blocking read from a socket will block the <em>entire runtime</em>. Node's definition of "blocking" 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 "blocking" (but not blocking the runtime) code.</p>
<p>You almost certainly don't need a channel.</p>
<p>You also, as <a href="/u/koffizet" rel="nofollow">/u/koffizet</a> said, probably don't need to spawn a goroutine "just to read". You spawn a goroutine for the task you want to do, like "read a webpage" or "service a socket for a network protocol", and stay blocking within it. The only exception I've encountered is that if you'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 "reading" 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're spawning and where the channels go and why is this deadlocking, etc. etc., you've probably got something overcomplicated there.</p></pre>tv64738: <pre><pre><code>for {
var msg Message
if err := dec.Decode(&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 &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
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传