Go variables

Go is a strictly typed language, which implies that all variables are named elements that are bound to both a value and a type. As you will see, the simplicity and flexibility of its syntax make declaring and initializing variables in Go feel more like a dynamically-typed language.

Variable declaration

Before you can use a variable in Go, it must be declared with a named identifier for future reference in the code. The long form of a variable declaration in Go follows the format shown here:

var <identifier list> <type>

The var keyword is used to declare one or more variable identifiers followed by the type of the variables. The following source code snippet shows an abbreviated program with several variables declared outside of the function main():

package main 
 
import "fmt" 
 
var name, desc string 
var radius int32 
var mass float64 
var active bool 
var satellites []string 
 
func main() { 
  name = "Sun" 
  desc = "Star" 
  radius = 685800 
  mass = 1.989E+30 
  active = true 
  satellites = []string{ 
    "Mercury", 
    "Venus", 
    "Earth", 
    "Mars", 
    "Jupiter", 
    "Saturn", 
    "Uranus", 
    "Neptune", 
  } 
  fmt.Println(name) 
  fmt.Println(desc) 
  fmt.Println("Radius (km)", radius) 
  fmt.Println("Mass (kg)", mass) 
  fmt.Println("Satellites", satellites) 
} 

golang.fyi/ch02/vardec1.go

The zero-value

The previous source code shows several examples of variables being declared with a variety of types. Then the variables are assigned a value inside the function main(). At first glance, it would appear that these declared variables do not have an assigned value when they are declared. This would contradict our previous assertion that all Go variables are bound to a type and a value.

How can we declare a variable and not bind a value to it? During declaration of a variable, if a value is not provided, Go will automatically bind a default value (or a zero-value) to the variable for proper memory initialization (we see how to do both declaration and initialization in one expression later).

The following table shows Go types and their default zero-values:

Type

Zero-Value

string

"" (empty string)

Numeric - Integers: byte, int, int8, int16, int32, int64, rune, uint, uint8, uint16, uint32, uint64, uintptr

0

Numeric - Floating point: float32, float64

0.0

bool

false

Array

Each index position has a zero-value corresponding to the array's element type.

Struct

An empty struct with each member having its respective zero-value.

Other types: Interface, function, channel, slice, map, and pointer

nil

Initialized declaration

As hinted earlier, Go also supports the combination of both variable declaration and initialization as one expression using the following format:

var <identifier list> <type> = <value list or initializer expressions>

This declaration format has the following properties:

  • An identifier list provided on the left-hand side of the equal sign (followed by a type)
  • A matching comma-separated value list on the right-hand side
  • Assignment occurs in the respective order of identifiers and values
  • Initializer expressions must yield a matching list of values

The following abbreviated example shows the declaration and initialization combination at work:

var name, desc string = "Earth", "Planet" 
var radius int32 = 6378 
var mass float64 = 5.972E+24 
var active bool = true 
var satellites = []string{ 
  "Moon", 
} 

golang.fyi/ch02/vardec2.go

Omitting variable types

So far, we have discussed what is called the long form of Go's variable declaration and initialization. To make the language feel closer to its dynamically-typed cousins, the type specification can be omitted, as shown in the following declaration format:

var <identifier list> = <value list or initializer expressions>

During compilation, the compiler infers the type of the variable based on the assigned value or the initializer expression on the right-hand side of the equal sign, as shown in the following example.

var name, desc = "Mars", "Planet" 
var radius = 6755 
var mass = 641693000000000.0 
var active = true 
var satellites = []string{ 
  "Phobos", 
  "Deimos", 
} 

golang.fyi/ch02/vardec3.go

As stated earlier, when a variable is assigned a value, it must receive a type along with that value. When the type of the variable is omitted, the type information is deduced from the assigned value or the returned value of an expression. The following table shows the type that is inferred given a literal value:

Literal value

Inferred type

Double- or single-quoted (raw) text: "Planet Mars"

"All planets revolve around the Sun."

string

Integers:

-76

0

1244

1840

int

Decimals:

-0.25

4.0

3.1e4

