Golang Program Structure: Variables
If you're not new to programming, you are already aware that variables are the main mechanism for storing and managing the data in a program, as well as holding values that can be referenced and manipulated throughout the program. Go provides several ways to declare and initialize variables, emphasizing simplicity, readability, and efficiency.
In this article, we will go through a detailed description of how variables are structured in Golang, covering types, declaration methods, initialization, and the nuances of variable management in the language.
And of course, we will start with variable declaration.
Variable declaration
Variable declaration in Go is the process of defining a variable, which involves assigning it a name and an optional data type, and potentially initializing it with a value. This step sets aside memory space to store data associated with that variable, and it allows the variable to be referenced and manipulated within the program.
In Go, variable declaration is a bit more structured compared to dynamically typed languages. Variables must either be explicitly typed or initialized with values that allow Go to infer their type.
The standard way to declare variables in Go is with the `var` keyword. This is particularly useful when you need to declare variables without immediately initializing them or if you want to specify their type explicitly.
The syntax looks like this:
var variableName type
where:
`variableName` is The name of the variable
`type` is The data type of the variable (e.g., int, string, bool, or any other custom type)
Let's try to define a couple of variables:
var age int
var name string
var isActive bool
Variables declared with var are automatically initialized to their zero values, which we will discuss later in this article.
Go offers a shorthand for variable declaration using the `:=` operator. This method infers the type of the variable based on the assigned value and can only be used inside functions:
variableName := value
The type of the variable is inferred from the value on the right side, a process called type inference.
Let's try to define a couple of variables using shorthand definition, similar to example from above:
age := 30 Â Â Â // inferred as int
name := "John" // inferred as string
isActive := true // inferred as bool
In this case, we used literals, and it automatically inferred types of the literal values, as stated in the comments from the code section. As you may notice, this approach eliminates the need to specify the type explicitly, making the code more concise. The short form declaration variables are assigned directly to required values, without the need to assign zero values.
Go also allows declaring multiple variables in a single line. This is useful when you need to declare several variables at once.
var x, y, z int // Declaring three integer variables
x, y, z := 1, 2, 3 // Shorthand multiple variables declaration for the same type
name, age := "Alice", 25 // Shorthand multiple variables declaration for different types
In the example from above, you can notice that when using the standard way of variable declaration, the type will be the same for all variables. On shorthand declaration, the types of variables could be different, very handy for assigning values from a function that returns multiple values.
Variable Initialization
Variables in Go can be initialized in several ways, depending on the declaration style.
When you declare a variable using the var keyword without initializing it, Go automatically assigns it a "zero value." This ensures that the variable always has a well-defined state.
It's not difficult to remember zero values, as they are as follows:
- `int`: 0 (it is applied to all types of integers, either signed or unsigned)
- `float`: 0.0 (same as integers, it applies for all float types)
- `string`: "" (empty string)
- `bool`: false
- Pointers, slices, maps, channels, interfaces, and function types: `nil`
For example:
var count int   // count is initialized to 0
var isActive bool // isActive is initialized to false
var name string  // name is initialized to an empty string
Or, can explicitly assign a value at the time of declaring a variable:
var count int = 10
var isActive bool = true
var name string = "Golang"
Here, the type is specified explicitly, and a value is assigned simultaneously, which is similar to:
count := 10 Â Â Â // inferred as int
isActive := true  // inferred as bool
name := "Golang" Â // inferred as string
but here, it's just adding the overhead of type inference. This is especially useful when the type is obvious.
Go also supports declaring constants using the `const` keyword. Unlike regular variables, constants cannot be reassigned once they are set, and their values must be determinable at compile time.
The syntax of constants looks like this:
const constantName = value
And this is how it can be used:
const pi = 3.14
const companyName = "TechCorp"
Constants are particularly useful for values that never change throughout the execution of a program, such as mathematical constants, fixed configuration values, or application settings.
But bear in mind that constants can have values only literal types, it can not have values by reference and could be nil, like pointers, functions, structs, etc.
Variables scope
The scope of a variable determine the contexts of the Go program were a variable could be accessed from. Here, by context I mean the area were the program execution goes.
The most visible of course is the so called `Global Scope`. Any variable declared outside of a function/method is defined in a global scope, and it can be visible within the package. Of course, if it starts in higher case, when package is imported, the variable could be visible as well. But, we will discuss this more in the `Encapsulation`
Here is an example on it should look like:
var globalVar = "Accessible Everywhere"
func main() {
  fmt.Println(globalVar)  // Accessible within this function
}
The `globalVar` variable will be accessible within this package, on only within it; but still, because it's defined outside the function, and it could be accessed by other functions, it's in the global scope.
Narrowing it down, we are getting to the `Local Scope`, which covers the variables defined within the same function, and can only be accessed within the same function.
func main() {
  localVar := "Accessible Only Here"
  fmt.Println(localVar)
}
// But not accessible here, in the global scope
Narrowing it down even further, we are getting to the `Block Scope`, which covers the variables only defined within a block within a function:
func main() {
  if true {
    blockVar := "Block Scoped"
    fmt.Println(blockVar) // Accessible within the if block
  }
  // fmt.Println(blockVar) // Error: blockVar is undefined (therefore unaccessible) here
}
Best Practices for Variable Declaration and Usage
Although, Go provides pretty good array of tooling for variable declaration, and initialization, it is good to make sure those are not overused, that could lead to undesired side effects.
Make sure that:
Use Short Declarations Wisely: While the := operator is convenient, avoid overusing it in global scope or when explicit typing improves code clarity
Prefer Descriptive Names: Variable names should be meaningful and descriptive, indicating their purpose
Limit Scope: Declare variables in the smallest possible scope to reduce the chance of unintended side effects
Initialize When Possible: Explicitly initialize variables if the zero value is not appropriate for the intended logic
Immutable Data: Use constants (const) for values that do not change throughout the program to prevent accidental reassignment.
This might be a good example on how to define and initialize multiple variables:
package main
import "fmt"
func main() {
  var a, b, c int = 1, 2, 3
  name, age := "Alice", 25
  fmt.Println(a, b, c)
  fmt.Println(name, age)
}
Conclusion
Understanding the structure and behavior of variables is crucial for writing efficient, maintainable, and scalable Go code. Golang's variable declaration and initialization mechanisms are designed to be simple yet powerful, allowing developers to work with minimal syntax while maintaining performance and flexibility. By adhering to best practices, Go developers can effectively manage data and optimize their programs for both readability and efficiency.
Thank you so much for reading this article!
Any questions or suggestions on materials that you would like to see here? Send me a DM: