Skip to content

bregman-arie/go-exercises

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go Exercise

ℹ️  This repo contains questions and exercises to learn and practice Golang

📊  There are currently 98 exercises and questions


Hello World
- Exercises
- Questions

Strings
- Exercises
- Questions

Arrays and Slices
- Exercises
- Questions

Loops
- Exercises
- Questions

Exercises

Hello World

Name Exercise Solution Comments
Hello World! Exercise Solution
Variables & Constants Exercise Solution
Arithmetic Operators Exercise Solution
Data Types Exercise Solution
User Input Exercise Solution
Packages Exercise Solution
Logical Operators Exercise Solution
Conditionals Exercise Solution
Switch Exercise Solution

Strings Exercises

Name Exercise Solution Comments
Split Strings Exercise Solution

Arrays and Slices Exercises

Name Exercise Solution Comments
Arrays 101 Exercise Solution
Slices 101 Exercise Solution

Maps Exercises

Name Exercise Solution Comments
Maps 101 Exercise Solution

Loops Exercises

Name Exercise Solution Comments
Loops 101 Exercise Solution
Loops 102 Exercise Solution
Continue Exercise Solution

Functions Exercises

Name Exercise Solution Comments
Functions 101 Exercise Solution
Named Return Values Exercise Solution

Generics Exercises

Name Exercise Solution Comments
Generics 101 Exercise Solution

Questions

Go 101

What are some characteristics of the Go programming language?
  • Strong and static typing - the type of the variables can't be changed over time and they have to be defined at compile time
  • Simplicity
  • Fast compile times
  • Built-in concurrency
  • Garbage collected
  • Platform independent
  • Compile to standalone binary - anything you need to run your app will be compiled into one binary. Very useful for version management in run-time.
True or False? Go is a compiled, statically typed language

True

Why some functions and packages in Go begin with a Capital letter?

Any exported variable, function, ... begins with a capital letter. In fact when using a package, you can use only the things the package exports for you and others to use.

Variables and Data Types

Demonstrate short and regular variable declaration
package main

import "fmt"

func main() {
  x := 2
  var y int = 2

  fmt.Printf("x: %v. y: %v", x, y)
}

True or False?
  • In Go we can redeclare variables
  • Once a variable declared, we must use it
  • False
  • True
What is the result of the following program?
package main

import "fmt"

func main() {
    var userName
    userName = "user"
    fmt.Println(userName)
}

Error. The type userName is not defined. It has to be declared or the value assignment should happen at declaration.

So both var userName = user and var userName string are valid.

What is the difference between var x int = 2 and x := 2?

The result is the same, a variable with the value 2.

With var x int = 2 we are setting the variable type to integer, while with x := 2 we are letting Go figure out by itself the type. The result is the same, both styles can't be used in every situation. For example, short declaration can't be used outside of a function.

What would be the result of executing the following code:
package main

import "fmt"

x := 2

func main() {
    x = 3
    fmt.Println(x)
}

