Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Go Programming - From Beginner to Professional

You're reading from   Go Programming - From Beginner to Professional Learn everything you need to build modern software using Go

Arrow left icon
Product type Paperback
Published in Mar 2024
Publisher Packt
ISBN-13 9781803243054
Length 680 pages
Edition 2nd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Samantha Coyle Samantha Coyle
Author Profile Icon Samantha Coyle
Samantha Coyle
Arrow right icon
View More author details
Toc

Table of Contents (30) Chapters Close

Preface 1. Part 1: Scripts
2. Chapter 1: Variables and Operators FREE CHAPTER 3. Chapter 2: Command and Control 4. Chapter 3: Core Types 5. Chapter 4: Complex Types 6. Part 2: Components
7. Chapter 5: Functions – Reduce, Reuse, and Recycle 8. Chapter 6: Don’t Panic! Handle Your Errors 9. Chapter 7: Interfaces 10. Chapter 8: Generic Algorithm Superpowers 11. Part 3: Modules
12. Chapter 9: Using Go Modules to Define a Project 13. Chapter 10: Packages Keep Projects Manageable 14. Chapter 11: Bug-Busting Debugging Skills 15. Chapter 12: About Time 16. Part 4: Applications
17. Chapter 13: Programming from the Command Line 18. Chapter 14: File and Systems 19. Chapter 15: SQL and Databases 20. Part 5: Building For The Web
21. Chapter 16: Web Servers 22. Chapter 17: Using the Go HTTP Client 23. Part 6: Professional
24. Chapter 18: Concurrent Work 25. Chapter 19: Testing 26. Chapter 20: Using Go Tools 27. Chapter 21: Go in the Cloud 28. Index 29. Other Books You May Enjoy

Enums

Enums are a way of defining a fixed list of values that are all related. Go doesn’t have a built-in type for enums, but it does provide tools such as iota to let you define your own using constants. We’ll explore this now.

For example, in the following code, we have the days of the week defined as constants. This code is a good candidate for Go’s iota feature:

…
const (
  Sunday  = 0
  Monday  = 1
  Tuesday = 2
  Wednesday = 3
  Thursday = 4
  Friday  = 5
  Saturday = 6
)
…

With iota, Go helps us manage lists just like this. Using iota, the following code is equal to the preceding code:

…
const (
  Sunday = iota
  Monday
  Tuesday
  Wednesday
  Thursday
  Friday
  Saturday
)
…

Now, we have iota assigning the numbers for us. Using iota makes enums easier to create and maintain, especially if you need to add a new value to the middle of the code later. Order matters when using iota as it is an identifier that tells the Go compiler to start the first value at 0 and increment by 1 for each subsequent value in the case of this example. With iota, you can skip values using _, start with a different offset, and even use more complicated calculations.

Next, we’ll take a detailed look at Go’s variable scoping rules and how they affect how you write code.

Scope

All the variables in Go live in a scope. The top-level scope is the package scope. A scope can have child scopes within it. There are a few ways a child scope gets defined; the easiest way to think about this is that when you see {, you are starting a new child scope, and that child scope ends when you get to a matching }. The parent-child relationship is defined when the code compiles, not when the code runs. When accessing a variable, Go looks at the scope the code was defined in. If it can’t find a variable with that name, it looks in the parent scope, then the grandparent scope, all the way until it gets to the package scope. It stops looking once it finds a variable with a matching name or raises an error if it can’t find a match.

To put it another way, when your code uses a variable, Go needs to work out where that variable was defined. It starts its search in the scope of the code using the variable it’s currently running in. If a variable definition using that name is in that scope, then it stops looking and uses the variable definition to complete its work. If it can’t find a variable definition, then it starts walking up the stack of scopes, stopping as soon as it finds a variable with that name. This searching is all done based on a variable name. If a variable with that name is found but is of the wrong type, Go raises an error.

In this example, we have four different scopes, but we define the level variable once. This means that no matter where you use level, the same variable is used:

package main
import "fmt"
var level = "pkg"
func main() {
  fmt.Println("Main start :", level)
  if true {
    fmt.Println("Block start :", level)
    funcA()
  }
}
func funcA() {
  fmt.Println("funcA start :", level)
}

The following is the output displaying variables when using level:

Main start : pkg
Block start : pkg
funcA start : pkg

In this example, we’ve shadowed the level variable. This new level variable is not related to the level variable in the package scope. When we print level in the block, the Go runtime stops looking for variables called level as soon as it finds the one defined in main. This logic results in a different value getting printed out once that new variable shadows the package variable. You can also see that it’s a different variable because it’s a different type, and a variable can’t have its type changed in Go:

package main
import "fmt"
var level = "pkg"
func main() {
  fmt.Println("Main start :", level)
  // Create a shadow variable
  level := 42
  if true {
    fmt.Println("Block start :", level)
    funcA()
  }
  fmt.Println("Main end :", level)
}
func funcA() {
  fmt.Println("funcA start :", level)
}

The following is the output:

Main start : pkg
Block start : 42
funcA start : pkg
Main end : 42

Go’s static scope resolution comes into play when we call funcA. That’s why, when funcA runs, it still sees the package scope’s level variable. The scope resolution doesn’t pay attention to where funcA gets called.

You can’t access variables defined in a child scope:

package main
import "fmt"
func main() {
  {
    level := "Nest 1"
    fmt.Println("Block end :", level)
  }
  // Error: undefined: level
  //fmt.Println("Main end  :", level)
}

The following is the output:

Figure 1.23: Output displaying an error

Figure 1.23: Output displaying an error

Activity 1.03 – message bug

The following code doesn’t work. The person who wrote it can’t fix it, and they’ve asked you to help them. Can you get it to work?

package main
import "fmt"
func main() {
  count := 5
  if count > 5 {
    message := "Greater than 5"
  } else {
    message := "Not greater than 5"
  }
  fmt.Println(message)
}

Follow these steps:

  1. Run the code and see what the output is.
  2. The problem is with message; make a change to the code.
  3. Rerun the code and see what difference it makes.
  4. Repeat this process until you see the expected output.

    The following is the expected output:

    Not greater than 5

In this activity, we saw that where you define your variables has a big impact on the code. Always think about the scope you need your variables to be in when defining them.

In the next activity, we are going to look at a similar problem that is a bit trickier.

Activity 1.04 – bad count bug

Your friend is back, and they have another bug in their code. This code should print true, but it’s printing false. Can you help them fix the bug?

package main
import "fmt"
func main() {
  count := 0
  if count < 5 {
    count := 10
    count++
  }
  fmt.Println(count == 11)
}

Follow these steps:

  1. Run the code and see what the output is.
  2. The problem is with count; make a change to the code.
  3. Rerun the code and see what difference it makes.
  4. Repeat this process until you see the expected output.

The following is the expected output:

True
You have been reading a chapter from
Go Programming - From Beginner to Professional - Second Edition
Published in: Mar 2024
Publisher: Packt
ISBN-13: 9781803243054
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime