0%

A Tour Of Go/ Basics/ Packages, variables and functions

Packages, variables and functions

Packages

Every Go program is made up of packages.

Programs start running in package main.

This program is using the packages with import paths “fmt” and “math/rand”.

By convention, the package name is the same as the last element of the import path. For instance, the “math/rand” package comprises files that begin with the statement package rand.

Note: The environment in which these programs are executed is deterministic, so each time you run the example program rand.Intn will return the same number.

(To see a different number, seed the number generator; see rand.Seed. Time is constant in the playground, so you will need to use something else as the seed.)

Imports

This code groups the imports into a parenthesized, “factored” import statement.

You can also write multiple import statements, like:

import “fmt”
import “math”
But it is good style to use the factored import statement.

Exported names

In Go, a name is exported if it begins with a capital letter. For example, Pizza is an exported name, as is Pi, which is exported from the math package.

pizza and pi do not start with a capital letter, so they are not exported.

When importing a package, you can refer only to its exported names. Any “unexported” names are not accessible from outside the package.

Run the code. Notice the error message.

To fix the error, rename math.pi to math.Pi and try it again.

Function

type comes after the variable name

It still reads clearly, from left to right, and it’s always obvious which name is being declared - the name comes first.

The distinction between type and expression syntax makes it easy to write and invoke closures in Go:

1
sum := func(a, b int) int { return a+b } (3, 4)

can shorten when arguments use the same type

1
2
3
4
5
6
7
func add(x int, y int) int {
return x + y
}

func add(x, y int) int {
return x + y
}

Multiple results

1
2
3
func swap(x, y string) (string, string) {
return y, x
}

Named return value

Go’s return values may be named. If so, they are treated as variables defined at the top of the function.

These names should be used to document the meaning of the return values.

A return statement without arguments returns the named return values. This is known as a “naked” return.

Naked return statements should be used only in short functions, as with the example shown here. They can harm readability in longer functions.

1
2
3
4
5
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}

Variables

scope

A var statement can be at package or function level.

var

type goes last

1
var i int

var declaration factored into block

just like import

1
2
3
4
5
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)

Variables with initializers

A var declaration can include initializers, one per variable.

If an initializer is present, the type can be omitted; the variable will take the type of the initializer.

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

var i, j int = 1, 2
var k, l = 3, 4

func main() {
fmt.Println(i, j, k, l)
}

Short variable declarations

1
2
3
4
5
func main() {
var i, j int = 1, 2
k := 3
fmt.Println(i, j, k)
}

Can only use inside a function

the := short assignment statement can be used in place of a var declaration with implicit type.

Reason:

Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available.

Basic Types

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

The int, uint, and uintptr types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems.

When you need an integer value you should use int unless you have a specific reason to use a sized or unsigned integer type.

Zero values

Variables declared without an explicit initial value are given their zero value.

The zero value is:

0 for numeric types,
false for the boolean type, and
“” (the empty string) for strings.

Type conversions

The expression T(v) converts the value v to the type T.

Some numeric conversions:

1
2
3
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

Type inference

When declaring a variable without specifying an explicit type (either by using the := syntax or var = expression syntax)
the variable’s type is inferred from the value on the right hand side.

1
2
var i int
j := i // j is an int

But when the right hand side contains an untyped numeric constant, the new variable may be an int, float64, or complex128 depending on the precision of the constant:

1
2
3
i := 42           // int
f := 3.142 // float64
g := 0.867 + 0.5i // complex128

Constants

Constants are declared like variables, but with the const keyword.

Can declared in a factored block

1
2
3
4
5
6
7
const (
// Create a huge number by shifting a 1 bit left 100 places.
// In other words, the binary number that is 1 followed by 100 zeroes.
Big = 1 << 100
// Shift it right again 99 places, so we end up with 1<<1, or 2.
Small = Big >> 99
)

Constants can be character, string, boolean, or numeric values.
Constants cannot be declared using the := syntax.

Numeric Constants

Numeric constants are high-precision values.

An untyped constant takes the type needed by its context.

depend on the value that assigned