Back

2. Primitive Types & Declarations


Literals

💡 Go assigns a default zero value to any variable that is declared but not assigned a variable - this means NOTHING can ever be undefined and removes a source of bugs found in C and C++ programs.

There are 4 common kinds of literals in Go (and a fifth rare one to do with complex numbers).

Integers

Floating point

Rune

Strings

`Greetings and
Saluations`

Booleans

The bool can only be true or false. The zero value for a bool is false.

var flag bool // defaults to false
var isTrue = true // set to true

Numeric Types

Integers

There are signed and unsigned integers in a variety of sizes, from one to eight bytes (or from 8 to 64 bits). The zero value for all integers is 0.

TypeMin ValueMax Value
int8-128127
int16-32,76832,767
int32-2,147,483,6482,147,483,647
int64-9,223,372,036,854,775,8089,223,372,036,854,775,807
uint80255
uint16065,535
uint3204,294,967,295
uint64018,446,744,073,709,551,615

Go has some special integer types:

Choosing which type to use:


Arithmetic Operators

There are the usual operators +, -, *, / and % for modulus.

You can combine any of the operators with = to modify the variable: +=, -=, *=. /=, and %=

var x int = 10
x *= 2 // x = 20

Comparison operators

Bit manipulation

We can also combine them with equals to modify a variable, like &=, |=, &^=, <<=, >>=

Floating Point Types

Like integer types, the zero value for floats is 0.

TypeMin ValueMax ValueSmallest Non-Zero Value
float32-3.4e+383.4e+381.4e-45
float641.7e+3081.7e+3084.9e-324

Float defaults to float64 which mitigates floating point accuracy issues since float32 only has ~6-7 decimal digits of precision.

In most cases, however, you should use integers as it’s much safer - floats aren’t exact.

Operators

DO NOT USE == and != to compare floats, due to the inexact nature of them, they might not be equal when they should be. You could use a maximum allowed variance (epsilon) to determine if the difference between the floats is less than that instead.


Strings

The zero value for a string is the empty string, "".


Explicit Type Conversion

We cannot automatically convert from one type to another when needed implicilty, we have to explicitly declare the type conversion.

var x int = 10
var y float64 = 30.2
var z float64 = float64(x) + y
var d int = x + int(y)
fmt.Println(z, d) // 40.2, 40

This also means you can’t treat another Go type as a Boolean. There is no concept of “truthy” and “falsey” values in Go - if you want to convert another type to boolean you must use one of the comparison operators (==, !=, >, …). For example to check if x is equal to 0, you have to write x == 0 or to check if a string is empty, s == "".


Var versus :=

There are many ways to declare variables in Go:

var x int = 10 // the most verbose
var x = 10 // gets the type int
var x int // gets the value 0
var x, y int = 10, 20 // x = 10, y = 20
var x, y = 10, "hello" // different types

// declaring multiple variables at once:
var (
		x    int
		y        = 20
		z    int = 30
		d, e     = 40, "hello"
		f, g string
	)

There is also the short declaration format, with :=. When you are within a function, you can use := instead of var and it uses type inference. These 2 are the same thing:

var x = 10
x := 10

var x, y = 10, "hello"
x, y := 10, "hello"

You can also re-assign values to existing variables

x := 10
x, y := 30, "hello"

The only restriction is that you HAVE to be within a function, you can’t use := at the package level - only var.

When you should avoid using :=:


Using const

To ensure a variable is immutable, we use const.

const x int64 = 10
const (
	idKey   = "id"
	nameKey = "name"
)

const z = 20 * 10

func main() {
	const y = "hello"

	x = x + 1
	y = "bye"
}

This will throw two errors - cannot assign to x and cannot assign to y

However, it is very limited. They can only hold values that the compiler can figure out at compile time - which limits it to:

Go doesn’t provide a way to specify that a value calculated at runtime is immutable, this means there are no immutable arrays, slices, maps or structs and there’s no way to declare that a field in a struct is immutable.

Typed and Untyped Constants

Constants can be typed or untyped, they behave exactly like a literal - if it has no type of it’s own, it will have a default type that is used when no other type can be inferred.

const x = 10 // untyped

All the following are legal:

var y int = x
var z float64 = x
var d byte = x

If we wanted to be strict with the types, we could say const x int = 10 and only int can be assigned to this.

Unused Variables

Go has some unique rules to ensure large teams can collaborate on Go and keep the coding style consistent. One of these is that every declared local variable MUST be read. Otherwise this will throw a compile-time error.

However, the compiler won’t stop you from using unread package-level variables, which is another reason you shouldn’t use these.

Naming Conventions

Go requires variable names to:

Any Unicode character that is considered a number or letter is allowed.

You should AVOID names like these:

_0 := 0_0
_𝟙 := 20
η := 3
a := "hello" // unicode U+FF41

While they work, they are non-idiomatic and are confusing or difficult to type, because and a look almost exactly the same, but will be considered different variables.

Common rules:

PrevNext