Golang Book
Golang Book
Learning Objectives
In this lesson, we’ll cover the basics of Go, its features, program structure, data types, syntax,
and more.
To put these concepts into practice, we’ll end session two with a simple coding exercise.
Prerequisites
What is Go?
“Go, also known as Golang, is a statically typed, compiled programming language designed at
Google in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson. Go is syntactically similar to C,
but with memory safety, garbage collection, structural typing, and communicating sequential
processes style concurrency.” - Wikipedia
Installation Guide
Features of Go
● Imperative language
● Statically typed
● Syntax tokens similar to C (but less parentheses and no semicolons)
● Compiles to native code (no JVM)
● No classes, but uses structs with methods
● Interfaces
● No implementation inheritance. There's type embedding.
● Functions are first class citizens
● Functions can return multiple values
● Has closures
● Has pointers, but not pointer arithmetic
● Built-in concurrency primitives: Goroutines and Channels
Let’s go
Hello world
Source code
// file main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, World!")
}
Execute it
A Go program is constructed by one or more source files, usually ending in .go. Each
source file usually consists of the following parts:
● Import Packages
● Declaration for the following:
○ Packages
○ Constants
○ Variables
○ Types
○ Functions
○ Methods
Packages and Files
Declarations
A Go source file begins with a package declaration, which defines the package it
belongs to.
package name
// file demo.go
package demo
const (
Description = "Public constant" // public
description = "private constant" // private, visible to only its
own package
)
var (
Content string = "Public"
content string = "private"
)
The names follow a simple rule: begins with a letter or an underscore and may have any
number of additional letters, digits, and underscores. Case matters: heapSort and
Heapsort are different names.
If the name of var, const, type, func begins with an upper-case letter, it is
exported, which means that it is visible and accessible outside of its own package and
may be referred to by other parts of the program.
A var declaration creates a variable of a particular type, attaches a name to it, and sets
its initial value.
When declaring variables, the type or expression must be indicated. Both cannot be
omitted. If the type is omitted, the type is determined by the initializer expression. If
the expression is omitted, the initial value is the zero value for the type.
var ten = 10
Constants
A const declaration defines named values that syntactically look like variables, but
whose value is constant. This prevents accidental (or nefarious) changes during
program execution.
const(
Pi = 3.14
Company = “Grab”
)
The variable or expression type defines the characteristics of the values it takes on,
such as the size (number of bits or number of elements), how they are represented
internally, the intrinsic operations that can be performed on them, and the methods
associated with them.
// group declaration
type (
Name string
User struct{
ID int
Name string
}
)
Scope
● The scope of an import package’s identifier is the file block containing the
package import declaration.
● The scope of a defined type’s identifier declared inside a function begins at the
identifier in the type’s specification that ends at innermost containing block.
● The scope of an alias’ identifier declared inside a local block begins at the end
of the type declaration and ends at the innermost containing block.
● The scope of a label is the innermost function body block containing the label
declaration, but excludes all the anonymous functions’ bodies nested in the
containing function.
type sample
Complex64 complex128
Integers
Boolean
Strings
Declarations
s := “Grab”
hello := `Welcome`
Lengths
The built-in len function returns the number of bytes in a string instead of the number of
characters in a string.
s := “Grab”
fmt.Println(len(s)) // 4
S := “Chào”
fmt.Println(len(s)) // 5
Count characters
The strings in Go are UTF-8 encoded by default. Go represents a character (code point) in
int32 data type. A rune is Go terminology for a single Unicode code point.
S := “Chào”
fmt.Println(count(s)) // 4
Library
Here are some important standard library packages for working with strings:
Arrays
An array is a fixed length sequence of a particular type. Arrays are rarely used in Go.
var a [3]int
var b [...]int{1, 2, 3}
Slices
A slice is a variable length sequence of a particular type. A slice has three components:
● A pointer points to the first element of the array that is reachable through the slice
● The length is the number of slice elements, it can’t exceed the capacity ( len )
● The capacity is the number of elements between the start and the end of the underlying
array ( cap )
Append
var a []int
var b = []int{1, 2, 3}
a = append(a, 0) // a = [0]
a = append(a, b … ) // a = [0, 1, 2, 3]
Note: Since a slice contains a pointer to an array element, passing a slice to a function permits
the function to modify the underlying array elements.
Maps
A map is an unordered collection of key/value pairs in which all key are distinct. All of the keys
in a given map are of the same type.
var m map[string]int
var a = map[string]interface{}{
“name”: “foo”,
“age” : 10,
}
x := map[string]struct{} {
“foo”: struct{}{},
“bar”: struct{}{},
}
/* will print
name foo
age 10
*/
Structs
A struct is an aggregate data that groups together zero or more fields. Each field will have a
name and a data type for that name.
var x Circle
x.X = 1
x.Y = 2
x.Radius = 10
Anonymous structs
x := struct {
Name string
} {
Name: “Grab”
}
Go allows field definitions for a nameless type, such a field is called anonymous field. The field
type must be a named type or pointer to a named type. In effect, the outer struct type gains not
just the embedded type fields, but its methods too.
var x Cat
var y = Cat{
Animal: Animal{
Name: "Foo",
},
}
var d = Dog{
Animal: &Animal{
Name: "Bar",
},
}
Functions
A function is a sequence of statements known as a unit, which can be called from anywhere
else in the program.
- A name
- A list of parameters, which specifies the names and types of the function’s parameters
- The return list specifies the names (optional) and types of the function’s returns. If the
name is specified, then it is declared as a local variable for the function.
Declaration
body
Return values
You can name returned values that act as implicit local variables.
Functions are the first-class values in Go. It has types and can be assigned to variables or
passed to or returned from functions. A function value can be called like any other functions.
func main() {
s := sum
total := s(1, 2)
fmt.Println(total)) // 3
fmt.Println(decrease(10)) // 9
}
Variadic functions
total += value
return total
// usage
total := sum(1, 2, 3) // 6
total := sum() // 0
Defer statements
A defer statement is an ordinary function or method call prefixed by the keyword prefer. The
function and argument expressions are evaluated when the statement is executed, but the
actual call is deferred until the function that contains the defer statement has finished.
If a function has multiple defer statements, they are executed in reverse order.
fmt.Println(“receive:”, v)
}(value)
return value++
If DEBUG {
fmt.Println(“receive:”, v)
}(value)
return value--
func hello() {
defer fmt.Print(1)
defer fmt.Print(2)
defer fmt.Print(3)
// output: 321
Methods
Declarations
A method is declared with an ordinary function declaration variant in which an extra parameter
appears before the function name. The parameter attaches the function to that parameter type.
// usage
a := Point( X: 1, Y: 1}
b := Point{ X: 4, Y: 5}
fmt.Println( a.Distance(b) ) // 5
a.Reset()
fmt.Println(a.X, a.Y) // 0, 0
Value vs pointer receiver
Method receiver can be either a value and a pointer. When calling a function, Go will make a
copy of each argument value. Ensure to use:
- Pointer receiver to update the receiver variable or type when it’s too large. Note that nill
is a valid receiver value.
- Value receiver when there are no side effects.
Empty interface
The empty interface is an interface with no method. Since every type conforms to
interface{}, you can assign any value to a variable of interface{} type.
var x interface{}
x = 1
x = struct{}{}
x = Point{}
Type assertion
Type assertion allows you to check an empty interface value’s given type.
If
If num > 0 {
return num
}
_, err := os.Create(“grab.doc”)
if err != nil {
// todo
} else if err = os.EOF {
// todo
} else {
// todo
}
For
The for syntax consists of three different forms, only one of which has semicolons:
// Like a C for
for init; condition; post { }
// Like a C while
for condition { }
// Like a C for(;;)
for { }
For example:
m := map[string]int{}
for key, value := range m{
// todo
}
Switch
switch num{
case 1:
return “A”
case 2, 3, 4:
return “B”
case 5:
return “C”
}
switch {
case a < b:
return -1
case a > b:
return 1
default:
return 0
}
Go only runs the matched case. If you want to continue with the rest of the code execution, use
fallthrough.
n := 1
switch n {
case 1:
fmt.Println(“case 1”)
case 2:
fmt.Println(“case 2”)
}
// output
case 1
switch n {
case 1:
fmt.Println(“case 1”)
fallthrough
case 2:
fmt.Println(“case 2”)
}
// output
case 1
case 2
Goto
A goto statement transfers control to the statement with the corresponding label within the same
function.
In Go, errors are values, just like strings and integers. Go handles failures by returning error
values. If a function or method returns an error, it should always be the last returned value.
Error interface
In Go, the error type is a built-in interface with a single method Error() string.
Creation
You can create an error with the following approaches:
- errors.New
- fmt.Errorf
- Custom error type
A panic halts normal execution flow and exits the current function, while a recover attempts
to recover from a panic. The recover statement must appear directly within the deferred function
enclosure.
- Effective Go
- Wiki
- Profiling Go Programs
Session 2
Write a simple REPL program (Read–Eval–Print–Loop).
Take a formula from a user then print out the result. The formula must be in this format:
Example:
> 1 + 2
1 + 2 = 3
> 2 * 10
2 * 10 = 20
> 100 / 10
100 / 10 = 10