I think I am getting a race condition but I don't understand why.

xuanbao · · 598 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am new to go and I am doing a practice exercise from exercism.io. The directions are simple: </p> <p>Write a program that converts a number to a string, the contents of which depends on the number&#39;s prime factors.</p> <ul> <li>If the number contains 3 as a prime factor, output &#39;Pling&#39;.</li> <li>If the number contains 5 as a prime factor, output &#39;Plang&#39;.</li> <li>If the number contains 7 as a prime factor, output &#39;Plong&#39;.</li> <li>If the number does not contain 3, 5, or 7 as a prime factor, just pass the number&#39;s digits straight through.</li> </ul> <h2>Examples</h2> <ul> <li>28&#39;s prime-factorization is 2, 2, 7.</li> <li>In raindrop-speak, this would be a simple &#34;Plong&#34;.</li> <li>1755 prime-factorization is 3, 3, 3, 5, 13.</li> <li>In raindrop-speak, this would be a &#34;PlingPlang&#34;.</li> <li>The prime factors of 34 are 2 and 17.</li> <li>Raindrop-speak doesn&#39;t know what to make of that, so it just goes with the straightforward &#34;34&#34;.</li> </ul> <p>I had a relatively ugly solution with a bunch of naked ifs that worked. I was trying to refactor and now I think I am getting a race because sometimes all the tests pass. Other times the tests that are expecting multiple raindrops(pling plang ect) randomly fail. </p> <p>here is the code that fails: </p> <pre><code>func Process(input int) string { Lookup := map[int]string{3: &#34;Pling&#34;, 5: &#34;Plang&#34;, 7: &#34;Plong&#34;} output := &#34;&#34; for key, value := range Lookup { mod := math.Mod(float64(input), float64(key)) if (mod == 0) { output = output + value } } return output } func Convert(input int) string { output := Process(input) if (output == &#34;&#34;) { output = strconv.Itoa(input) } return output } </code></pre> <p>What I would like to know is 1) Are naked ifs a no no in go? 2) why is the race occurring? 3) What would be the idiomatic way to solve this in Go?</p> <p>Thanks in advance. </p> <p>Edit to add a <a href="https://gist.github.com/EvanTedesco/969997f5431669051ca9" rel="nofollow">Gist</a> of all the code and tests.</p> <hr/>**评论:**<br/><br/>FUZxxl: <pre><p>Show us the whole code. What you show us has no parallelism and thus no race conditions.</p></pre>Americanstandard: <pre><p>Ok so I may be wrong about the race condition. Here is a <a href="https://gist.github.com/EvanTedesco/969997f5431669051ca9" rel="nofollow">gist</a> of the tests and all of my code. Sometimes all tests pass. Other times the multiple raindrop ones have the correct contents but the order is wrong. </p></pre>FUZxxl: <pre><p>You are being bitten by the nondeterminism in which a <code>range</code> loop iterates over a map. Beginning with Go 1.2 (I think), the Go runtime randomizes the order in which you iterate over a map every time you try. This is because some programs erroneously started to depend on the order being a certain way, which is something not guaranteed by the standard.</p> <p>For example, for 1755 you some times get “PlingPlang” and some times you get “PlangPling” depending on the order in which the factors are tested. You should consider using an array of pairs instead of a map as the iteration order over arrays is well-defined.</p></pre>Americanstandard: <pre><p>By array of pairs do you mean array of structs? Which data type should I be using that allows int and string pairs?</p></pre>FUZxxl: <pre><p>Yeah, an array of structs. Make your own struct type for that.</p></pre>Americanstandard: <pre><p>Thanks a lot man! I appreciate it. </p></pre>paddie: <pre><p>A map has no guarantees of order, meaning when you iterate over the key, values in the map, you cannot make any assumptions on the order apart from it being random. </p></pre>Fwippy: <pre><p>Others have already pointed out the actual issue - that map iteration order is explicitly randomized and cannot be relied upon.</p> <p>But I wanted to point out, if you&#39;re not using goroutines, you shouldn&#39;t see any race conditions. If you are using goroutines and suspect you have a race, you can use the <code>-race</code> flag to <code>go test</code> or <code>go build</code>, which will do a very good job of pointing out any data races you might have.</p></pre>Americanstandard: <pre><p>Excellent thank you for that. </p></pre>

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

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