Hi everyone! this is Jimmy , and this is the third article in my series “Breaking Things with Go.” In this series, I document my journey through Jon Bodner’s Second Edition: Learning Go – An Idiomatic Approach to Real-World Go Programming and explore how to use Go in the most practical way I can
in this series the resources are the book itself, go documentation, and any AI model to clarify some things
lets Jump into it

we’re almost done with control structures except switch statements which exists in mostly every programming language
Switch Statements
I used to code C++ and C and i had my issues with my switch statements due to their limitation that can be switched but in Go is kinda different and more useful
- just like if statement we can declare a variable that is seen to all switch branches
- no need to use parentheses to the value we compare
- you can have multiple lines (case body) inside each case
- each case is considered a new block so if you declare a variable inside the block it is accessible within itself only
- you can specify multiple cases at once separated by comma that should be matched like
1, 2, 3, 4for example - fall-through means executing the next case body after current’s one without checking the condition
- there is no implicit fall-through in Go → meaning that switch will break after the first matched case execution
- you can do explicit fall-through using the keyword
fallthroughbut if you found yourself using it too much change your logic instead - if you specified a case and nothing inside its block nothing happens
- you can switch on any comparable type which mean all types except slices, maps, channels, functions, structs with any field of these types
- if you use break inside a case it will break this case only, but if you are inside a loop it won't break outside the loop that's why labeling is important
- case keyword is indented as the same switch keyword level
words := []string{"a", "cow", "smile", "gopher", "octopus", "anthropologist"}
for _, word := range words {
switch size := len(word); size {
case 1, 2, 3, 4:
fmt.Println(word, "is short word")
fallthrough
case 5:
fmt.Println(word, "perfect Length")
case 6, 7, 8, 9:
default:
fmt.Println(word, "too big")
}
}
Blank switches
so far the switched on values are the same like any other language so how go make it more useful ?
- Go support what’s known as Blank switches to replace the if else chains as a cleaner alternative
- in Blank statements the case is executed based on Boolean so we can put a condition in the case if it is evaluated to true executed, if no move on
here is how
x := 9
switch {
case x < 10:
fmt.Println(x, "less than 10") //executed
case x > 10:
fmt.Println(x, "larger than 10")
default:
fmt.Println("It's 10")
}
we didn’t specify what we are comparing to so it will execute based on the condition result and if there is two cases evaluated to true it will execute the first one and exit
look at this blank switch
words := []string{"hi", "salutaions", "hello"}
for _, word := range words {
switch wordLen := len(word); { // we are just declaring the wordlen but we didn't specify that we are comparing to it
case wordLen < 5:
fmt.Println(word, "small word")
case wordLen > 10:
fmt.Println(word, "long word")
default:
fmt.Println(word, "normal length")
}
}
you can’t mix between expression switch and blank switch
x := 10
switch x{ //comparing to an integer
case x>10: // found boolean so it is a compile-time error
//do something
}
favor the blank switch statements over if/else chains when you have multiple related cases
using switch makes it more readable
Goto statements
goto statements are dangerous cause they jump anywhere in a program so you might jump over variable definition or in the middle of set of statements in an if statement (without checking condition) so it exists in Go and it has couple rules but even you will follow this rules try to avoid using it if you can
- Jump that skip over variable declaration is forbidden
- Jump that go into an inner or parallel block is forbidden
a := 10
goto skip // error jumping over b declaration
b := 20
skip:
c := 30
fmt.Println(a, b, c)
if c > a {
goto inner // error jummping into an inner block
}
if a < b {
inner:
fmt.Println("a is less than b")
}
}
and here is a good use case for goto statement from the book itself
func main() {
a := rand.Intn(10)
for a < 100 {
if a%5 == 0 {
goto done
}
a = a*2 + 1
}
fmt.Println("do something when the loop compeletes casually")
done:
fmt.Println("do complicated stuff no matter why we left the loop")
fmt.Println(a)
}
i think the reason is the cleanup work after the logic not the logic itself is pretty easy this way i mean we can do the same logic using break and labeled for loop but we will have to add another flag to tell if it was terminated normally or because it found a number and then check this statement to decide which statement we will print
bottom line → try very hard to avoid using goto
Takes
- If you can read the code as choose exactly one of these → use
switch - If you read it as do this, then maybe also do that → use
if - you can’t mix expression switches and blank switches → causes compile time error
- avoid using goto statements unless you’re absolutely have to
Coming Next
the next break will be about functions in Go so stick around for next break where we will break more stuff
feel free to reach out to me
