Search icon CANCEL
Subscription
0
Cart icon
Cart
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Go Programming - From Beginner to Professional - Second Edition

You're reading from  Go Programming - From Beginner to Professional - Second Edition

Product type Book
Published in Mar 2024
Publisher Packt
ISBN-13 9781803243054
Pages 680 pages
Edition 2nd Edition
Languages
Author (1):
Samantha Coyle Samantha Coyle
Profile icon Samantha Coyle
Toc

Table of Contents (30) Chapters close

Preface 1. Part 1: Scripts
2. Chapter 1: Variables and Operators 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

Declaring variables

Now that you’ve had a glimpse of Go and completed your first exercise, we’re going to dive deep. Our first stop on our journey is variables.

A variable holds data for you temporarily so that you can work with it. When you declare a variable, it needs four things: a statement that you are declaring a variable, a name for the variable, the type of data it can hold, and an initial value for it. Fortunately, some of the parts are optional, but that also means there’s more than one way of defining a variable.

Let’s cover all the ways you can declare a variable.

Declaring a variable using var

Using var is the foundational way to declare a variable. Every other way we’ll cover is a variation of this approach, typically by omitting parts of this definition. A full var definition with everything in place looks like this:

var foo string = "bar"

The key parts are var, foo, string, and = "bar":

  • var is our declaration that we are defining a variable
  • foo is the name of the variable
  • string is the type of the variable
  • = "bar" is its initial value

Exercise 1.02 – declaring a variable using var

In this exercise, we’ll declare two variables using the full var notation. Then, we’ll print them to the console. You’ll see that you can use the var notation anywhere in your code, which isn’t true for all variable declaration notations. Let’s get started:

  1. Create a new folder and add a main.go file to it.
  2. In main.go, add the main package name to the top of the file:
    package main
  3. Add the imports:
    import (
      "fmt"
    )
  4. Declare a variable at the package-level scope. We’ll cover what scopes are in detail later:
    var foo string = "bar"
  5. Create the main() function:
    func main() {
  6. Declare another variable using var in our function:
      var baz string = "qux"
  7. Print both variables to the console:
      fmt.Println(foo, baz)
  8. Close the main() function:
    }
  9. Save the file. Then, in the new folder, run the following:
    go run .

The following is the output:

bar qux

In this example, foo is declared at the package level while baz is declared at the function level. Where a variable is declared is important because where you declare a variable also limits what notation you can use to declare it.

Next, we’ll look at another way to use the var notation.

Declaring multiple variables at once with var

We can use a single var declaration to define more than one variable using a var block or statement. Using this method is common when declaring package-level variables. The variables don’t need to be of the same type, and they can all have their own initial values. The notation looks like this:

var (
  <name1> <type1> = <value1>
  <name2> <type2> = <value2>
…
  <nameN> <typeN> = <valueN>
)

You can have multiple of these types of declarations. This is a nice way to group related variables, thereby making your code more readable. You can use this notation in functions, but it’s rare to see it used there.

Exercise 1.03 – declaring multiple variables at once with var

In this exercise, we’ll declare multiple variables using one var statement, each with a different type and initial value. Then, we’ll print the value of each variable to the console. Let’s get started:

  1. Create a new folder and add a main.go file to it.
  2. In main.go, add the main package name to the top of the file:
    package main
  3. Add the imports:
    import (
      "fmt"
      "time"
    )
  4. Start the var declaration:
    var (
  5. Define three variables:
      Debug   bool   = false
      LogLevel  string  = "info"
      startUpTime time.Time = time.Now()
  6. Close the var declaration:
    )
  7. In the main() function, print each variable to the console:
    func main() {
      fmt.Println(Debug, LogLevel, startUpTime)
    }
  8. Save the file. Then, in the new folder, run the following:
    go run .

    The following is the output:

Figure 1.5: Output displaying three variable values

Figure 1.5: Output displaying three variable values

In this exercise, we declared three variables using a single var statement. Your output will look different for the time.Time variable, but that’s correct. The format is the same, but the time itself is different.

Using the var notation like this is a good way to keep your code well organized and save you some typing.

Next, we’ll start removing some of the optional parts of the var notation.

Skipping the type or value when declaring variables

In real-world code, it’s not common to use the full var notation. There are a few cases where you need to define a package-level variable with an initial value and tightly control its type. In those cases, you need the full notation. It’ll be obvious when this is needed as you’ll have a type mismatch of some kind, so don’t worry too much about this for now. The rest of the time, you’ll remove an optional part or use the short variable declaration.

You don’t need to include both the type and the initial value when declaring a variable. You can use just one or the other; Go works out the rest. If you have a type in the declaration but no initial value, Go uses the zero value for the type you picked. We’ll talk about what a zero value is later in this book. On the other hand, if you have an initial value and no type, Go has a ruleset for how to infer the types that are needed from the literal value you use.

Exercise 1.04 – skipping the type or value when declaring variables

In this exercise, we’ll update our previous exercise so that it skips the optional initial values or type declarations from our variable declaration. Then, we’ll print the values to the console, as we did previously, to show that the result is the same. Let’s get started:

  1. Create a new folder and add a main.go file to it.
  2. In main.go, add the main package name to the top of the file:
    package main
  3. Import the packages we’ll need:
    import (
      "fmt"
      "time"
    )
  4. Start the multi-variable declaration:
    var (
  5. The bool value in the first exercise has an initial value of false. That’s a bool value’s zero value, so we’ll drop the initial value from its declaration as it is set by default:
      Debug   bool
  6. The next two variables both have a non-zero value for their type, so we’ll drop their type declaration:
      LogLevel  = "info"
      startUpTime = time.Now()
  7. Close the var declaration:
    )
  8. In the main() function, print out each variable:
    func main() {
      fmt.Println(Debug, LogLevel, startUpTime)
    }
  9. Save the file. Then, in the new folder, run the following:
    go run .

    The following is the output:

Figure 1.6: Output displaying variable values despite not mentioning the type while declaring the variables

Figure 1.6: Output displaying variable values despite not mentioning the type while declaring the variables

In this exercise, we were able to update the previous code so that it uses a much more compact variable declaration. Declaring variables is something you’ll have to do a lot, and not having to use the notation makes for a better experience when writing code.

Next, we’ll look at a situation where you can’t skip any of the parts.

Type inference gone wrong

There are times when you’ll need to use all the parts of the declaration – for example, when Go isn’t able to guess the correct type you need. Let’s take a look at an example of this:

package main
import "math/rand"
func main() {
  var seed = 1234456789
  rand.NewSource(seed)
}

The following is the output:

Figure 1.7: Output showing an error

Figure 1.7: Output showing an error

The issue here is that rand.NewSource requires a variable of the int64 type. Go’s type inference rules interoperate a whole number, such as the one we used as an int value. We’ll look at the difference between them in more detail later in this book. To resolve this, we will add int64 type to the declaration. Here’s how that looks:

package main
import "math/rand"
func main() {
  var seed int64 = 1234456789
  rand.NewSource(seed)
}

Next, we’ll look at an even quicker way to declare variables.

Short variable declaration

When declaring variables in functions and functions only, we can use the := shorthand. This shorthand allows us to make our declarations even shorter. It does this by allowing us to not have to use the var keyword and by always inferring the type from a required initial value.

Exercise 1.05 – implementing a short variable declaration

In this exercise, we’ll update our previous exercise so that it uses a short variable declaration. Since you can only use a short variable declaration in a function, we’ll move our variable out of the package scope. Where before Debug had a type but no initial value, we’ll switch it back so that it has an initial value since that’s required when using a short variable declaration. Finally, we’ll print it to the console. Let’s get started:

  1. Create a new folder and add a main.go file to it.
  2. In main.go, add the main package name to the top of the file:
    package main
  3. Import the packages we’ll need:
    import (
      "fmt"
      "time"
    )
  4. Create the main() function:
    func main() {
  5. Declare each variable using the short variable declaration notation:
      Debug := false
      LogLevel := "info"
      startUpTime := time.Now()
  6. Print the variables to the console:
      fmt.Println(Debug, LogLevel, startUpTime)
    }
  7. Save the file. Then, in the new folder, run the following:
    go run .

The following is the output:

Figure 1.8: Output displaying the variable values that were printed after using short variable declaration notation

Figure 1.8: Output displaying the variable values that were printed after using short variable declaration notation

In this exercise, we updated our previous code to use a very compact way to declare variables when we have an initial value to use.

The := shorthand is very popular with Go developers and the most common way in which variables get defined in real-world Go code. Developers like how it makes their code concise and compact while still being clear as to what’s happening.

Another shortcut is declaring multiple variables on the same line.

Declaring multiple variables with a short variable declaration

It’s possible to declare multiple variables at the same time using a short variable declaration. They must all be on the same line, and each variable must have a corresponding initial value. The notation looks like <var1>, <var2>, …, <varN> := <val1>, <val2>, …, <valN>. The variable names are on the left-hand side of:=, separated by ,. The initial values are on the right-hand side of:= again, each separated by ,. The leftmost variable name gets the leftmost value. There must be an equal number of names and values.

Here is an example that uses our previous exercise’s code:

package main
import (
  "fmt"
  "time"
)
func main() {
  Debug, LogLevel, startUpTime := false, "info", time.Now()
  fmt.Println(Debug, LogLevel, startUpTime)
}

The following is the output:

Figure 1.9: Example output displaying the variable values for the program with a variable declaring function

Figure 1.9: Example output displaying the variable values for the program with a variable declaring function

Sometimes, you do see real-world code like this. It’s a little hard to read, so it’s not common to see it in terms of literal values. This doesn’t mean this isn’t common, though – it’s very common when calling functions that return multiple values. We’ll cover this in detail when we look at functions later in this book.

Exercise 1.06 – declaring multiple variables from a function

In this exercise, we’ll call a function that returns multiple values, and we’ll assign each value to a new variable. Then, we’ll print the values to the console. Let’s get started:

  1. Create a new folder and add a main.go file to it.
  2. In main.go, add the main package name to the top of the file:
    package main
  3. Import the packages we’ll need:
    import (
      "fmt"
      "time"
    )
  4. Create a function that returns three values:
    func getConfig() (bool, string, time.Time) {
  5. In the function, return three literal values, each separated by ,:
      return false, "info", time.Now()
  6. Close the function:
    }
  7. Create the main() function:
    func main() {
  8. Using a short variable declaration, capture the values that were returned from the function’s three new variables:
      Debug, LogLevel, startUpTime := getConfig()
  9. Print the three variables to the console:
      fmt.Println(Debug, LogLevel, startUpTime)
  10. Close the main() function:
    }
  11. Save the file. Then, in the new folder, run the following:
    go run .

    The following is the output:

Figure 1.10: Output displaying the variable values for the program with the variable declaring function

Figure 1.10: Output displaying the variable values for the program with the variable declaring function

In this exercise, we were able to call a function that returned multiple values and capture them using a short variable declaration in one line. If we used the var notation, it would look like this:

var (
  Debug bool
  LogLevel string
  startUpTime time.Time
)
Debug, LogLevel, startUpTime = getConfig()

Short variable notation is a big part of how Go has the feel of a dynamic language.

We’re not quite done with var yet, though – it still has a useful trick up its sleeve.

Using var to declare multiple variables in one line

While it’s more common to use a short variable declaration, you can use var to define multiple variables on a single line. One limitation of this is that, when declaring the type, all the values must have the same type. If you use an initial value, then each value infers its type from the literal value so that they can differ. Here’s an example:

package main
import (
  "fmt"
  "time"
)
func getConfig() (bool, string, time.Time) {
  return false, "info", time.Now()
}
func main() {
  // Type only
  var start, middle, end float32
  fmt.Println(start, middle, end)
  // Initial value mixed type
  var name, left, right, top, bottom = "one", 1, 1.5, 2, 2.5
  fmt.Println(name, left, right, top, bottom)
  // works with functions also
  var Debug, LogLevel, startUpTime = getConfig()
  fmt.Println(Debug, LogLevel, startUpTime)
}

The following is the output:

Figure 1.11: Output displaying variable values

Figure 1.11: Output displaying variable values

Most of these are more compact when using a short variable declaration. This fact means they don’t come up in real-world code much. The exception is the same type-only example. This notation can be useful when you need many variables of the same type, and you need to control that type carefully.

Non-English variable names

Go is a UTF-8 compliant language, which means you can define variables’ names using alphabets other than the Latin alphabet that, for example, English uses. There are some limitations regarding what the name of a variable can be. The first character of the name must be a letter or _. The rest can be a mixture of letters, numbers, and _. Let’s have a look at what this looks like:

package main
import (
  "fmt"
  "time"
)
func main() {
  デバッグ := false
  日志级别 := "info"
  ይጀምሩ := time.Now()
  _A1_Μείγμα := "" 
"
  fmt.Println(デバッグ, 日志级别, ይጀምሩ, _A1_Μείγμα)
}

The following is the output:

Figure 1.12: Output showing variable values

Figure 1.12: Output showing variable values

Note

Languages and language: Not all programming languages allow you to use UTF-8 characters as variables and function names. This feature could be one of the reasons why Go has become so popular in Asian countries, particularly in China.

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 $15.99/month. Cancel anytime