Goの構文がC言語と同様だとか、似ているとか言われるのを聞いたことがあると思います。
間違いです。
構文的にも、意味論的にもC言語とGoでは大きな隔たりがあり、「同様」や「似ている」の言葉の幅を考えても明確に間違いです。
Goでは、条件分岐は、if文などで行えます。C言語と同様では有りません。。
C言語にある if や else や switch などの機能は、Goにもあります。しかし、たとえばスコープルール1つをとってもC言語にない要素をGoはもっています。
C言語のif文:
    if ( 条件式 ) 文
Goのif文:
    if 条件式 {
       文
    }
また、Goでは条件式は真偽値である必要があり、i != 0 を単に i と書くことはできません。
整数値と真偽値の間には自動変換がなく、キャストもできません。そのため、比較演算子や論理演算子を使って条件式を書く必要があります。
[https://play.golang.org/p/iTj_he9lLIZ コード例]:
package main
import (
	"fmt"
	"math"
)
func main() {
	if num := math.NaN(); num < 0.0 {
		fmt.Println("負")
	} else if num > 0.0 {
		fmt.Println("正")
	} else if num == 0.0 {
		fmt.Println("零")
	} else {
		fmt.Println("NaN")
	}
}
実行結果:
NaN
if の条件式の前に「単純な文」を書くことができます（必須ではありません）。
上の例では簡素な変数宣言で、変数 num を宣言して math.NaN() で初期化しています（スコープはif文が終わるまでです）。
math.NaN() は NaN（非数）を返す関数です。
NaN はfloat64型で、全ての浮動所数点数と比較したとき必ず false になる変わった値です。
NaN == NaN も false です。
このため浮動小数点数がNaNであるかは math.IsNaN() を使います。
if文は条件がfalseだったとき実行する else 節を持つことができます（必須ではありません）。
else 節は、さらに別の条件のif節を持つことができます（必須ではありません）。
{{コラム|Goには条件演算子はありません|
Goには条件演算子（式 ? 値 : 値）はありません。
このため、条件演算子を書きたくなるケースでは、if文を使うことになります。
別解として、mapを使う方法があります。
[https://play.golang.org/p/LE4oWslBmSc コード例]:
package main
import (
	"fmt"
	"unsafe"
)
func main() {
	n := 0x5a5a5a5a5a5a5a5a
	size := int(unsafe.Sizeof(n)) * 8
	for i := 0; i < size; i++ {
		if (1 << (size - i - 1) & n) == 0 {
			fmt.Print("●")
		} else {
			fmt.Print("○")
		}
	}
	fmt.Println()
	m := map[bool]string{false: "●", true: "○"}
	for i := 0; i < size; i++ {
		fmt.Print(m[(1<<(size-i-1)&n) != 0])
	}
	fmt.Println()
}
実行結果:
●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●
●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●●○●○○●○●
switch文をつかうと複雑になったif文を簡素に書換えることができます。
[https://play.golang.org/p/bXQaelJwaO9 コード例]:
package main
import (
	"fmt"
	"math"
)
func main() {
	switch num := math.NaN(); {
	case num < 0.0:
		fmt.Println("負")
	case num > 0.0:
		fmt.Println("正")
	case num == 0.0:
		fmt.Println("零")
	default :
		fmt.Println("NaN")
	}
}
実行結果:
NaN
if文のコード例をswitch文に置換えてみました。
switch文の冒頭:
	switch num := math.NaN(); {
	switch num := math.NaN(); true {
の省略形で、if文と同じく「単純な文」を書くことができます（必須ではありません）。
上の例では簡素な変数宣言で、変数 num を宣言して math.NaN() で初期化しています（スコープはswitch文が終わるまでです）。
Cファミリーの言語を知っている人ならば、break がないのが気になると思いますが、Goのswitch文のcase節ではbreakが標準動作で、フォールスルーさせるためには、fallthrough 文を使いますJavaの -> と同じふるまいをします。ただしGoのswitch文はJavaの様に文の値を持ちません。。
Goのcase文の式には、定数以外も書くこともでき上の例では（動的な）比較演算が使われています。
この例では（暗黙の）true と比較しているので、最初にtrueになったcaseに対応する文が実行されるのですが、numはNaNでどの条件にも当てはまらないので default 節まで落ちてきます。
select文はswitch文と似ていますが、通信チャンネルの並行待ちを行います。
[https://paiza.io/projects/WoJ_v8HVA9Apbht5JtDckQ?language=go Select文を使ったタイムアウト]:
package main
import (
        "fmt"
        "time"
)
func main() {
        done := make(chan bool)
        go func(s int) {
                fmt.Printf("#%d..do\n", s)
                time.Sleep(time.Duration(s) * time.Second)
                fmt.Printf("#%d..done\n", s)
                done <- true
        }(2)
        select {
        case <-done:
                fmt.Println("Done!")
        case <-time.After(1 * time.Second):
                fmt.Println("Timeout!")
        }
}
実行結果:
Timeout!
Goでは、For文がイテレート（繰返し；反復）する唯一の構文です(Goには、doやwhileはありません)。
For文には素朴なFor文と他の言語で言うForeach文の2種類があります。
素朴なFor文: for i := 0; i < n; i++ {
	/* 繰返す処理 */
}
Foreach文的なFor文: 
for i, e := range collection {
	/* 繰返す処理 */
}
まず、素朴のFor文の使い方を説明します。
for 初期化; 条件式; ポスト文 {
	/* 繰返す処理 */
}
これをIf文とGoto文を使って書き直すと。
{
	初期化
top:
	if !(条件式) {
		goto bottom
	}
	/* 繰返す処理 */
	ポスト文
	goto top
bottom:
}
''初期化''および''ポスト文''は単純な文（簡単な変数宣言、インクリメント文、代入、関数呼び出し）でなくてはなりません。
また、条件式は論理式 (trueかfalseを返す式)でなくてはならず、省略されると true が仮定されます。
	/* 繰返す処理 */
}
と表現します。
[https://play.golang.org/p/5YquULYfrQ6 コード例]:
package main
import "fmt"
func main() {
	for i := 1; i < 6; i++ {
		fmt.Printf("%d * 2 = %d\n", i, i*2)
	}
}
実行結果:
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6
4 * 2 = 8
5 * 2 = 10
For文の三項はそれぞれ省略できます。
GoにもForeach文的なFor文があり、For文のrange節を伴った構文を使用します。
スライス・配列・文字列・マップ・チェンネルなどのコレクションの要素を1つづつ（breakやreturnで中途退出しない限り）すべてイテレートします。
[https://play.golang.org/p/utKbU8y5gfd スライス]:
package main
import "fmt"
func main() {
	s := make([]int, 6)
	for i, _ := range s {
		s[i] = 10 * i
	}
	fmt.Printf("%#v\n", s)
	for i, e := range s {
		fmt.Println(i, e)
	}
}
実行結果:
[]int{0, 10, 20, 30, 40, 50}
0 0
1 10
2 20
3 30
4 40
5 50
この例ではintのスライス s を宣言し、最初のForで各要素に添え字の10倍の値を代入しています。
range 節は多値代入の右辺となり、左辺の最初に添え字が次に要素の値が入ります。
不要な項は、8行目のようにブランク識別子( _ )を起きます。
[https://play.golang.org/p/dDGwALQ6u8g 配列]:
package main
import "fmt"
func main() {
	s := [6]int{}
	for i, _ := range s {
		s[i] = 10 * i
	}
	fmt.Printf("%#v\n", s)
	for i, e := range s {
		fmt.Println(i, e)
	}
}
実行結果:
[]int{0, 10, 20, 30, 40, 50}
0 0
1 10
2 20
3 30
4 40
5 50
宣言部分以外は、スライスと同じです。実行結果も全く同じです。
このようにスライスと配列は区別しにくいですが、配列は append で要素数を増したり、部分要素を返したりできません（部分要素を得ようとするとスライスが返る）。
性能的には、スライスは要素のアクセスは線形時間 O(n)、配列の要素のアクセスは定数時間 O(1)であることが大きな違いです。
配列 s をスライスに変換するには、s[:]とします。
スライスを配列に変換する方法は、現時点(go-1.17.1)ではありません（配列の要素数はコンパイル時に確定することが要求されている）。
[https://play.golang.org/p/USwXt9hEPi0 文字列]:
package main
import "fmt"
func main() {
	s := "abcd"
	fmt.Printf("%#v\n", s)
	for i, e := range s {
		fmt.Println(i, e)
	}
	for _, e := range s {
		fmt.Print(string(e))
	}
}
実行結果:
"abcd"
0 97
1 98
2 99
3 100
abcd
文字列にFor・rangeを適用するとインデックスと1文字をイテレートします。
Rune型は整数型なので単純に文字列化すると数字になります。
Rune型を文字コード（厳密にはコードポイント）として文字化するには、string() で型変換します。
[https://play.golang.org/p/_mZJ5xsEgEm マップ]:
package main
import "fmt"
import "sort"
func main() {
	s := map[int]string{}
	for i := 0; i < 6; i++ {
		s[i] = fmt.Sprintf("str%v", 10*i)
	}
	fmt.Printf("%#v\n", s)
	for i, e := range s {
		fmt.Println(i, e)
	}
	keys := []int{}
	for i := range s {
		keys = append(keys, i)
	}
	fmt.Printf("%#v\n", keys)
	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
	fmt.Printf("%#v\n", keys)
	for i := 0; i < len(keys); i++ {
		fmt.Println(i, s[i])
	}
}
実行結果:
map[int]string{0:"str0", 1:"str10", 2:"str20", 3:"str30", 4:"str40", 5:"str50"}
2 str20
3 str30
4 str40
5 str50
0 str0
1 str10
[]int{4, 5, 0, 1, 2, 3}
[]int{0, 1, 2, 3, 4, 5}
0 str0
1 str10
2 str20
3 str30
4 str40
5 str50
マップはキーとマップに様々な型を使えますが、１つのマップではキー・値それぞれの型はすべて一致している必要があります。
マップの要素へのアクセスは定数時間 O(1)です。
マップにFor文を適用した場合、すべてのキーと値のペアを順にイテレートできますが、順序は不定です。
キーの値順に要素を取り出したい場合は、一旦すべてのキーをスライスに取り出し、そのスライスをソートした上で、スライスをループさせることで実現します。
[https://play.golang.org/p/q0vXC0MFreF チェンネル]:
package main
import "fmt"
func main() {
	c := make(chan int)
	go func() {
		defer close(c)
		for i := 0; i < 5; i++ {
			c <- i
		}
	}()
	for v := range c {
		fmt.Println(v)
	}
}
実行結果:
0
1
2
3
4
For・rangeにチェンネルを適用するとクローズされるまで受信した値をイテレートします。
また、C言語などと同様にGoでも、Break文やReturn文などがforブロック中（{ } の内部）にあれば、すべての要素をイテレートする前にFor文から脱出します。
[https://play.golang.org/p/4dTQLVE_3jf Continue文 Break文 Return文]:
package main
import "fmt"
func main() {
	for i := 0; i < 5; i++ {
		if i == 2 {
			continue
		}
		fmt.Print(i)
	}
	fmt.Println()
	for i := 0; i < 5; i++ {
		if i == 2 {
			break
		}
		fmt.Print(i)
	}
	fmt.Println()
	for i := 0; i < 5; i++ {
		if i == 2 {
			return
		}
		fmt.Print(i)
	}
	fmt.Println("Can't reach it.")
}
実行結果:
0134
01
01