[A Tour of Go Study Notes] 02 Variables and Types
Understanding Go language variables and types using the official tutorial
Entering the world of Golang, we first use the official tutorial: A Tour of Go
to learn the basics of using Golang.
This article is a note on variables and types.
Variables
In the Golang, var
is used to declare variables, and just like the parameter list of a function, the type is defined at the end.
var
declarations can appear within the package or function scope.
package main
import "fmt"
var c, python, java bool
func main() {
var i int
fmt.Println(i, c, python, java)
}
/*
>>> 0 false false false
*/
Default Values of Variables
When declaring variables, an initial value can be defined.
If an initial value is defined, the type can be omitted during declaration.
Go will infer the variable’s type based on the initial value, which is quite clever!
package main
import "fmt"
// Actively defining variable types
var i, j int = 1, 2
func main() {
// Omitting type, using default values
var c, python, java = true, false, "no!"
fmt.Println(i, j, c, python, java)
}
/*
>>> 1 2 true false no!
*/
Short Variable Declaration
Within a function, :=
can be used instead of var
to declare variables.
Outside functions, every statement must begin with a keyword (var, func, etc.) and cannot use :=
.
package main
import "fmt"
func main() {
var i, j int = 1, 2
k := 3
c, python, java := true, false, "no!"
fmt.Println(i, j, k, c, python, java)
}
/*
>>> 1 2 3 true false no!
*/
Basic Types
Go’s basic types include:
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32
// represents a Unicode code point
float32 float64
complex64 complex128
Generally, the lengths of int
, uint
, and uintptr
are the same as the system’s bit size.
For instance, on a 32-bit system, it’s 32 bits; on a 64-bit system, it’s 64 bits.
Use int
directly when you need an integer unless there’s a specific reason to restrict its length.
You can use the fmt.Printf
package to print formatted output of variables, including the type %T
and value %v
.
package main
import (
"fmt"
"math/cmplx"
)
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
func main() {
fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
fmt.Printf("Type: %T Value: %v\n", z, z)
}
/*
>>> Type: bool Value: false
>>> Type: uint64 Value: 18446744073709551615
>>> Type: complex128 Value: (2+3i)
*/
Zero Values
If a variable is declared without an initial value, it automatically gets assigned a zero value.
Different types have different zero values:
- Numeric types:
0
- Boolean type:
false
- String type:
""
(empty string)
Type Conversion
Use T(v)
to convert a value v
to type T
.
For example:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
Or use a more concise form:
i := 42
f := float64(i)
u := uint(f)
Constants
- Similar to variable declarations but using
const
- Content can be characters, strings, booleans, or numerical data
- Cannot use
:=
for declaration
Numeric Constants
- A form of high-precision numerical values
- The type of the constant is determined based on the context
import "fmt"
const (
// Creating a large number by shifting 1 left by 100 bits (binary 1 followed by 100 zeros)
Big = 1 << 100
// Then shifting left by 99 bits, becoming binary "10," which is decimal 2
Small = Big >> 99
)
func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
return x * 0.1
}
func main() {
fmt.Println(needInt(Small))
fmt.Println(needFloat(Small))
fmt.Println(needFloat(Big))
}
/*
>>> 21
>>> 0.2
>>> 1.2676506002282295e+29
*/
What happens if we print needInt(Big)
?
constant 1267650600228229401496703205376 overflows int
This occurs because in our system, the longest int
is 64-bit (sometimes less),
and the numerical constant Big
we’ve defined is a 100-bit positive number, causing an overflow.