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.

Reply via email to