Skip to content

Conditional Control ​

Before You Start

  • Applies to: Go 1.21+ (examples verified with Go 1.22) · Prerequisites: Variables · Read time: about 5 min

In Go, there are three conditional control statements: if, switch, and select. select is relatively special compared to the other two and will not be covered in this section. It will be explained in the concurrency chapter.

if else ​

if else has at most two branches. The syntax is as follows:

go
if expression {

}

Or

go
if expression {

}else {

}

expression must be a boolean expression, meaning the result must be either true or false, it must be a boolean value. Here are some examples:

go
func main() {
   a, b := 1, 2
   if a > b {
      b++
   } else {
      a++
   }
}

You can also write more complex expressions. When necessary to improve readability, you should use parentheses to explicitly indicate which operations should be calculated first.

go
func main() {
   a, b := 1, 2
    if a<<1%100+3 > b*100/20+6 { // (a<<1%100)+3 > (b*100/20)+6
      b++
   } else {
      a++
   }
}

At the same time, if statements can also contain some simple statements, for example:

go
func main() {
  if x := 1 + 1; x > 2 {
    fmt.Println(x)
  }
}

else if ​

else if statements can create more branches based on if else. The syntax is as follows:

go
if expression1 {

}else if expression2 {

}else if expression3 {

}else {

}

During execution, each expression is evaluated from left to right, and the entire if statement is evaluated from top to bottom. An example of grading based on scores is as follows. The first approach:

go
func main() {
   score := 90
   var ans string
   if score == 100 {
      ans = "S"
   } else if score >= 90 && score < 100 {
      ans = "A"
   } else if score >= 80 && score < 90 {
      ans = "B"
   } else if score >= 70 && score < 80 {
      ans = "C"
   } else if score >= 60 && score < 70 {
      ans = "E"
   } else if score >= 0 && score < 60 {
      ans = "F"
   } else {
      ans = "nil"
   }
   fmt.Println(ans)
}

The second method takes advantage of the premise that if statements are evaluated from top to bottom, so the code is more concise.

go
func main() {
  score := 90
  var ans string
  if score >= 0 && score < 60 {
    ans = "F"
  } else if score < 70 {
    ans = "D"
  } else if score < 80 {
    ans = "C"
  } else if score < 90 {
    ans = "B"
  } else if score < 100 {
    ans = "A"
  } else if score == 100 {
    ans = "S"
    }else {
        ans = "nil"
    }
  fmt.Println(ans)
}

switch ​

switch is also a multi-branch conditional statement. The syntax is as follows:

go
switch expr {
  case case1:
    statement1
  case case2:
    statement2
  default:
    default statement
}

A simple example:

go
func main() {
   str := "a"
   switch str {
   case "a":
      str += "a"
      str += "c"
   case "b":
      str += "bb"
      str += "aaaa"
   default: // When all cases don't match, the default branch will be executed
      str += "CCCC"
   }
   fmt.Println(str)
}

You can also write some simple statements before the expression, such as declaring new variables:

go
func main() {
  switch num := f(); { // equivalent to switch num := f(); true {
  case num >= 0 && num <= 1:
    num++
  case num > 1:
    num--
    fallthrough
  case num < 0:
    num += num
  }
}

func f() int {
  return 1
}

switch statements can also have no expression at the entry point.

go
func main() {
   num := 2
   switch { // equivalent to switch true {
   case num >= 0 && num <= 1:
      num++
   case num > 1:
      num--
   case num < 0:
      num *= num
   }
   fmt.Println(num)

Use the fallthrough keyword to continue executing the next adjacent branch.

go
func main() {
   num := 2
   switch {
   case num >= 0 && num <= 1:
      num++
   case num > 1:
      num--
      fallthrough // After executing this branch, continue to execute the next branch
   case num < 0:
      num += num
   }
   fmt.Println(num)
}

label ​

Label statement, labels a block of code, can be a target for goto, break, continue. Example:

go
func main() {
  A:
    a := 1
  B:
    b := 2
}

Simply using labels has no meaning. It needs to be combined with other keywords to be useful.

goto ​

goto transfers control to the statement with the corresponding label in the same function. Example:

go
func main() {
   a := 1
   if a == 1 {
      goto A
   } else {
      fmt.Println("b")
   }
A:
   fmt.Println("a")
}

In practical applications, goto is rarely used. Jumping around reduces code readability, and performance is also a concern.

Complete Example ​

The program below runs as-is: copy it into a file and execute go run main.go, or paste it into the Go Playground.

go
package main

import "fmt"

func classify(n int) string {
	// The variable v is scoped to the if/else chain only
	if v := n * 2; v > 10 {
		return "large"
	} else if v > 4 {
		return "medium"
	}
	return "small"
}

func describe(v any) string {
	switch x := v.(type) {
	case nil:
		return "nil"
	case int:
		return fmt.Sprintf("int %d", x)
	case string:
		return "string " + x
	default:
		return "unknown"
	}
}

func main() {
	fmt.Println(classify(3), classify(6))

	for _, v := range []any{nil, 7, "go", 3.14} {
		fmt.Println(describe(v))
	}
}

Expected output:

text
medium large
nil
int 7
string go
unknown

Common Pitfalls ​

  • Conditions must be bool. if 1 { } does not compile, and Go has no ternary operator.
  • Init statements leak nothing. Variables declared in the if header are not visible after the chain.
  • switch breaks automatically. Add fallthrough explicitly if you need it — and it cannot appear in the last case.
  • In a type switch, the variable's type changes per case. With case int, string: the variable keeps the interface type, so you still need a type assertion.
  • goto cannot jump over variable declarations, which is a common cause of confusing compile errors.

Change Log ​

  • 2026-10-14: Added "Before You Start" notes, a complete runnable example with expected output, common pitfalls, and this change log.

Golang by www.golangdev.cn · Adapted in part from Golang 中文学习文档 (MIT, © 寒江蓑笠翁)