Good point. The same is true for the C-style for loop BTW. https://play.golang.org/p/58jwveiywB
Using an explicit boolean flag for signaling success avoids this trap. > On 2. Aug 2017, at 10:30, tom.pa...@centralway.com wrote: > > A side effect of this approach is that the index after the range loop will be > zero if slice contains zero or one elements: > https://play.golang.org/p/F7lLZ5wcuv > > This means that code using the index after the range will need to re-test > whether the slice was empty to avoid a potential panic. > > On Thursday, July 27, 2017 at 2:21:34 PM UTC+2, Christoph Berger wrote: > That’s actually what I meant to indicate in the last paragraph (emphasis > added by me): > > > The code in the Reddit post takes advantage of the fact that the last > > increment of the C-style loop can be observed outside the loop, > > But thanks for providing a clarification. I see now it has not been clear to > everyone. > >> On Wed, Jul 26, 2017 at 08:44:46AM -0700, Christoph Berger wrote: >> >>>> someone shared [this question]( >>>> https://www.reddit.com/r/golang/comments/6paqc0/bug_that_caught_me_with_range/ >>>> >>>> <https://www.reddit.com/r/golang/comments/6paqc0/bug_that_caught_me_with_range/>) >>>> >>>> on reddit. I must say, that I'm surprised by the behavior myself. I would >>>> have expected >>>> for i = range v >>>> to be semantically equivalent to >>>> for i = 0; i < len(v); i++ >>>> and don't really understand the reasoning behind choosing different >>>> semantics. Note, that the difference only exists, if i is declared outside >>>> of the loop, that is, this is solely about the behavior after exiting the >>>> loop-body. >>>> >>>> I'd greatly appreciate some explanation :) >>> An attempt to explain this by looking at the C-style loop only: >>> >>> The classic C-style for loop >>> >>> for i:=0; i<len(v); i++ {...} >>> >>> is equivalent to >>> >>> for i:=0; i<len(v); { >>> // do something with i >>> i++ // This is always the very last statement in the loop body >>> } >>> >>> The loop body runs from 0 to len(v)-1 only, because the last increment of i >>> to len(v) stops the loop, and no further iteration occurs. The code in the >>> loop body never sees i being set to len(v). >>> >>> And that's the same behavior as with the range operator. >>> >>> The code in the Reddit post takes advantage of the fact that the last >>> increment of the C-style loop can be observed outside the loop, for >>> detecting if the loop stopped early. This is a neat side effect that is not >>> possible with the range operator. >> >> I would point out that both Axel and you are off a tiny bit from what >> actually happens ;-) >> >> In a for loop which uses a short variable declaration, that variable's >> scope is confined to the for *statement* itself, and is also visible in >> the loop's body because its scope is defined to be nested in that of the >> loop statement. This means in a loop like >> >> for i := 0; i < len(s); i++ { >> } >> >> the variable "i" is not accessible after the closing brace. >> >> The actual "problem" stated in that Reddit post is different: it uses a >> variable defined outside the "for" loop: >> >> var i int >> for i = 0; i < len(v); i++ { >> } >> >> As you can see, the loop merely uses that variable; it existed before >> the loop and continued to live on after it finished executing. >> >> To recap what others have already written, since the for loop's post >> statement is defined to be executed after each execution of the body >> (unless it was exited by means of executing `break` or `return`), that >> >> i++ >> >> statement gets executed, the condition evaluates to false, and the loop >> exits -- with the variable "i" having the value equal to len(v). >> >> One could do >> >> var x int >> >> for i := 0; i < len(v); i, x = i+1, x*2 { >> } >> >> and get even more interesting effect on the variable "x" after the loop >> finishes executing ;-) >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "golang-nuts" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/golang-nuts/Xi6W3H5mlto/unsubscribe >> <https://groups.google.com/d/topic/golang-nuts/Xi6W3H5mlto/unsubscribe>. >> To unsubscribe from this group and all its topics, send an email to >> golang-nuts...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout >> <https://groups.google.com/d/optout>. > > > This message is for the attention of the intended recipient(s) only. It may > contain confidential, proprietary and/or legally privileged information. Use, > disclosure and/or retransmission of information contained in this email may > be prohibited. If you are not an intended recipient, you are kindly asked to > notify the sender immediately (by reply e-mail) and to permanently delete > this message. Thank you. > > -- > You received this message because you are subscribed to a topic in the Google > Groups "golang-nuts" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/golang-nuts/Xi6W3H5mlto/unsubscribe > <https://groups.google.com/d/topic/golang-nuts/Xi6W3H5mlto/unsubscribe>. > To unsubscribe from this group and all its topics, send an email to > golang-nuts+unsubscr...@googlegroups.com > <mailto:golang-nuts+unsubscr...@googlegroups.com>. > For more options, visit https://groups.google.com/d/optout > <https://groups.google.com/d/optout>. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.