2. Introduction
This Lab introduces you to the course, outlining the
semester structure regarding the labs and the project.
We'll kick off with Go fundamentals, covering installation,
basic syntax, and modules.
A live demo will ensure your development environment is
properly set up, so you're ready to dive into coding.
3. Objectives
1. Understand the course structure and the scope of labs.
2. Learn why Go is being used and its advantages in modern software
development.
3. Install and set up Go on your machine, ensuring your environment is
ready for future labs and projects.
4. Explore Go basics, including its core features, and write a basic Go
program to get familiar with its syntax.
5. Understand Go modules and how they manage dependencies effectively.
4. Meet your TAs
•Omar Khaled
t-omarkhaled@zewailcity.edu.eg
•Maram Ashraf
t-maramalazab@zewailcity.edu.eg
•Aya Tawfiq
t-aya.said@zewailcity.edu.eg
6. What is Go ?
● Go is an open-source programming language focused on simplicity, reliability, and
efficiency.
● Go was originally designed at Google in 2007. At the time, Google was growing quickly,
and code being used to manage their infrastructure was also growing quickly in both
size and complexity. Some Google cloud engineers began to feel that this large and
complex codebase was slowing them down. So they decided that they needed a new
programming language focused on simplicity and quick performance. Robert Griesemer,
Rob Pike, and Ken Thompson designed Go.
● Go became an open-source project and was released publicly in 2012.
It quickly gained a surprising level of popularity and has
become one of the leading modern programming languages.
7. Why Go
for our Software Architecture Course ?
● The de facto language for cloud native
development, powering projects like Docker and
Kubernetes.
● Different (and better?) way of doing concurrency.
● There are no classes/inheritance.
● We want you to learn it :”)
8. Go VS. C++ VS. Java
Go Tutorial - GeeksforGeeks
Feature Java C++ Go (Golang)
Paradigm Object-Oriented Programming
(OOP), Imperative
Procedural, Object-Oriented
Programming (OOP), Generic,
Functional
Procedural, Concurrent, Simplicity-
focused
Compilation Compiled to bytecode, runs on
JVM (platform-independent)
Compiled directly to machine
code (platform-dependent)
Compiled directly to machine code
(platform-independent binaries)
Speed Slower than C++ (due to JVM
overhead)
Fast, closer to hardware Fast, optimized for concurrency
Memory
Management
Automatic (Garbage Collector) Manual (need to handle new
and delete for dynamic
memory)
Automatic (Garbage Collector)
Pointers No direct pointer manipulation Full pointer support Limited pointer usage, safer
9. Go VS. C++ VS. Java
Go Tutorial - GeeksforGeeks
Feature Java C++ Go (Golang)
Error
Handling
Exceptions Exceptions, manual error
checking
Explicit error handling (error
type)
Platform Platform-independent (runs
on JVM)
Platform-dependent Platform-independent
(compiles to static binaries for
any platform)
Performance Moderate performance High performance (low-level
control)
High performance (with
simplicity and concurrency
focus)
Inheritance Supports class-based
inheritance, abstract classes,
and interfaces
Supports multiple inheritance
(with potential complexity)
No traditional inheritance;
uses interfaces and
composition
10. Go Installation
Tutorial: Get started with Go - The Go Programming Language
• Install the compatible version with your machine
(1.22+)
Download and install - The Go Programming Language
• In your text editor (VS Code), create a file hello.go in
which to write your code.
• Paste the following code into your hello.go file and
save the file.
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
11. How it works ?
Go is a compiled language
Programs compile to machine code. There's no VM.
12. Go tools
The tools that come with the Go compiler are utilities designed to enhance
development, testing, debugging, and deployment of Go applications.
These tools are part of the Go toolchain and are automatically available when
you install the Go programming language.
Some of common go tools:
● gofmt and goimports
Gofmt formats code automatically. No options.
Goimports updates import statements based on your workspace.
● go tool
Builds Go programs from source in a conventional directory layout.
● godoc
Generated documentation for the world's open-source Go code.
● Delve Debugger
you can view, add and change breakpoints in a Go program, navigate the program either line-
wise or through breakpoints, inspect variables, functions, and expression values, and finally
analyze all the programs in details.
14. Go Modules
• Your module specifies dependencies needed to run your code, including the
Go version and the set of other modules it requires.
This is our goal to create
Tutorial: Create a Go module - The Go Programming Language
Go module
example.com/greetings
Go package Greetings
Go Src code greetings.go
Go function Hello
Go package Main
Go Src code Main.go
Go function main
go.mod
Call
15. Create Go module
1- In the command prompt Change to Your Home Directory:
>> cd %HOMEPATH%
2- Create a Directory for Your Module:
>> mkdir greetings
>> cd greetings
3- Initialize the Go Module
>> go mod init example.com/greetings
What Happens:
A file named go.mod is created. This file:
○ Tracks the module's name.
○ Specifies the Go version being used.
○ Tracks the dependencies the module relies on.
16. Create Go module
4- Create the Code File greetings.go in the greetings directory
5- Write the Code: in your file greetings.go
for example:
package greetings
import "fmt"
func Hello(name string) string {
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
17. Create Go module
6- Use the Hello Function:
Create another Go program in the same module to call the Hello function. (the main
package) for example:
package main
import (
"example.com/greetings"
"fmt"
)
func main() {
message := greetings.Hello("Developer")
fmt.Println(message)
}
Now you are
ready to test your work
>> go run main.go
18. Go Packages - Import and Export
• Every Go program is made up of packages.
• Programs start running in package main.
Import & Export
Import
Bring in external packages or
libraries into the current file
Two ways:
import (
"fmt"
"math" )
import "fmt"
import "math"
Export
A name is exported so you can
use in another package: If it
begins with a capital letter.
// Exported Function
func SayHello() {
//Code
}
19. Access modifiers in Go
Unlike other languages, there are no specific access modifier keywords.
Instead, Go has a simple approach to access modifiers:
capitalized means public (Exported) and un-capitalized means private
(Unexported) outside package.
package gists
type Sample struct {
PublicField bool // Public/Exported fields
privateField string // Private/Unexported fields in Go
}
20. Semi Columns in Go
Like C, Go's formal grammar uses semicolons to terminate statements,
but unlike in C, those semicolons do not appear in the source.
Instead the lexer uses a simple rule to insert semicolons automatically
as it scans, so the input text is mostly free of them.
Idiomatic Go programs have semicolons only in places such as for loop
clauses, to separate the initializer, condition, and continuation elements.
They are also necessary to separate multiple statements on a line, should
you write code that way.
21. Go Data 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
When you need an integer value you should use int unless you have a specific reason to use a sized or
unsigned integer type.
22. Go Syntax: Variable declaration
var variablename type = value
variablename := value
• Inside a function, the := short assignment statement can be used in
place of a var declaration with implicit type (inferred type).
• Outside a function, every statement begins with a keyword (var, func,
and so on) and so the := construct is not available.
• Go does not allow := at the package level because:
- Top-level declarations require explicit structure .
- This keeps the program easy to read and maintain.
- Global variables should be used sparingly . Encourages proper
scoping
• Rely on the type inference in golang as much as possible (within
• A var statement can be at package or function level.
• You always have to specify either type or value (or both).
• If an initializer is present, the type can be inferred from.
23. Go Syntax: Variable declaration
package main
var a bool
var b, c bool
var e, f int = 1, 2
g := 1
var (
h int
i int = 1
j string =
"hello"
k := 4
)
func main() {
l := 3
var m int
m = 5
24. Go Syntax: Variable declaration
package main
var a bool
var b, c bool
var e, f int = 1, 2
g := 1
var (
h int
i int = 1
j string =
"hello"
k := 4
)
func main() {
l := 3
var m int
m = 5
Package-level bool, default false
Package-level bools, default false
Package-level ints with values 1 and 2
Error: := not allowed at package level
Grouped declarations
Error: := not allowed in grouped declarations
Local int, inferred type, value 3
Local int, default 0
Assign value 5 to m
25. Go Syntax: Constants
const constantname type = value
• Constants are declared like variables, but with the const
keyword.
• Constants can be declared both inside and outside of a
function
• Constants cannot be declared using the := syntax.
Typed Constants UnTyped Constants Grouped Constants
const A int = 1 const A = 1
const (
A = 1
string B =
“Hello”
)
26. Go Syntax: Constant declaration
package main
import "fmt"
const a bool
const b, c bool
const e, f int = 1, 2
g := 1
const(
h int
i int = 1
j string =
"hello"
k := 4
)
func main() {
l := 3
const m int
What would be the output here?
Which will result in an error and which is not?
27. Go Syntax: Enums + iota
Implementing Enums in Golang | Built In
An enumerator, or enum, is a data type in Go that consists of a set
of named, constant values. While Go doesn’t support enums, it
can be implemented using the identifier iota with constants.
What Is Iota in Go?
iota is an identifier that is used with constant and can simplify
constant definitions that use auto-increment numbers. The iota
keyword represents integer constant starting from zero.
28. Go Syntax: Enums + iota
package main
import "fmt"
type Status int
const (
Pending Status = iota // 0
Approved // 1
Rejected // 2
)
func main() {
fmt.Println(
Pending,
Approved,
Rejected
)
// Output: 0 1 2
}
type Permission int
const (
Read Permission = 1 << iota // 1 (0001)
Write // 2 (0010)
Execute // 4 (0100)
)
Works Well with Bitwise Flags
(Unlike Traditional Enums)
Basic example
29. Go Syntax: Enums + iota
const (
C1 = iota + 1
C2
C3
)
fmt.Println(C1, C2, C3)
// "1 2 3"
Start from one
To start a list of constants at 1
instead of 0, you can use iota in
an arithmetic expression.
Skip value
You can use the blank identifier to skip a
value in a list of constants.
const (
C1 = iota + 1
_
C3
C4
)
fmt.Println(C1, C3, C4)
// "1 3 4"
30. Go Syntax: Conditions
If-else
If
If-elseif nested if
if condition {
// code
}
OR
if (condition) {
// code
}
if condition {
// code
} else {
// code
}
if condition1 {
// code
} else if condition2 {
// code
} else {
// code
}
if condition1 {
// code
if condition2 {
// code
}
}
31. Go Syntax: If with short expression
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim
{
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
The if statement can start with a
short statement to execute before
the condition.
Remember: the visibility scope
32. Go Syntax: Conditions
package main
import ("fmt")
func main() {
x:= 14
if x > 15
{
fmt.Println("True")
}
else if (x > 12) {
fmt.Println("False1")
}
else {
fmt.Println("False")
}
}
package main
import ("fmt")
func main() {
x:= 14
if x > 15 {
fmt.Println("True")
} else if (x > 12) {
fmt.Println("False1")
} else {
fmt.Println("False")
}
}
33. Go Syntax: Loops
• Go has only one looping construct, the for loop.
• Unlike other languages like C, Java, or JavaScript:
there are no parentheses surrounding the three components of
the for statement
and the braces { } are always required.
• The init and post statements are optional.
• At that point you can drop the semicolons: For is Go's "while"
for loop
for statement1; statement2; statement3 {
// code to be executed for each
iteration
}
GO’s While
for condition {
// code
}
GO’s infinite loop
for {
// code
}
34. Go Syntax: Loops
package main
import ("fmt")
func main() {
for i:=0; i < 5; i++ {
fmt.Println(i)
}
}
func f2() {
sum := 1
for ; sum < 1000; {
sum += sum
}
fmt.Println(sum)
}
func f1() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
The init and post statements are
optional
GO’s
While
func f3() {
for (i:=0; i < 5; i++)
{
fmt.Println(i)
}
}
35. Go Syntax: Switch statement
• Go's switch is like the one in C, C++, Java, JavaScript, and PHP, except
that
Go only runs the selected case, not all the cases that follow.
In effect, the break statement here is provided automatically in Go.
• All the case values should have the same type as the switch
expression.
• Go's switch cases need not be constants, and the values involved
need not be integers.
Single case
switch expression {
case x:
// code block
case y:
// code block
case z:
...
default:
// code block
}
Multi case
switch expression {
case x,y:
// code block if expression is
evaluated to x or y
case v,w:
// code block case z:
...
default:
// code block
}
36. Go Syntax: Switch statement
With expressions
currentHour :=
time.Now().Hour()
switch {
case currentHour < 12:
// Case is an expression
fmt.Println("Good
morning!")
case currentHour < 18:
fmt.Println("Good
afternoon!")
x := 5
y := 10
switch x + y {
case 10:
fmt.Println("Sum is
10.")
case 15:
fmt.Println("Sum is
15.")
With non-constant variables
func f1() {
a := 3
switch a {
case 1:
fmt.Println("a is one")
case "b":
fmt.Println("a is b")
}
}
Different type as
the switch
expression
37. Go Syntax: Functions
Unnamed Return values
With No return
func FunctionName(param1 type){
// code to be executed
}
Named return values
func FunctionName(param1 type, param2
type) returnType {
// code to be executed
return output
}
func FunctionName(param1 type) returnValueName returnType {
// code to be executed
return returnValueName
}
fun
FunctionName(param1 type)(x int){
// code to be executed
return
}
Naked Return
38. Go Syntax: Functions
func swap(x, y string) (newX, newY string) {
newX, newY = y, x
return newX, newY
}
Named return value
func swap(x, y string) (string, string) {
return y, x
}
Unnamed return value
the return values are not explicitly named in the
function signature
39. Go Syntax: Arrays
• In Go, there are two ways to declare an array:
1. With the var keyword:
var array_name = [length]datatype{values}
// here length is defined
or
var array_name = [...]datatype{values}
// here length is inferred
2. With the := sign:
array_name := [length]datatype{values}
// here length is defined
or
array_name := [...]datatype{values}
// here length is inferred
• If an array or its elements are uninitialized, they get the type's default value.
• Specific array elements can be initialized by index, regardless of var, :=, or
defined/inferred length.
{index0:value0, index3:value3, ...}
40. Go Syntax: Arrays
package main
import ("fmt")
func main() {
arr1 := [5]int{1:10,2:40}
var arr2 = [3]int{1:9,0:3}
arr3 := [...]int{0:2,10:3}
fmt.Println(len(arr3))
arr3[12] = 10
fmt.Println(arr1)
fmt.Println(arr2)
fmt.Println(arr3)
}
What would be the output here?
Based on your answer above,
what do you think about this line’s output?
41. Slices
• Like arrays, slices are also used to store multiple values of
the same type in a single variable.
• Unlike arrays, the length of a slice can grow and shrink as you see fit.
• In practice, slices are much more common than arrays.
• There are several ways to create a slice:
Using the []datatype{values} format
Using the make() function
slice_name := []datatype{values}
var myarray =
[length]datatype{values} // An array
myslice := myarray[start:end]
// A slice made from the array slice_name :=
make([]type, length, capacity)
Create a slice from an array
var myarray =
[length]datatype{values} // An array
myslice := myarray[start:end]
// A slice made from the array
42. Create Slice from an array
Slices are like references to arrays
• A slice does not store any data, it just describes a section of an
underlying array.
• Changing the elements of a slice modifies the corresponding
elements of its underlying array.
• Other slices that share the same underlying array will see those
changes.
• A slice has both a length len(slice) and a capacity cap(slice).
- The length of a slice is the number of elements it contains.
- The capacity of a slice is the number of elements in the underlying
array, counting from the first element in the slice.
• The zero value of a slice is nil.
- A nil slice has a length and capacity of 0 and has no underlying array.
43. Create Slice from an array
package main
func main() {
var array = [6]int{10, 20, 30, 40, 50, 60}
var slice = array[1:4]
}
44. More with Slices in Go
• A Tour of Go
• Go Slices: usage and internals - The Go Programming Language
• GoLang Tutorial - Arrays vs Slices
45. Structs
● A struct (short for structure) is used to create a collection of members of
different data types, into a single variable.
● Unlike arrays, structs are used to store multiple values of different data
types into a single variable.
To declare a structure in Go, use the type and struct keywords:
type struct_name struct {
// fields here
member1 datatype;
member2 datatype;
member3 datatype;
...
}
46. Access Struct Members
using the dot operator (.)
package main
import ("fmt")
type Person struct {
name string
age int
job string
salary int
}
}
func main() {
var pers1 Person
// Pers1 specification
pers1.name = "Hege"
pers1.age = 45
pers1.job = "Teacher"
pers1.salary = 6000
printPerson(pers1)
}
func printPerson(pers Person) {
fmt.Println("Name: ", pers.name)
fmt.Println("Age: ", pers.age)
fmt.Println("Job: ", pers.job)
fmt.Println("Salary: ", pers.salary)
}
Pass Struct as Function Arguments
47. Maps
● Maps are used to store data values in key:value pairs.
● A map is an unordered and changeable collection that does not allow
duplicates.
● The default value of a map is nil.
● Maps hold references to an underlying hash table.
Go has multiple ways for creating maps
1. Using var and :=
var a =
map[KeyType]ValueType{key1:value1,
key2:value2,...}
b :=
map[KeyType]ValueType{key1:value1,
key2:value2,...}
2. Using make()Function:
var a = make(map[KeyType]ValueType)
b := make(map[KeyType]ValueType)
// The map is empty now
48. Access Map Members
package main
func main() {
// using var and :=
var a = map[string]string{"brand": "Ford", "model": "Mustang", "year":
"1964"}
b := map[string]int{"Oslo": 1, "Bergen": 2, "Trondheim": 3, "Stavanger": 4}
// using make() function
var c = make(map[string]string) // The map is empty now
c["brand"] = "Ford"
c["model"] = "Mustang"
c["year"] = "1964" // a is no longer empty
d := make(map[string]int)
d["Oslo"] = 1
d["Bergen"] = 2
d["Trondheim"] = 3
d["Stavanger"] = 4
}
You need to explicitly specify
the types of both the key and the value
49. Maps Are References
package main
import ("fmt")
func main() {
var a = map[string]string{"brand": "Ford", "model":
"Mustang", "year": "1964"}
b := a
fmt.Println(a)
fmt.Println(b)
b["year"] = "1970"
fmt.Println("After change to b:")
fmt.Println(a)
fmt.Println(b)
}
50. Interfaces
Interfaces in Golang - GeeksforGeeks
● The concept is same as Java, but since no OOP in Go, to use this interface
you can make a variable of the interface type to store any value that has
the needed methods.
● Implementation is implicit, no keyword (such as implements) is needed.
type InterfaceName interface {
Method1() returnType
Method2() returnType
}
51. Interface Example
package main
import (
"fmt"
"math"
)
// Define the interface
type Shape interface {
Area() float64
Perimeter() float64
}
// Circle type that implements the
Shape interface
type Circle struct {
radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.radius *
c.radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.radius
}
// Main function to demonstrate the interface
func main() {
var s Shape
s = Circle{radius: 5}
fmt.Println("C Area:", s.Area())
fmt.Println("C Perimeter:", s.Perimeter())
}
52. Interfaces types
1. Type assertion 2. Type switch
switch v := i.(type) {
case T:
// here v has type T
case S:
// here v has type S
default:
// no match; here v has the
same type as i
}
Interfaces in Go -Go 101
A type assertion provides access to
an interface value's underlying
concrete value.
A type switch is a construct that
permits several type assertions
in series.
53. Interfaces Types Example
package main
import "fmt"
func main() {
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
s, ok := i.(string)
fmt.Println(s, ok)
f, ok := i.(float64)
fmt.Println(f, ok)
f = i.(float64) // panic
fmt.Println(f)
}
package main
import "fmt"
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %vn",
v, v*2)
case string:
fmt.Printf("%q is %v bytes long
n", v, len(v))
default:
fmt.Printf("I don't know about
type %T!n", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
Type assertion
Type switch
A Tour of Go
54. Common and useful interface
Golang Interfaces Explained – Alex Edwards
Lastly, here's a short list of some of the most common and useful
interfaces in the standard library.
I recommend taking out a bit of time to look at the relevant
documentation for them.
● builtin.Error
● fmt.Stringer
● io.Reader
● io.Writer
● io.ReadWriteCloser
● http.ResponseWriter
● http.Handler
55. References
• Go Tutorial
• Documentation - The Go Programming Language
• Go for Java Programmers
• Go Programming Language (Introduction) - GeeksforGeeks
• How Go’s Simplicity Brings Complexity