7e-12

float64

Complex numbers:

-5.0i

3i

(0+4i)

complex128

Booleans:

true

false

bool

Array values:

[2]int{-76, 8080}

The array type defined in the literal value. In this case it is: [2]int

Map values:

map[string]int{

  "Sun": 685800,

  "Earth": 6378,

  "Mars": 3396,

}

The map type defined in the literal value. In this case it is: map[string]int

Slice values:

[]int{-76, 0, 1244, 1840}

The slice type defined in the literal value:

[]int

Struct values:

struct{

  name string

  diameter int}

{

  "Mars", 3396,

}

A struct type as defined in the literal value. In this case the type is:

struct{name string; diameter int}

Function values:

var sqr = func (v int)   int {

  return v * v

}

The function type defined in the function definition literal. In this case, variablesqr will have type:

func (v int) int

Short variable declaration

Go can further reduce the variable declaration syntax using the short variable declaration format. In this format, the declaration loses the var keyword and the type specification, and uses an assignment operator := (colon-equal), as shown:

<identifier list> := <value list or initializer expressions>

This is a simple and uncluttered idiom that is commonly used when declaring variables in Go. The following code sample shows usage of the short variable declarations:

func main() { 
    name := "Neptune" 
    desc := "Planet" 
    radius := 24764 
    mass := 1.024e26 
    active := true 
    satellites := []string{ 
         "Naiad", "Thalassa", "Despina", "Galatea", "Larissa", 
     "S/2004 N 1", "Proteus", "Triton", "Nereid", "Halimede", 
         "Sao", "Laomedeia", "Neso", "Psamathe", 
    } 
... 
} 

golang.fyi/ch02/vardec4.go

Notice the keyword var and variable types have been omitted in the declaration. Short variable declaration uses the same mechanism to infer the type of the variable discussed earlier.

Restrictions for short variable declaration

For convenience, the short form of the variable declaration does come with several restrictions that you should be aware of to avoid confusion:

  • Firstly, it can only be used within a function block
  • The assignment operator :=, declares variable and assign values
  • := cannot be used to update a previously declared variable
  • Updates to variables must be done with an equal sign

While these restrictions may have their justifications rooted in the simplicity of Go's grammar, they are generally viewed as a source of confusion for newcomers to the language. For instance, the colon-equal operator cannot be used with package-level variables assignments. Developers learning Go may find it compelling to use the assignment operator as a way to update a variable, but that would cause a compilation error.

Variable scope and visibility

Go uses lexical scoping based on code blocks to determine the visibility of variables within a package. Depending on the location where a variable is declared, within the source text, will determine its scope. As a general rule, a variable is only accessible from within the block where it is declared and visible to all nested sub-blocks.

The following screenshot illustrates the scope of several variables declared within a source text. Each variable declaration is marked with its scope (package, function, for loop, and if...else block):

Variable scope and visibility

golang.fyi/ch02/makenums.go

As explained earlier, variable visibility works top-down. Variables with package scope, such as mapFile and numbersFile, are globally visible to all other elements in the package. Moving down the scope ladder, function-block variables such as data and err are visible to all elements in the function and including sub-blocks. Variables i and b in the inner for loop block are only visible within that block. Once the loop is done, i and b would go out of scope.

Note

One source of confusion to newcomers to Go is the visibility of package-scoped variables. When a variable is declared at package level (outside of a function or method block), it is globally visible to the entire package, not just to the source file where the variable is declared. This means a package-scoped variable identifier can only be declared once in a group of files that make up a package, a fact that may not be obvious to developers starting out with Go. Refer to Chapter 6, Go Packages and Programs, for details on package organization.

Variable declaration block

Go's syntax allows the declaration of top-level variables to be grouped together into blocks for greater readability and code organization. The following example shows a rewrite of one of the previous examples using the variable declaration block:

var ( 
  name string = "Earth" 
  desc string = "Planet" 
  radius int32 = 6378 
  mass float64 = 5.972E+24 
  active bool = true 
  satellites []string   
) 

golang.fyi/ch02/vardec5.go

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.17.18