Go if: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(30 intermediate revisions by the same user not shown)
Line 1: Line 1:
=External=
* https://go.dev/ref/spec#If_statements
=Internal=
=Internal=
* [[Go_Language#if_Statement|Go Language]]
* [[Go_Language#if_Statement|Go Language]]


=Overview=
=Overview=
The <code>if</code> statement specifies the conditional execution of two branches according to the value of a boolean expression. Optionally, the boolean expression [[#Statement_Precedes_Expression |may be preceded by an initialization statement]], which is executed before the expression is evaluated.
The <code>if</code> statement specifies the conditional execution of one, two or more branches according to the value of boolean expressions. Optionally, the boolean expression [[#Statement_Precedes_Expression |may be preceded by an initialization statement]], which is executed before the expression is evaluated.
===Simple If===
 
{{External|https://go.dev/ref/spec#If_statements}}
The statements to be executed must aways be encoded in braces. Mandatory braces encourage writing simple <code>if</code> statements on multiple lines.
 
=Simple <tt>if</tt>=
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if <condition> {
if <expression> {
  <statements>
    <statements>
}
}
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if x > 5 {
if x > 5 {
  println(x)
    println(x)
}
}
</syntaxhighlight>
</syntaxhighlight>
 
Note that because the lexer [[Go_Language#Semicolons|automatically inserts a semicolon]] after each token that may represent the end of statement, if it is followed by newline, we always must provide the opening brace on the same line as the expression.
===If/else===
=<tt>if</tt>/<tt>else</tt>=
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if <condition> {
if <condition> {
  <statements>
    <statements>
} else {
} else {
  <statements>
    <statements>
}
}
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if x > 5 {
if x > 5 {
  println(x)
    println(x)
} else {
} else {
  println("something else")
    println("something else")
}
}
</syntaxhighlight>
</syntaxhighlight>
<span id='Statement_Precedes_Expression'></span>A special <code>if</code> syntax supports the Go [[Go_Language_Error_Handling#If_Syntax_for_Handling_Errors|error handling idiom that relies on functions returning errors as result value]]:
 
If the <code>if</code> statement does not flow into the next statement, because the body ends in <code>break</code>, <code>continue</code> or most commonly <code>return</code>, the unnecessary <code>else</code> is omitted. This is a common situation when the code must guard agains a sequence of error conditions. The code reads well if the successful flow of control runs down the page eliminating error cases as they arise. Since error cases then to end in <code>return</code> statements, the resulting code needs no <code>else</code> statements:
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
var result ...
f, err := os.Open(name)
var err error
if err != nil {
if result, err = someFunc(); err != nil {
    return err
  // handle error
  return
}
}
// handle success
d, err := f.Stat()
...
if err != nil {
</syntaxhighlight>
    f.Close()
 
    return err
'''Avoid <code>else</code>''' in the idiom above. Do NOT write this:
 
<syntaxhighlight lang='go'>
if result, err := someFunc(); err {
  // handle error
  ...
} else { // BAD, avoid the "else"
  // handle success
  ... 
}
}
codeUsing(f, d)
</syntaxhighlight>
</syntaxhighlight>


===If/else if/else===
=<tt>if</tt>/<tt>else if</tt>/<tt>else</tt>=
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if <condition> {
if <condition> {
  <statements>
    <statements>
} else if <condition> {
} else if <condition> {
  <statements>
    <statements>
} else {
} else {
  <statements>
    <statements>
}
}
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
if x < 5 {
if x < 5 {
  println(x)
    println(x)
} else if x == 5 {
} else if x == 5 {
  println("is 5")
    println("is 5")
} else {
    println("something else")
}
</syntaxhighlight>
 
=<tt>if</tt> with Initialization Statement=
<code>if</code> accepts an initialization statement before the expression, which is commonly used to set up local variables that are then used in the expression and are also accessible in the entire <code>if</code> statement scope, which includes the subsequent [[Go_Language#if,_for,_switch_Blocks|<code>if</code>, <code>else if</code> and <code>else</code> blocks]]:
<syntaxhighlight lang='go'>
if <initialization-statement>; <expression> {
    <statements>
} else if <expression> {
    // variables declared by the initialization statements are visible here
    <statements>
} else <expression> {
    // variables declared by the initialization statements are visible here
    <statements>
}
 
</syntaxhighlight>
<syntaxhighlight lang='go'>
if a := compute(); a > 0 {
    fmt.Println("positive " + a)
} else {
  fmt.Println("negative " + a)
}
</syntaxhighlight>
The local variables declared in the initialization statement are only accessible in the expression and the subsequent <code>if</code> blocks.
 
==Error Handling Idiom with <tt>if</tt> Initialization Statement==
 
<span id='Statement_Precedes_Expression'></span>This syntax supports the Go [[Go_Language_Error_Handling#If_Syntax_for_Handling_Errors|error handling idiom that relies on functions returning errors as result value]]:
<syntaxhighlight lang='go'>
var result ...
var err error
if result, err = someFunc(); err != nil {
    // handle error
    return
}
// handle success
...
</syntaxhighlight>
 
The <code>if</code>/<code>else</code> alternative is:
<syntaxhighlight lang='go'>
if result, err := someFunc(); err {
    // handle error
    ...
} else {
} else {
  println("something else")
    // handle success, result is available in this block
    ... 
}
}
</syntaxhighlight>
</syntaxhighlight>
However, the form without <code>else</code>, which exits the function from the error handling block, is preferred, because makes the code easier to read.

Latest revision as of 01:41, 6 July 2024

External

Internal

Overview

The if statement specifies the conditional execution of one, two or more branches according to the value of boolean expressions. Optionally, the boolean expression may be preceded by an initialization statement, which is executed before the expression is evaluated.

The statements to be executed must aways be encoded in braces. Mandatory braces encourage writing simple if statements on multiple lines.

Simple if

if <expression> {
    <statements>
}
if x > 5 {
    println(x)
}

Note that because the lexer automatically inserts a semicolon after each token that may represent the end of statement, if it is followed by newline, we always must provide the opening brace on the same line as the expression.

if/else

if <condition> {
    <statements>
} else {
    <statements>
}
if x > 5 {
    println(x)
} else {
    println("something else")
}

If the if statement does not flow into the next statement, because the body ends in break, continue or most commonly return, the unnecessary else is omitted. This is a common situation when the code must guard agains a sequence of error conditions. The code reads well if the successful flow of control runs down the page eliminating error cases as they arise. Since error cases then to end in return statements, the resulting code needs no else statements:

f, err := os.Open(name)
if err != nil {
    return err 
}
d, err := f.Stat()
if err != nil {
    f.Close()
    return err 
}
codeUsing(f, d)

if/else if/else

if <condition> {
    <statements>
} else if <condition> {
    <statements>
} else {
    <statements>
}
if x < 5 {
    println(x)
} else if x == 5 {
    println("is 5")
} else {
    println("something else")
}

if with Initialization Statement

if accepts an initialization statement before the expression, which is commonly used to set up local variables that are then used in the expression and are also accessible in the entire if statement scope, which includes the subsequent if, else if and else blocks:

if <initialization-statement>; <expression> {
    <statements>
} else if <expression> {
    // variables declared by the initialization statements are visible here
    <statements>
} else <expression> {
    // variables declared by the initialization statements are visible here
    <statements>
}
if a := compute(); a > 0 {
    fmt.Println("positive " + a)
} else {
   fmt.Println("negative " + a)
}

The local variables declared in the initialization statement are only accessible in the expression and the subsequent if blocks.

Error Handling Idiom with if Initialization Statement

This syntax supports the Go error handling idiom that relies on functions returning errors as result value:

var result ...
var err error
if result, err = someFunc(); err != nil {
    // handle error
    return
}
// handle success
...

The if/else alternative is:

if result, err := someFunc(); err {
    // handle error
    ...
} else {
    // handle success, result is available in this block
    ...  
}

However, the form without else, which exits the function from the error handling block, is preferred, because makes the code easier to read.