Data Structures and Algorithms in Go PDF
Data Structures and Algorithms in Go PDF
Table of Contents
Introduction 0
Minimum Viable Go 1
Arrays 2
2
Data Structures and Algorithms in Go
This book is just getting started and doesn't have much content yet. Stay tuned.
Learning data structures and algorithms is the next step in improving programming skills.
Sound knowledge of data structures and algorithms will allow you to solve new problems,
develop more performant applications, and discover new design paradigms.
The learning of data structures and algorithms also happens to be a good vessel for learning
key elements of a programming language. That is the key focus of this book. You will learn
the Go programming language in conjunction with the concepts presented in the book.
This book is focused on practical application and will only delve into theoretical foundations
as needed to understand the application.
There are problem sets presented at the end of each chapter, however solutions will be
publicly available online. This point would exclude the text from being used for formal
instruction purposes unless an instructor developed their own problem sets.
Example code
All code presented in this book is available on GitHub.
Introduction 3
Data Structures and Algorithms in Go
Technical requirements
The technical requirements to follow this book are simple:
If you are looking for a solid, free text editor with Go language support, I would recommend
looking at GitHub Atom.
Where to find it
Read Online At:
https://www.gitbook.com/book/wlbrough/data-structures-and-algorithms-in-go
https://www.gitbook.com/book/wlbrough/data-structures-and-algorithms-in-go/details
https://github.com/wlbrough/data-structures-and-algorithms-in-go
Introduction 4
Data Structures and Algorithms in Go
Minimum Viable Go
Go is an open source programming language that makes it easy to build simple,
reliable, and efficient software.
golang.org
A team at Google developed Go in 2007 and the language was released publicly in 2009.
The language was originally developed as a systems programming language and has
syntactic similarity to C-derived languages. While taking some syntax from C, Go also
adopted conventions from dynamic languages to make the code easier to read and
understand. Simplicity was a stated goal of the project. Go features built in concurrency, a
native package manager, and an extensive standard library.
This chapter covers the basics of the language to get started with the material. New pieces
of the programming language are introduced as they are needed throughout the text.
Getting set up
Find the instructions to install and configure Go on the official Go website.
I will point out that you should ensure that you have set your GOPATH environment variable
is set to your working directory.
As stated in the introduction, I recommend GitHub's Atom text editor if you do not already
have a preferred text editor.
Other resources
If you are looking for a guided tutorial or more detailed documentation, you can find it on the
Go documentation page. In particular, check out the following resources:
Go Tool
Once you have Go installed, you can verify the installation by typing:
Minimum Viable Go 5
Data Structures and Algorithms in Go
go version
The current version is 1.6 at the time I an writing this. You will see a result like the following:
In addition to the compiler, Go installs a suite of tools under the go command. You can see
the full listing of commands by running go help .
Primitives
Go has integer and floating point number types, a string type, and a boolean type. The
number types can be declared with a memory allocation, but it is generally easier to let Go
manage the memory allocation.
Integers
Integers are numbers without a decimal component or "round numbers". Go integers can be
unsigned (i.e. positive only) like uint8 , uint16 , uint32 , or uint64 or signed (positive or
negative) like int8 , int16 , int32 , int64 . The numbers in those type declarations
represent the number of bits allocated for the number.
For simplicity, Go has integer types that are allocated based on machine architecture: int ,
uint , and uintptr . int and uint will be either 32 or 64 bits depending on architecture.
For the purposes of this book, integers will always be declared as int .
Example:
Minimum Viable Go 6
Data Structures and Algorithms in Go
package main
import "fmt"
func main() {
var one int = 1
var two int = 2
fmt.Println("1 + 2 =", one + two)
}
Go has two floating point types: float32 and float64 . Unless there are memory concerns,
float64 is generally used. Go also has types for complex numbers complex64 and
Example:
package main
import "fmt"
func main() {
var seven float64 = 7.
var twoandahalf float64 = 2.5
fmt.Println("7 / 2.5 =", seven / twoandahalf)
}
Strings
Strings are composed of letters and numbers and have the type string . They can be
defined using double quotes "Go is awesome!" or backticks Go is awesome! . Strings
created with double quotes allow the use of escape characters like \n and \t , while
strings created with backticks allow newlines.
Booleans
Booleans are either true or false and have the type bool . There are three logical operators
used with booleans:
|| for or
Minimum Viable Go 7
Data Structures and Algorithms in Go
! for not
Example:
package main
import "fmt"
func main() {
var isTrue bool = true
fmt.Println("isTrue is", isTrue)
}
Arrays
Go arrays have a fixed size and a single type. Like most other programming languages,
arrays are zero indexed. A new array variable is defined like this:
This creates an array with 10 string elements. An array can also be initialized with an array
literal:
Arrays are fixed in size, so trying to add a sixth element to the previously defined int array
will cause an error:
Slices
A slice can be thought of as a dynamic array. Slices have elements of a single type like
arrays, but can grow to accommodate new elements. Slices are defined like this:
var x []int
This creates a 0 length slice that accepts int elements. To initialize the slice with a length,
but defining no elements, the make function is used:
var x = make([]int, 5)
Minimum Viable Go 8
Data Structures and Algorithms in Go
Maps
A map is an unordered key-value collection. In other languages this is called an associative
array, hash, or dictionary. Maps are declared with the key type and the value type:
var x map[string]float64
The map x has string -type keys and float64 -type values. For example x["apple"] =
0.99 .
One caveat is that maps must be initialized before they are used, so in practice the above
example will be declared as:
x := make(map[string]float64)
Variables
The section on types and data structues presented two ways to declare a variable: the var
keyword and the := operator. With the var keyword, you must declare the type for the
variable. The := operator infers the type based on the value provided, but the type remains
fixed after declaration. For example, the following variable declations are equivalent:
var x int = 7
x := 7
Variable naming
Variable names in go must start with a letter and can contain letters, numbers, and the _
underscore character. In practice, multi-word variable names should be camelCased rather
than snake_cased . Names should be terse, but descriptive.
Variable scope
Minimum Viable Go 9
Data Structures and Algorithms in Go
According to the Go docs "Go is lexically scoped using blocks". This means that variables
declared inside a set of curly braces ( { } ) cannot be accessed outside of that block. For
example:
package main
import "fmt"
func other() {
var x int = 5
fmt.Println("x =", x)
}
func main() {
x := 8
fmt.Println("x =", x)
other()
}
8
5
if and for blocks also have their own scope, so variables defined in those blocks will be
Constants
Constants are immutable variables that are defined with the const keyword:
Control structures
A major difference you will notice coming from most other languages is that Go does not use
parenthesis around the conditions for control structures. You will see this in practice as each
control structure is discussed, but it is important to know that this is not an omission.
if
if takes a condition and runs the code in the block if the condition is true. For example:
Minimum Viable Go 10
Data Structures and Algorithms in Go
x := 5
if x == 5 {
fmt.Println("x is 5")
}
If there is also code that should run in the case that the condition is not true, the else
keyword is used. Modifying the previous example:
if x == 5 {
fmt.Println("x is 5")
} else {
fmt.Println("x is not 5")
}
If there are more conditions that need to be handled, the else if part can be added:
if x == 5 {
fmt.Println("x is 5")
} else if x == 10 {
fmt.Println("x is 10")
} else {
fmt.Println("x is not 5 or 10")
}
switch
If there are several else if statements in your if block, it may be more efficient to use
the switch statement. To rewrite the last example in the if section:
switch x {
case 5: fmt.Println("x is 5")
case 10: fmt.Println("x is 10")
default: fmt.Println("x is not 5 or 10")
}
Unlike some other languages, Go switch statements do not "fall through". If a case is
matched, the switch statement breaks and the next statement following the switch is
executed. This is why there is no break statement needed after each case.
for
for is the only looping structure in Go. There is no while or do...while . These
Minimum Viable Go 11
Data Structures and Algorithms in Go
for {
// ever and ever
break // just kidding
}
x := 10
for x > 0 {
// do something
x--
}
Functions
Functions are declared with the format func name(arguments) T { ... } . To tie together
previous concepts and present function composition, an example will be followed with
explanation.
package main
import "fmt"
func main() {
var nums []int{5, 6, 7, 8}
fmt.Println(sum(nums)) // Prints 26
}
Minimum Viable Go 12
Data Structures and Algorithms in Go
The function sum takes one argument: a slice containing integers that will be called x
within the function block. The int between the closing parenthesis and the opening curly
bracket ) int { is the return type. This means that the function will send back an integer
when it is finished processing.
The syntax in the for condition is unfamiliar. The range function returns an index and a
value for each element in an array, slice, or map. The underscore _ receives the index, but
allows the program to ignore it because it is unused. If a named variable was declared and
not used, it would cause a compile error.
func main() {
x, y := multVal()
}
Structs
A struct defines a data object type with a specified collection of fields. Go does not have
classes and does not have a class keyword, but structs are roughly analogous. Methods
are associated to structs rather than being composed within the struct.
Initialization
Minimum Viable Go 13
Data Structures and Algorithms in Go
There are many ways to create a new instance of the struct. To define the local variable,
use:
var me Person
The alternative form initializes all fields to their zero-value, allocates memory, and returns a
pointer:
me := new(Person)
To define the value for each field at initialization, use this format:
me:= Person{firstName: "Bill", lastName: "Broughton", age: 29, eyeColor: "Brown", glasses:
If the order of the fields is known, the field names can be left out:
Fields
Fields are accessed through dot notation.
Keep in mind that function arguments are always copied in Go, so functions will not change
field values unless the instance is passed as a pointer.
// Arguments copied
func incrementAge(p Person) integer {
p.age++
return p.age
}
Minimum Viable Go 14
Data Structures and Algorithms in Go
// Arguments copied
func incrementAge(p *Person) integer {
p.age++
return p.age
}
Methods
The example above presents a simple use case for a method. Methods are associated with
structs rather than composed in the struct. Modifying the function above:
The method name is defined between the arguments and the return type. Defining a method
like this associates it with the Person struct and allows the use of the dot notation. Here's
another example for an introduction:
Type embedding
Rather than classical inheritance, Go uses embedded types. To demonstrate this concept,
we define an Author struct that embeds the Person type discussed in the prior section.
Minimum Viable Go 15
Data Structures and Algorithms in Go
me := Author{
Person: Person{
firstName: "Bill",
lastName: "Broughton",
age: 29,
eyeColor: "Brown",
glasses: true
},
publishedBooks: make([]string,1)
}
// Now properties and methods from Person can be used with Author
me.incrementAge()
fmt.Println(me.age) // Output: 30
Minimum Viable Go 16
Data Structures and Algorithms in Go
Arrays
To explore the functionality of the array data structure, a new MyArray struct will be
implemented with methods that duplicate the functionality of Go's built-in arrays. The built-in
Array type will be used for data storage only.
This chapter works with basic arrays, dynamic arrays, and ordered arrays. Linear search
and binary search are also discussed.
Basic array
The basic array is a fixed-length sequence of elements of a single type.
TODO: Add a description and some background. NOTE: Discussion of duplicates in the
array.
Display array
TODO: Write content
Linear search
TODO: Write content
Arrays 17
Data Structures and Algorithms in Go
Dynamic array
TODO: Add a description and some background.
Ordered array
TODO: Add a description and some background.
Binary search
TODO: Write content
Exercises
1. Implement findMin & findMax methods (TODO: add detail)
2. Implement deleteMin & deleteMax methods (TODO: add detail)
3. Implement getAvg method (TODO: add detail)
4. Implement reverseOrder method (TODO: add detail)
5. Use binary search for insert and delete methods in the ordered array (TODO: add
detail)
6. Implement a merge method (TODO: add detail)
Arrays 18