<p>I just published my first go package. It's a pretty simple thing that provides this function: </p>
<pre><code>chrono.WaitFor(func() bool {
// return True when ready
})
</code></pre>
<p>Is there anything else I should do to distribute or promote this? Currently, you can see all I've done by checking the readme file of: <a href="https://github.com/defcube/chrono" rel="nofollow">https://github.com/defcube/chrono</a></p>
<hr/>**评论:**<br/><br/>xlab_is: <pre><p>The first thing to consider is that you shouldn't call them "shared library" but a package. The second one is to write a doc that covers every feature and examples of usage. And then just push to <a href="https://www.reddit.com/r/golang" rel="nofollow">https://www.reddit.com/r/golang</a> or/and in the Go's mailing list <a href="https://groups.google.com/d/forum/golang-nuts" rel="nofollow">golang-nuts</a>.</p>
<p>If the package itself isn't about code but about the methodology, it's good idea to create a blog post (medium?) and then share it, having a link to the package as a reference implementation. Because for this particular chrono thing it's better to share the methodology itself rather than the package because of its simplicity.</p></pre>defcube: <pre><p>Thank you, great answer. </p>
<p>I must say, sharing go packages feels simpler than publishing python packages. </p></pre>jerf: <pre><blockquote>
<p>Is there anything else I should do to distribute or promote <em>this</em>?</p>
</blockquote>
<p>Others have given you good generic advice. I'm going to give you two specific pieces of advice.</p>
<p>First, in general, the Go community does not generally pick up very small libraries with very small bits of functionality. This seems to have come as a reaction to Ruby or Node environments where it becomes problematic to have dozens upon dozens of tiny packages that import dozens of other tiny packages and produce a huge, unwieldy dependency chain. Having not had this experience myself, this is not something I'm quite so worried about myself, so I'm not necessarily relaying my personal opinion, but the community opinion.</p>
<p>The second problem is that, well, I mean this with all due politeness and I wish I could say this in person where it would be clear I'm trying to provide helpful feedback and not just be an ass, but this code is too complicated for what it does, and the polling loop is unnecessary. This is better done <a href="http://golang.org/pkg/time/#After" rel="nofollow">as in the example for time.After</a>, with a function that simply returns when the task is done. With the concurrency primitives in Go, there's always a way to arrange that rather than a function returning true, and goroutines are cheap enough to make that worthwhile. You shouldn't be polling with a probe function like that. If for no other reason, than because on average you'll be delayed half the SleepTime, for no benefit.</p>
<p>If you need some discussion on how you can arrange your task to become a goroutine that simply returns when the task is done, please post more details and we can help you out. (I'm probably out for tonight but the night is young further west.)</p></pre>defcube: <pre><p>Thanks for your well written advice, and thanks for showing me time.After. </p>
<p>In my use-case, which is probably rare, I'm waiting for external servers to become ready. Because I'm dealing with processes that my program isn't directly controlling, I don't think a goroutine/channel/time.After type solution will work. </p></pre>jerf: <pre><p>It's perfectly normal to spawn a goroutine whose sole purpose in life is to wait for something to happen. You don't have to conserve them, or at least, not to anywhere near that degree. You shouldn't be writing this much code trying to conserve them. Unless you're simultaneously running many tens of thousands of processes, you're not going to run out, or even notice the resource consumption.</p>
<p>This is actually an important element of learning how to use Go fluently and if this is the sort of thing you are doing, probably something you really want to fiddle around with until you're comfortable with. You'll find it really opens up the possibilities when you see how easy it is.</p></pre>defcube: <pre><p>I'd love to learn to think more about solving problems using channels. I notice the go community likes to use channels and goroutines as much as possible, and I'm try to use them. </p>
<p>I'd like to go into a bit more detail about my app though, because I'm not seeing how I could use more goroutines/channels to solve this problem.</p>
<p>Here is a function to close one of my external test servers. I'm working dozens, and eventually hundreds, of processes here. Each test runs in it's own goroutine, and that means that this close function is executing in a goroutine for my test.</p>
<pre><code> func (u *UserContext) Close() {
for slot, _ := range u.OpenAppSlots {
httptestclient.MustHttpPostForm(u.t, *managerUrl+"/stopapp", url.Values{"slot": {slot}, "room": {u.Username}})
}
chrono.MustWaitFor(func() bool {
return len(u.OpenAppSlots) == 0
})
u.CallbackServer.Close()
}
</code></pre>
<p>Another example is when waiting for a server to startup. That part looks like:</p>
<pre><code>// sleep to let the manager fully start
chrono.MustWaitFor(func() bool {
_, err := httptestclient.HttpPostForm(t, *managerUrl+"/stats", url.Values{})
return err == nil
})
</code></pre></pre>djherbis: <pre><p>Your len(u.OpenAppSlots) == 0 looks like a race condition to me (how is the length of u.OpenAppSlots changing between checks?).</p>
<p>Any reason you couldn't use sync.WaitGroup?</p>
<p><a href="http://golang.org/pkg/sync/#WaitGroup" rel="nofollow">http://golang.org/pkg/sync/#WaitGroup</a></p></pre>defcube: <pre><p>Is the race condition related to maps not being thread safe? The solution there could be to sync all the getter/setter functions for the map?</p></pre>djherbis: <pre><p>Yes if you are doing something that modifies the map (set, delete) and anything that is reading the map (including len()) it's unsafe to be concurrent. You'll need to do sync these ops. </p>
<p>Though depending on how you are deleting things from the map, a sync.WaitGroup would make more sense instead of chrono.MustWaitFor when waiting for the map to be empty.</p></pre>djherbis: <pre><p>Out of curiosity, do you use this library? And what do you use it for? I have a couple suggestions depending on your use case.</p></pre>defcube: <pre><p>Yes, I'm using it. I'm writing a diagnostics/testing tool for a custom python server. </p>
<p>I don't want to get into what the python server is doing, but suffice it to say that it starts up other programs, all of which have a small delay before they finish executing. </p>
<p>When I first wrote my go test program, I used time.Sleep. This is not ideal for several reasons, so I created chrono.WaitFor. </p></pre>djherbis: <pre><p>That is a tricky use case since you don't have a way to cleanly detect when the server closes. You could use time.Ticker and time.After instead of time.Sleep if you want to play around with channels.</p></pre>defcube: <pre><p>Thanks. I see how time.Ticker and time.After could accomplish the same thing. </p>
<p>Is time.Sleep inefficient, even when used inside a goroutine? </p></pre>djherbis: <pre><p>I don't know about inefficient, but it's not cancellable. If you wanted to be able to "stop" a chrono you'd have to wait it out. </p>
<p>Also, just thought it might be fun to use the go-routines since they are fun :)</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传