Go for: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(41 intermediate revisions by the same user not shown)
Line 8: Line 8:
=Overview=
=Overview=


There are four <code>for</code> syntactical forms: the generic, C-like syntax with an init section, a condition and post section, a form where the iteration is controlled by a <code>range</code> keyword, a form with just one condition, and a form that iterates forever, unless the body contains statements that exit the loop.
There are four <code>for</code> syntactical forms: the generic, C-like syntax [[#Form_1|with an init section, a condition and post section]], a form where the [[#Form_2|iteration is controlled by a <code>range</code> keyword]], a form with [[#Form_3|just one condition]], and a form that [[#Form_4|iterates forever]], unless the body contains statements that exit the loop. There are no <code>do</code> or <code>while</code> loops in Go. In all four causes, the <code>for</code> statement specifies repeated execution of a [[Go_Language#Blocks|block]].


=<span id='Form_1'></span><span id='for_Controlled_by_a_%22for%22_Clause'></span><tt>for init; condition; post {}</tt>=
The most generic syntax of the <code>for</code> statement is a C-like syntax, with an init, condition and post statements:
<font size='-1.5'>
<font color=darkgreen><b>for</b></font> <font color=teal><i><init></i></font>; <font color= teal ><i><condition></i></font>; <font color= teal ><I><post></i></font> {
  <i><statements></i>
}
</font>
The <code>for</code> loop executes the <code>init</code> statement and then iterates while the <code>condition</code> evaluates to <code>true</code>. The <code>condition</code> is an expression evaluated on each iteration. <code>condition</code> must evaluate to a boolean. If the expression evaluates to <code>true</code>, the block is executed. At the end of each block execution, the <code>post</code> statement is executed.


The most generic syntax of the <code>for</code> statement is:
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
for <init>; <condition>; <update> {
for i := 0; i < 3; i ++ {
   <statements>
   println(i)
}
}
</syntaxhighlight>
</syntaxhighlight>
The <code>for</code> loop executes the <code>init</code> statement and then iterates while the <code>condition</code> evaluates to true. The <code>condition</code> is an expression evaluated on each iteration. <code>condition</code> must evaluate to a boolean. If the expression evaluates to true, the block is executed. At the end of each block execution, the <code>update</code> statement is executed.


The <code>init</code> statement is usually a variable declaration and initialization. Multiple variables can be declared at the same time (for more details, see [[#Short_Variable_Declaration|Short Variable Declaration]] section above):
The <code>init</code> statement is usually a variable declaration and initialization. Multiple variables can be declared at the same time (see [[Go_Language#Short_Variable_Declaration|Short Variable Declaration]]):
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
for i, j := 0, 0; ... {
for i, j := 0, 0; ... {
Line 28: Line 32:
</syntaxhighlight>
</syntaxhighlight>


Examples:
All of the <code>init</code>, <code>condition</code> and <code>post</code> sections are optional and can be dropped. If we drop the <code>init</code> and the <code>post</code> section, we get the [[#Form_3|<code>for <I><condition></I></code>]] form. If we drop all of them, we get the [[#Form_4|<code>for {}</code>]] form.


=<span id='Form_2'></span><span id='for_Controlled_by_a_%22range%22_Clause'></span><tt>for range {}</tt>=
To iterate over an iterable structure, such as an array, slice, string or map, or values received on a channel,  use <code>[[Go_Keyword_range#Overview|range]]</code>. For each entry, <code>range</code> assigns iteration values to corresponding iteration variables if present and then executes the block. For arrays, maps and slices, <code>for</code> exits when all values are returned. For channels, <code>for</code> exists when the channel is closed.
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
for i := 0; i < 3; i ++ {
// map
   println(i)
ss := []string{"a", "b", "c"}
for key, value := range ss {
   ...
}
}
</syntaxhighlight>
</syntaxhighlight>
All three expressions (initialization, condition and update) are optional:
If you only need the first item in a range (the key or the index), the second can be dropped:
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
i := 0
// map
for i < 3 {
ss := ...
   println(i)
for key := range ss {
  i ++
   ...
}
}
</syntaxhighlight>
</syntaxhighlight>
If you only need the second item in the range (the value), use a blank identifier to discard the first:
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
i := 0
// slice
for  {
ss := ...
  if i == 3 {
for _, value := range ss {
    break
  }
  println(i)
  i ++
}
</syntaxhighlight>
 
To iterate over an iterable structure, use <code>[[Go_Keyword_range#Overview|range]]</code>:
<syntaxhighlight lang='go'>
ss := []string{"a", "b", "c"}
for index, value := range ss {
   ...
   ...
}
}
Line 69: Line 68:
}
}
</syntaxhighlight>
</syntaxhighlight>
To get consecutive integers in the loop, use this syntax (Go 1.22 and newer):
To get consecutive integers in the loop, use this syntax (Go 1.22 and newer):
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
Line 79: Line 77:
<code>for</code> can be used to [[Go_Channels#Iterative_Read_from_a_Channel_(Ranging_over_a_Channel)|iterate over values received from a channel]].
<code>for</code> can be used to [[Go_Channels#Iterative_Read_from_a_Channel_(Ranging_over_a_Channel)|iterate over values received from a channel]].


=<tt>for</tt> Controlled by a Condition=
For strings, <code>range</code> breaks out individual Unicode code points by parsing UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD.


<pre>
=<span id='for_Controlled_by_a_Condition'></span><span id='Form_3'></span><tt>for condition {}</tt>=
for a < b {
<font size='-1.5'>
    a *= 2
<font color=darkgreen><b>for</b></font> <font color= teal ><i><condition></i></font> {
  <i><statements></i>
}
</font>
The condition is evaluated before each iteration. If the condition is absent, is equivalent with <tt>true</tt>, and the form syntax becomes [[#Form_4|<code>for {}</code>]]. <code>for <I>condition</I> {}</code> is equivalent with <code>while</code> in other languages.
<syntaxhighlight lang='go'>
i := 0
for i < 3 {
  println(i)
  i ++
}
}
</pre>
</syntaxhighlight>


The condition is evaluated before each iteration. If the condition is absent, is equivalent with <tt>true</tt>.
=<span id='Form_4'></span><tt>for {}</tt>=
 
<syntaxhighlight lang='go'>
<pre>
i := 0
for {
for {
     // do this forever
  if i == 3 {
     break
  }
  println(i)
  i ++
}
}
</pre>
</syntaxhighlight>
=Iteration Variable Scope=
<font color=darkkhaki>TODO</font>.


=<tt>for</tt> Controlled by a "for" Clause=
=Use Cases=


<tt>for</tt> controlled by a "for" clause is equivalent with [[#for_Controlled_by_a_Condition|for controlled by a condition]], but it has an extra ''init'' and ''post'' statement:
==Iterating over a slice from a non-zero index==
 
<syntaxhighlight lang='go'>
<pre>
for i := 0; i < 10; i++ {
    // do something
}
</pre>
 
=<tt>for</tt> Controlled by a "range" Clause=
 
A <tt>for</tt> statement with a "range" clause iterates through all entries of an array, slice, string or map, or values received on a channel. For each entry it assigns iteration values to corresponding iteration variables if present and then executes the block.
 
For arrays, maps and slices, <tt>for</tt> exits when all values are returned. For channels, <tt>for</tt> exists when the channel is closed.
 
<pre>
var a [10]string
 
for i, s := range a {
 
// type of i is int
// type of s is string
// and s == a[i]
 
      // do something
}
</pre>
 
More about <tt>range</tt>:
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:<tt>[[Go Keyword range|range]]</tt>
</blockquote>
 
=Iterating over a slice from a non-zero index=
 
<pre>
for index := 5; index < len(slice); index ++ {
for index := 5; index < len(slice); index ++ {
     // slice[index] ...
     // slice[index] ...
}
}
</pre>
</syntaxhighlight>
==Reverse a Slice==
<syntaxhighlight lang='go'>
for i, j := 0, len(a) - 1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}
</syntaxhighlight>

Latest revision as of 00:12, 13 August 2024

External

Internal

Overview

There are four for syntactical forms: the generic, C-like syntax with an init section, a condition and post section, a form where the iteration is controlled by a range keyword, a form with just one condition, and a form that iterates forever, unless the body contains statements that exit the loop. There are no do or while loops in Go. In all four causes, the for statement specifies repeated execution of a block.

for init; condition; post {}

The most generic syntax of the for statement is a C-like syntax, with an init, condition and post statements:

for <init>; <condition>; <post> {
  <statements>
}

The for loop executes the init statement and then iterates while the condition evaluates to true. The condition is an expression evaluated on each iteration. condition must evaluate to a boolean. If the expression evaluates to true, the block is executed. At the end of each block execution, the post statement is executed.

for i := 0; i < 3; i ++ {
  println(i)
}

The init statement is usually a variable declaration and initialization. Multiple variables can be declared at the same time (see Short Variable Declaration):

for i, j := 0, 0; ... {
  ...
}

All of the init, condition and post sections are optional and can be dropped. If we drop the init and the post section, we get the for <condition> form. If we drop all of them, we get the for {} form.

for range {}

To iterate over an iterable structure, such as an array, slice, string or map, or values received on a channel, use range. For each entry, range assigns iteration values to corresponding iteration variables if present and then executes the block. For arrays, maps and slices, for exits when all values are returned. For channels, for exists when the channel is closed.

// map
ss := []string{"a", "b", "c"}
for key, value := range ss {
  ...
}

If you only need the first item in a range (the key or the index), the second can be dropped:

// map
ss := ...
for key := range ss {
  ...
}

If you only need the second item in the range (the value), use a blank identifier to discard the first:

// slice
ss := ...
for _, value := range ss {
  ...
}

If the values of the iterable structure are not important, and only the number of elements matters, this syntax can also be used:

ss := []string{"a", "b", "c"}
for range ss {
  ...
}

To get consecutive integers in the loop, use this syntax (Go 1.22 and newer):

for i := range 10 {
  println(i)
}

for can be used to iterate over values received from a channel.

For strings, range breaks out individual Unicode code points by parsing UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD.

for condition {}

for <condition> {
  <statements>
}

The condition is evaluated before each iteration. If the condition is absent, is equivalent with true, and the form syntax becomes for {}. for condition {} is equivalent with while in other languages.

i := 0
for i < 3 {
  println(i)
  i ++
}

for {}

i := 0
for  {
  if i == 3 {
    break
  }
  println(i)
  i ++
}

Iteration Variable Scope

TODO.

Use Cases

Iterating over a slice from a non-zero index

for index := 5; index < len(slice); index ++ {
    // slice[index] ...
}

Reverse a Slice

for i, j := 0, len(a) - 1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}