It will fail with expected declaration, found x as outside of a function, every statement should start with a keyword (and short variable declarations won't work).

Demonstrate a block of variable declarations (at least 3 variables)
package main

import "fmt"

var (
  x bool   = false
  y int    = 0
  z string = "false"
)

func main() {
  fmt.Printf("The type of x: %T. The value of x: %v\n", x, x)
  fmt.Printf("The type of y: %T. The value of y: %v\n", y, y)
  fmt.Printf("The type of z: %T. The value of z: %v\n", y, y)
}

What are package level variables? What would be the reason to use them?

Package level variables are variables that defined at the package level instead of a specific function (like main for example).

If you have multiple functions in your package that use the same variables, it might make these variables available to the functions by defining them at the package level. This can be in the same file or any file under the same package. For example:

package main

var packageLevelVar int = 0 

func main() {
  nonPackageLevelVar := 0
}

Conversion

What is the problem with the following block of code? How to fix it?
func main() {
    var x float32 = 13.5
    var y int
    y = x
}

Demonstrate type conversion
package main

import "fmt"

func main() {
    var x int = 2
    fmt.Println(x)
    var y float32 = float32(x)                
    fmt.Println(y)
}

The following block of code tries to convert the integer 101 to a string but instead we get "e". Why is that? How to fix it?
package main

import "fmt"

func main() {
    var x int = 101
    var y string
    y = string(x)
    fmt.Println(y)
}

It looks what unicode value is set at 101 and uses it for converting the integer to a string. If you want to get "101" you should use the package "strconv" and replace y = string(x) with y = strconv.Itoa(x)

Integers

What is the result of the following program?
package main
 
import "fmt"
 
func main() {
    var x uint
    x = -3
    // comment!
    fmt.Println(x)
}

Error. When x is declared as uint it means you can't put any negative values. But because we did put a negative value (-3) it will fail to compile it.

How to print a random integer between 0 and 10?
package main

import (
	"fmt"
	"math/rand"
)

func main() {
	fmt.Println("A random integer:", rand.Intn(10))
}

Constants

Demonstrate decelaration of constants in the following forms:
  • Single constant
  • Multiple constants in one block

// Single constant
const x int = 2732

// Multiple constants in one block
const (
  y = 2017
  z = 2022
)

What is wrong with the following code?:
package main

func main() {
    var x int = 2
    var y int = 3
    const someConst = x + y
}

Constants in Go can only be declared using constant expressions. But `x`, `y` are variables hence, their sum is variable.
const initializer x + y is not a constant

What will be the result of executing the following code?
package main

import "fmt"

func main() {
  const X := 2
  fmt.Print(X)
}

It won't run. Constants cannot be declared using :=.

What will be the result of executing the following code?
package main

import "fmt"

const (
    Const1 = 1 
    Const2 = 1 < 2 
    Const3 = 1 << 10                              
)

func main() {
    fmt.Println(Const1)
    fmt.Println(Const2)
    fmt.Println(Const3)
}

1 true 1024

The 1024 result is because we shifted a 1 bit left 10 places.

Logical Operators

What is the output of the following code?
package main

import "fmt"

func main() {
    x := 2017

    fmt.Println(x > 2022 && x < 3000)
    fmt.Println(x > 2000 && x < 3000)
    fmt.Println(x > 2000 && x&2 == 0)              
}

false
true
false

What is the output of the following code?
package main

import "fmt"

func main() {
    x := 2017

    fmt.Println(x > 2022 || x < 3000)
    fmt.Println(x > 2000 || x < 3000)
    fmt.Println(x > 2000 || x&2 == 0)              
}

true
true
true

What is the output of the following code?
package main
        
import "fmt"
        
func main() {
    x := true
        
    fmt.Println(x)
    fmt.Println(!x)
    fmt.Println(!x && x)
    fmt.Println(!x || x)                   
}

true
false
false
true

Strings

Define a variable with the string value of "Hello, World"
var some_string := "Hello, World"

Define a variable that when printed will give this output:
Hello,
World

var some_string := "Hello,\nWorld"

How to print "Hello,\nWorld" ?
package main

import "fmt"
        
func main() {
    some_string := `Hello,\nWorld`

    fmt.Println(some_string)
}

What would be the output of the following code?
package main
 
import "fmt"
 
func main() {
    some_string := "There"
                              
    fmt.Println("Hello", some_string)
}

Hello There

How to print the length of a character in Go?
package main                         

import "fmt"

func main() {
    str := "Hello, world!"
    fmt.Println(len(str))
}

What would be the output of the following code? Why?
var str string = "cowabunga"
fmt.Println(str[3])

97 Because it prints the ascii code of 'a' which is 97.

Assuming var str string = "cowabunga", What would be the output of the following lines?
  • fmt.Println(str[3:5])

'ab'

How to check if a string variable contains the string "ob1"?

How to turn the string "Hi There" to "hi there" with the strings package?

Conditionals

Define a variable with value of 5. Write a conditional to check if the value of the variable is bigger than 0 and if it is, print "It's bigger than 0!"
x := 5
if x > 0 {
  fmt.Print("It's bigger than  0!")
}

Define a variable with a random value. If its value bigger than 10 print "yay!". If it's smaller than 10, print "nay!"
rand.Seed(time.Now().UnixNano())
var x int = rand.Intn(100)
if x > 10 {
  fmt.Print("yay!")
} else {
  fmt.Print("nay!")
}

What the following code does?
package main
  
import ( 
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    if randNum := rand.Intn(100); randNum%2 == 0 {
        fmt.Print("Bingo!")               
    } else {
        fmt.Print(randNum)
    }       
}

Defines a variable with random value between 0 and 100. If the random value is even, prints "Bingo!" otherwise, prints the random value itself.

Switch

Write a switch case to check what day of the week it is. If Sunday print "Here we go". If Monday print "We have just started". For any other day print the day.
package main

import (
	"fmt"
	"time"
)

func main() {

    today := time.Now().Weekday().String()

    switch today {
    case "Sunday":
      fmt.Println("Here we go")
    case "Monday":
      fmt.Println("We have just started")
    default:
      fmt.Println(today)
	}
}

User Input

Fix the following program to get an input from the user regarding his name and print it
var name string

fmt.Scan(name)

fmt.Println(name)

var name string

fmt.Scan(&name)

fmt.Println(name)

Why when asking for user input, we have to specify &?

Because we want to reference the memory address of the variable, this is where the user input will be stored.

What do we print here?
var age int = 3

fmt.Println(age)
fmt.Println(&age)

The value of age variable and then the memory location of age variable

Arrays and Slices

Define an array of integers of size 4 without value (no items).
var x [4]int

Define an array of the following colors: red, green and blue
var rgb = [3]string{"red", "green", "blue"}

You defined the following array and printed it. What was the output? var numbers = [10]int{}
[0 0 0 0 0 0 0 0 0 0]

Define an array of integers of size 10. All the values should be zeros except first one which should be 5 and the last one which should be 100
var arr = [10]int{5, 9: 100}

What would be the result of the following code?
var arr = [...]int{1, 2, 3, 4}
var anotherArr = [4]int{1, 2, 3, 4}
fmt.Println(arr == anotherArr)

The result of comparison is true.

Assuming there is a defined array called arr, print its length
fmt.Println(len(arr))

True or False? An array of type [1]int is the same type as an array of [2]int

False. Go treats the array size as being part of the type itself. So [1]int type != [2]int type.

True or False? If var x := 2, then var y [x]int is an array of size 2

False. It's not possible to use variable to define an array of certain size. As the size of an array is part of its type and types must be resolved at compile time, not runtime.

Demonstrate defining the following slices:
  • without values (with nil)
  • with two values

var slice []int var slice = []int{1, 2}

Append to a slice called b the number 7

b = append(b, 7)

Given that var slice = []int{2, 0, 1, 7} what would be the result of slice = append(slice, 2, 0, 2, 2)

[2 0 1 7 2 0 2 2]

How to compare two slices?
package main

import (
    "fmt"
    "reflect"
)

func main() {
    x := []int {2, 0, 1, 7}
    y := []int {2, 0, 2, 2}

    fmt.Println(reflect.DeepEqual(x, y))
}

Why in Go you need assign the value returned from append function as opposed of other programming languages like Python, where you don't need to do it?

Because in Go when you pass a something to a function, it copies it. So when we append something to a slice it appends it to a copy of it. So in order to change the original slice, we need to assign the returned copy back into the original slice.

How create a slice of capacity (not size) of 20?

slice := make([]int, 20)

How create a slice of size 3 ad capacity of 10?

slice := make([]int, 3, 20)

What's the use case for defining in advance the capacity of a slice?

It's more efficent to set the size once for a slice rather than increase its capacity every times new items added to it.

What's the value of slice after running the following code? Why?
slice := make([]int, 3)
slice = append(slice, 41)

[0 0 0 41]

True or False? When specifying the capacity of a slice, it's always best to specify a capacity that is bigger than the slice size

True. Otherwise it will cause compile-time error or run-time error, depends on how you defined it.

Given slice := []int{1, 2, 3, 4, 5} what would be the result of the following expressions:
  • slice[:]
  • slice[2:]
  • slice[:1]
  • slice[2:4]

  • [1 2 3 4 5]
  • [3 4 5]
  • [1]
  • [3 4]
What's the output of the following program?
slice := []int{1, 2, 3}
anotherSlice := slice[1:]
slice[1] = 999
anotherslice[1] = 5
fmt.Println("slice:", slice)
fmt.Println("slice:", anotherSlice)

[10 999 3]
[999 5]

The expalantion is that slicing a slice isn't creating a copy of the data but rather creates another variable that shares the very same memory.

How to create an independant slice of a slice?

When creating a slice of a slice, it will create variable that shares the same memory. To create a slice that is indepdant of the original slice, you can use the built-in function copy

slice := []int{1, 2, 3}
destSlice = make([]int, 3)
numOfElements := copy(slice, destSlice)

Loops

Define a simple for loop with following components:
  • variable i initialized to 0
  • expression where the variable should be smaller than 50
  • at the end of each iteration the variable value should be incremented by 1
  • In the loop itself, the value of variable i should be added to a variable called sum (initialize the variable before the loop with value of 0)

sum := 0
for i := 0; i < 50; i++ {
    sum += i
}

Implement infinite loop
for {
    fmt.Print("forever!")
}

What's the difference between the following two loops?
for {
    fmt.Print("forever!")
}

for true {
    fmt.Print("forever!")
}

From result perspective, there is no difference. Both are infinite loops.

Maps

Define the following map variables:
  • an empty map where all keys are of string type, as well as the values
  • an empty map where all the keys are of string type and the values are of int type
  • A map with string type keys and int array values (non empty map, populate it with data)
  • Empty map with int type keys and string type values of size 100

var someMap = map[string]string

anotherMap := map[string]int{}

nonEmptyMap := map[string][]int{
  "someKey": []int{1, 2, 3},
  "anotherKey": []int{4, 5, 6},
}

someMap := make(map[int][]string, 100)

True or False? All keys in a single map, should have the same data type

True. This is also true for the all the values in a single map.

How to check the number of key-value pairs in a map?

len(someMap)

True or False? To compare maps, one can use "==" this way someMap == anotherMap

False.

What's the output of the following code?
someMap := map[string]int{}
someMap["x"] = 41
fmt.Println(someMap["y"])

0

What's the output of the following code?
someMap := map[string]int{
  "x": 41,
}
value, exists := someMap["x"]
fmt.Println(value, exists)
value, exists = someMap["y"]
fmt.Println(value, exists)

41 true 0 false

Remove from the following map the key-value pair of "y"
someMap := map[string]int{
  "x": 41,
  "y": 303,
  "z": 56,
}

delete(someMap, "y")

Functions

Define a function that prints "Hello World"
func PrintHelloWorld() {
    fmt.Println("Hello World")
}

What the following code does?
func add(x int, y int) int {
    return x + y
}

add is a function that takes two parameters (two integers) and returns their sum.

Which of the following functions will work just fine?
func add(x int, y int) int {
    return x + y
}

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

Both. If two or more parameters share the same type, you can specify it only once.

True or False? A function in Go can return either zero or one values, but not more than that

False. A fucntion in Go can return multiple values

Write code that will execute the following function in a valid way
func swap(x, y string) (string, string) {
    return y, x
}

x, y = swap("and roll", "rock")
fmt.Println(a, b)

What is the result of the following code?
func process(num int) (x int) {
    x = num + 10
    var z = num - x
    x = z + x
    return
}

func main() {
  fmt.Println(process(10))
}

10

Defer

What will be the output of the following code? Why?
package main

import "fmt"

func main() {
    defer fmt.Println("1")

    fmt.Println("2")
}

2
1

2 is printed before 1 due to the defer statement. The defer statement defers the execution of the function (fmt.Println("1")) until the surrounding fucntion (which is main()) returns.

True or False? The arguments of a deferred functions are evaluated but the function itself isn't called until the surrounding function returns

True.

What will be the output of the following code? Why?
package main

import "fmt"

func main() {
    fmt.Println("100")

    for i := 0; i < 10; i++ {
      defer fmt.Println(i)
    }

    fmt.Println("200")
  }

100
200
9
8
7
6
5
4
3
2
1
0

Deferred functions are executed in a last-in-first-out order, this is why it prints it from 9 to 0 instead of from 0 to 9.

Packages

How do you export a variable or a function in Go for other packages to use?

Capitalize the first letter of what you would like to export.

What are different levels of scope of variables?
  • Local
  • Package
  • Global

Generics

How can you define your custom generic type in Golang?

By creating an interface.

package main

type C interface {
	int | int32 | string
}

Why can we send both int and string to following function?
package main

import "fmt"

type C interface {
  int | int32 | string
}

func show[T C](input T) {
	fmt.Println(input)
}

Because we created show function as a generic function. Therefore it can get types that we have in C.

Change this function to accept any type in Golang.
package main

import "log"

func do_log(input string) {
	log.Print(input)
}

Use any keyword.

package main

import "log"

func do_log(input any) {
	log.Print(input)
}

Projects

Name Description Solution Comments
Simple Web Server Description Solution

Credits

Images

Go Gopher was designed by Renee French. The specific Go Gophers designs used in this project created by Arie Bregman