UP | HOME

Go: The Basics

Table of Contents

1 Comments

Go supports two kinds of comments:

  • line comments begin with // and end at the newline; these are treated simply as newline.
  • general comments begin with /∗ and end with ∗/ and may span multiple lines.

2 Variables

The var statement declares a list of variables with the type declared last or one variable per line. Var declaration can include initializers, one per variable.

var (
        name string
        location string
        age int
)
var (
        name, location string
        age            int
)
var name string
var location string
var age int
var (
        name string = "Hello World"
        location string = "World"
        age int = 42
)

The type can be omited, the variable will get inferred type.

var (
        name = "Hello World"    // inferred string
        location = "World"      // inferred string
        age = 42                // inferred int
)

You can also initialize variables on the same line:

var (
        name, location, age = "Hello World", "World", 42
)

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

func main() {
        name, location := "Hello, World", "World"
        age := 42
        fmt.Printf("%s (%d) of %s", name, age, location)
}
Hello, World (42) of World

2.1 Identifiers names

A Go identifier is a nonempty sequence of letters and digits where the first character must be a letter. A letter is the underscore, _, or any character that is in the Unicode categories:

  • Lu — letter uppercase
  • Ll — letter lowercase
  • Lt — letter titlecase
  • Lm — letter modifier
  • Lo — letter other

A Go identifier can contain any Unicode letters from this list.

// italic theta is valid identifier for Go
𝟅 := 2.45
// Pi is valid identifier as well
𝝥 := 3.14
fmt.Printf("𝟅 = %.02f, 𝝥 = %.02f", 𝟅, 𝝥)

Identifiers are case-sensitive!

abc := "abc"
Abc := "Abc"
ABC := "ABC"
aBc := "aBc"
// there are four different variables
fmt.Printf("abc = %s, Abc = %s, ABC = %s, aBc = %s", abc, Abc, ABC, aBc)

3 Constants

Constants are declared with the const keyword. Constants can only be character, string, boolean, or numeric values and cannot be declared using := syntax.

const Pi = 3.14
const (
        StatusOK = 200
        StatusCreated = 201
        StatusAccepted = 202
        StatusNonAuthoritativeInfo = 203
        StatusNoContent = 204
        StatusResetContent = 205
        StatusPartialContent = 206
)

4 Printing Constants and Variables

While you can print the value of a variable or constant using the built-in print and println functions, the more idiomatic and flexible way is to use the fmt package. fmt.Println prints the passed in variables' values and appends a newline. fmt.Printf is used when you want to print one or multiple values using a defined format specifier.

func main() {
        someValue := 6
        fmt.Println(someValue)
}
6

func main() {
        someString := "The answer is"
        answerValue := 42
        fmt.Printf("%s %d", someString, answerValue)
}
The answer is 42

5 Packages and imports

Every Go program is made up of packages. Programs start runnig in package main. If you are writing an executable code (versus a library), then you need to define a main package and a main() function which will be the entry point to your software.

package main

func main() {
        fmt.Println("Hello World\n")
}

Import statements examples:

import (
        "fmt"
        "math/rand"
)
import "fmt"
import "math/random"

Usually, non standard lib packages are namespaced using web url.

import "github.com/name/repo/package"

The snippet above basically tells the compiler to import the crypto package available at the github.com/name/repo/package path. It doesn’t mean that the compiler will automatically pull down the repository. You need to pull down the code yourself. The easiest way is to use the go get command provided by Go.

go get github.com/name/repo/package

6 Exported names

After importing a package, you can refer to the names it exports (meaning variables, methods and functions that are available from outside of the package). In Go, a name is exported if it begins with a capital letter. Foo is an exported name, as is FOO. The name foo is not exported.

import (
        "fmt"
        "math"
)

func main() {
        fmt.Println(math.pi)
}
# command-line-arguments
/tmp/babel-9061vPW/go-src-90611Bk.go:9: cannot refer to unexported name math.pi
/tmp/babel-9061vPW/go-src-90611Bk.go:9: undefined: math.pi

func main() {
        fmt.Println(math.Pi)
}
3.141592653589793

7 Functions, signature, return values, named results

Function can take zero or more typed arguments. The type comes after the variable name. Functions can be defined to return any number of values that are always typed.;

package main

import "fmt"

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


func main() {
        fmt.Println(add(42, 122))
}

164

We can declare one type that applies to both

package main

import "fmt"

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

func main() {
        fmt.Println(add(42, 122))
}

164

In the following example, the location function return two string values

func location(city string) (string, string) {
        var region string
        var continent string

        switch city {
        case "Los Angeles", "LA", "Santa Monica":
                region, continent = "California", "North America"
        case "New York", "NYC":
                region, continent = "New York", "North America"
        default:
                region, continent = "Unknown", "Unknown"
        }
        return region, continent
}

func main() {
        region, continent := location("LA")
        fmt.Printf("Matt lives in %s, %s", region, continent)
}

Matt lives in California, North America

If the result parameters are named, a return statement without arguments returns the current values of the results. But DO NOT USE named return parameters because they often cause more confusion than they save time or help clarify your code.

func location(city string) (region, continent string) {
        region = city
        switch city {
        case "New York", "LA", "Chicago":
                continent = "North America"
        default:
                continent = "Unknown"
        }
        return
}

func main() {
        region, continent := location("LA")
        fmt.Printf("Matt lives in %s, %s", region, continent)
}

Matt lives in LA, North America

8 Pointers

Go has pointers (like C++ references), but no pointer arithmetic. Struct fields can be accessed through a struct pointer. Note that by default Go passes arguments by value (copying the arguments), if you want to pass the arguments by reference, you need to pass pointers (or use a structure using reference values like slices and maps). To get the pointer of a value, use the & symbol in front of the value; to dereference a pointer, use the (asterisk) symbol. Methods are often defined on pointers and not values (although they can be defined on both), so you will often store a pointer in a variable as in the example below:

client := &http.Client{}
resp, err := client.Get("http://gobootcamp.com")

9 Mutability

In Go only constants are immutable. However because arguments are passed by value, a function receiving a value argument and mutating it, won’t mutate the original value.

package main

import "fmt"

type Artist struct {
        Name, Genre string
        Songs       int
}

func newRelease(a Artist) int {
        a.Songs++
        return a.Songs
}

func main() {
        me := Artist{Name: "Matt", Genre: "Electro", Songs: 42}
        fmt.Printf("%s has a total of %d songs\n", me.Name, me.Songs)
        fmt.Printf("%s released their %dth song\n", me.Name, newRelease(me))
        fmt.Printf("%s has a total of %d songs", me.Name, me.Songs)
}
Matt has a total of 42 songs
Matt released their 43th song
Matt has a total of 42 songs

To mutate the passed value, we need to pass it by reference, using a pointer.

package main

import "fmt"

type Artist struct {
        Name, Genre string
        Songs       int
}

func newRelease(a *Artist) int {
        a.Songs++
        return a.Songs
}

func main() {
        me := &Artist{Name: "Matt", Genre: "Electro", Songs: 42}
        fmt.Printf("%s has a total of %d songs\n", me.Name, me.Songs)
        fmt.Printf("%s released their %dth song\n", me.Name, newRelease(me))
        fmt.Printf("%s has a total of %d songs", me.Name, me.Songs)
}
Matt has a total of 42 songs
Matt released their 43th song
Matt has a total of 43 songs

Author: Pavel Vavilin

Created: 2017-11-08 Wed 01:55

Validate