[
  {
    "path": ".gitignore",
    "content": "logger\n.DS_Store"
  },
  {
    "path": ".nojekyll",
    "content": "\n"
  },
  {
    "path": "01-basics/01-hello/README.md",
    "content": "# Your first program\n\nThis lesson covers some history of Go and also teaches you how to build your first Go app.\n\n> Watch the video\n> [![your first Go program](https://img.youtube.com/vi/1825FjiewWs/0.jpg)](https://www.youtube.com/watch?v=1825FjiewWs)\n\n## Introduction\n\nIn this lesson we'll cover:\n\n- The history of Go\n- Why use Go for your apps\n- The anatomy of a Go app\n- Authoring and running your first app\n\n## A history of Go\n\nThe language is called Go but is sometimes known as Golang as the first website for it was golang.org.\n\nGo was created in 2009 by Robert Griesemer, Rob Pike and Ken Thompson. It's hard to estimate the number of Go developers but it's somewhere between 1.1 and 2.7 million, quite a sizeable amount. More than 2500 companies are using Go including, Google, Pinterest and Uber. So, you see, used by a lot of folks by big companies.\n\n> Why was Go created?\n\nAs is often the case, a programming language is created to deal with the shortcomings of other languages. In this case, the creators wanted this new language to have the following capabilities:\n\n- **Static typing** and run-time efficiency from C.\n- **Readability** from JavaScript and Python.\n- **High-performance** networking and multi-processing.\n\nIt seems the creators agreed on disliking C++ :)\n\n## What is it used for though?\n\nHere's some areas where you are likely to find a Go being used:\n\n- Cloud based and server-side apps.\n- DevOps, automation.\n- Command-line tools.\n- AI and data science.\n\n## References\n\nThere are many great resources out there for learning the Go programming language like:\n\n- <https://go.dev/>\n- <https://www.tutorialspoint.com/go/index.htm>\n- <https://gobyexample.com/>\n- <https://www.w3schools.com/go/>\n- <https://docs.microsoft.com/en-us/learn/modules/go-get-started/>\n- <https://docs.microsoft.com/en-us/learn/modules/serverless-go/>\n\n## Features\n\nSo, what features makes Go compelling? Well, there are some features worth mentioning:\n\n- **Static typing**, I like my types :)\n- **Package system**. You can consume and create your own packages. Go to [pkg.go.dev](https://pkg.go.dev/) to read more on what packages there are.\n- **Command-line tools**, there's a set of executables that are installed when you install Go. With these executables, you can run, build, install packages, run tests and much more.\n- **Standard library**. Go has a powerful standard library that will help you with most things you might need. You can read more about what's in the [standard library](https://pkg.go.dev/std) here.\n- **Built-in testing**. Having a testing library that just works out of the box is something you shouldn't take for granted.\n- Concurrency. Go is great at handling concurrency. It uses concepts like goroutines and channels.\n- **Garbage collection**. You can read more about that [here](https://medium.com/safetycultureengineering/an-overview-of-memory-management-in-go-9a72ec7c76a8#:~:text=Go%20has%20all%20goroutines%20reach,the%20collector%20to%20run%20simultaneously). I like when I don't have to deal with that myself and just focusing on solving problems.\n\n## Install Go\n\nOk then, hope you are intrigued at this point and just want to see some code? Of course, you are :)\n\nMake sure you've followed the instructions for installing Go on your machine.\n\n> <https://go.dev/doc/install>\n\n## A Go program\n\nHere's what a first program can look like:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"hello\")\n}\n```\n\n### The program in detail\n\n- `package main`, the entry point module needs to have this instruction.\n- `import \"fmt\"`, fmt is standard package for input and output.\n- `func main`, entry point function, where your program starts.\n\n## Commands\n\nNow that you have a program, there's two things you might want to do:\n\n- **Run it**, to see if it compiles and runs.\n- **Create executable**, an executable is no longer Go code but like any executable program on your machine.\n\n### Run your app\n\nTo run your app, type `go run <file>.go`, for example:\n\n```bash\ngo run main.go\n```\n\n### Build your app\n\nTo produce an executable, run `go build <file>.go`, for example:\n\n```bash\ngo build main.go\n```\n\nIt produces an executable, on MacOS and Linux that's a file with -X as permission, on Windows, it's a .exe file.\n\nCongrats, you've created your first Go application.\n\n## Summary\n\nIn this article, you learned about the programming language Go, some features it has and how to write your first program.\n\n## 🚀 Challenge\n\nCompare Go to other programming languages, can you list some differences between them?\n\n## Review & Self Study\n\nSelect one of the resources below and try do a tutorial.\n\n- <https://go.dev/>\n- <https://www.tutorialspoint.com/go/index.htm>\n- <https://gobyexample.com/>\n- <https://www.w3schools.com/go/>\n- <https://docs.microsoft.com/en-us/learn/modules/go-get-started/>\n- <https://docs.microsoft.com/en-us/learn/modules/serverless-go/>\n\n## Assignment\n\nCreate a file *main.go*. Use the `fmt` library to print out to the console. Remember that your run programs with `go run <my program>.go`.\n\n## Solution\n\nCreate a file *main.go*\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n  fmt.Println(\"printing to the console\")\n}\n```\n"
  },
  {
    "path": "01-basics/01-hello/assignment.md",
    "content": "# Build an app\n\n## Instructions\n\nCreate a file *main.go*. Use the `fmt` library to print out to the console. Remember that your run programs with `go run <my program>.go`. "
  },
  {
    "path": "01-basics/01-hello/go.mod",
    "content": "module hello\n\ngo 1.17\n"
  },
  {
    "path": "01-basics/01-hello/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"hello\")\n\tfmt.Println(\"hey Chris\")\n\tvar name = \"Chris\"\n\tvar age = 20\n\tfmt.Printf(\"%s again, %d\", name, age)\n}\n"
  },
  {
    "path": "01-basics/02-variables/README.md",
    "content": "# Using variables\n\nWith variables, we can remember values and later refer to them via named references. using variables will make our code easier to read.\n\n## Introduction\n\nIn this lesson we'll cover:\n\n- The usage of variables in Go.\n- How to create them.\n- Assign different types and values.\n\n## Declare variables\n\nIn Go, there are many ways to declare variables:\n\n- **Define a name and type**. Here, you declare a variable with the keyword `var`, give it a name and lastly a type `string`. Below is an example:\n\n    ```golang\n    var firstName string\n    ```\n\n- **Define a group** of variables. It's possible to define a group of variables. Using this way of declaring means you only type the `var` keyword once. The group is defined using parenthesis `()`:\n\n   ```golang\n   var (\n     firstName = \"Chris\"\n     age = 20\n   )\n   ```\n\n    Note how each variable is on a new row.\n\n- **Define and assign a value**. Within functions, you can use the `:=` operator, it declares and assigns at the same time. The below code shows the creation of the `firstName` variable. The data type is inferred to be a string:\n\n   ```go\n   firstName := \"Chris\"\n   ```\n\n## Assign variables\n\nTo assign a new value to a variable, it needs to exist first. You use the assignment operator, `=`. Here's an example:\n\n```go\nfirstName = \"Mike\"\n```\n\n## Data types\n\nThere are many data types you can use with Go. They are divided into different categories:\n\n- **Basic types**. In this category, we find types like integers, floats (numbers with decimals) and other types like Booleans (for true/false), strings (for text) and more.\n- **Composite types**. We will talk about composite types in a separate article, but they are more complex, and examples of composite types are arrays, structs and interfaces.\n\n### Declare a variable with a type\n\nThere are two ways you can declare a variable and give it a type:\n\n- **explicitly**, by specifying its type, for example:\n\n   ```go\n   var name string\n   ```\n\n- **implicitly**, by assigning it a value and having it been inferred:\n\n   ```go\n   name := \"chris\"\n   ```\n\n   In the preceding code, the data type is inferred by the value you give it. In this case, the data type becomes `string` based on the value \"chris\".\n\n## String interpolation\n\nSometimes, you want to be able to write things to the screen and mix different data types doing so. For example, you might want to write, \"Customer: Adam has 20$ in his bank account\".\n\nLet's say then that this information is represented by these two variables:\n\n```go\nvar (\n  customerName = \"Adam\"\n  accountBalance = 20\n)\n```\n\nHow can you print out the text above? For this purpose, you can use the `Printf()` function that takes formatters. The idea is that a formatter is an instruction to what a certain type is. By providing this information to `Printf()`, it's able to print the type correctly.\n\nHere's how you can print the example string from before:\n\n```go\nfmt.Printf(\"Customer %s has %d$ on their bank account\", customerName, accountBalance)\n```\n\nAbove, the `%s` represents a string and `%d` represents a number. By using these formatters as placeholders, the variables are correctly implemented, and the output becomes:\n\n```output\nCustomer Adam has 20$ on their bank account\n```\n\n## Assignment - define some variables and print them out\n\nDefine some variables you might need for the card game Texas Holdem and print them out.\n\nCreate a file *main.go* and give it the following content:\n\n   ```go\n    package main\n    \n    import \"fmt\"\n    \n    func main () {\n    }\n   ```\n\n1. Add the following variables after the import section:\n\n   ```go\n   var (\n     players = 3\n     replay = false\n     namePlayerOne = \"chris\"\n   )\n   ```\n\n   Now you have:\n\n   - `players`, to represent the number of players in the game.\n   - `replay`, a boolean stating whether to start a new game session when the old one has ended.\n   - `namePlayerOne`, a string representing the name of the first player.\n\n   All of these variables help describe essential information in a Texas Holdem game.\n\n   Next, let's run our app to make sure it works.\n\n1. Add the following code to the `main()` function to print out the variables:\n\n   ```go\n   fmt.Println(players)\n   fmt.Println(replay)\n   fmt.Println(namePlayerOne)\n   ```\n\n1. Run `go run main.go` in the terminal:\n\n   ```go\n   go run main.go\n   ```\n\n   You should see the following output:\n\n   ```output\n    3\n    false\n    chris\n   ```\n\n   Great, you now have a starting point for an app you can keep building on.\n\n## 🚀 Challenge\n\nSee if you can come up with more variables to represent the state in a Texas Holdem card game, like for example, other players, the card deck etc. What data type would you give those variables?\n\n## Review & Self Study\n\nHave a look at this [official tutorial on variables](https://go.dev/tour/basics/8) using a Go sandbox\n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\nvar (\n  players = 3\n  replay = false\n  namePlayerOne = \"chris\" \n)\n\nfunc main () {\n  fmt.Println(players)\n  fmt.Println(replay)\n  fmt.Println(namePlayerOne)\n}\n```\n"
  },
  {
    "path": "01-basics/02-variables/exercise.go",
    "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// defining variables\n// with and without type\n// the other way with :=\n\n// package main\n\n// import \"fmt\"\n\n// var (\n// \tname string\n// )\n\n// func main() {\n// \tname = \"chris\"\n// \tfmt.Println(name)\n// }\n"
  },
  {
    "path": "01-basics/02-variables/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nvar (\n\tplayers        = 3\n\treplay         = false\n\tnamePlayerOne  = \"chris\"\n\tPI             = 3.14\n\tcustomerName   = \"Adam\"\n\taccountBalance = 20\n)\n\nfunc main() {\n\tfmt.Println(players)\n\tfmt.Println(replay)\n\tfmt.Println(namePlayerOne)\n\tfmt.Println(PI)\n\n\tfmt.Printf(\"Customer %s has %d on his bank account\", customerName, accountBalance)\n}\n"
  },
  {
    "path": "01-basics/03-if-and-else/README.md",
    "content": "# Flow control\n\nIn this chapter, we're looking to learn about constructs `if` and `else` to control the flow of your application.\n\n## Introduction\n\nThis chapter will cover:\n\n- Working with Boolean logic.\n- Create Boolean data.\n- Use constructs like `if`, `else if` and `else`.\n\n## What is flow control\n\nUsing Boolean logic in your program is about creating different execution paths through your code?\n\n> What does that mean?\n\nIt means there's more than one way that your program can run depending on what data you feed it.\n\n> Ok, can you show me?\n\nSure, consider this code:\n\n```go\nprintMessage := true\n\nif printMessage {\n  fmt.Println(\"Message\")\n}\n```\n\nIf `printMessage` is `true`, the string \"Message\" will print. If the value is `false`, nothing will print.\n\n> Ok, I think I get it.\n\n## The `if` construct\n\nYou've seen an example already about code that runs or doesn't run depending on a value. The `if` construct is what makes that possible. An `if` take a Boolean expression like so:\n\n```go\nif true {\n  // statements here will always run\n}\n```\n\n### Using a Boolean variable\n\nWhen you use a Boolean value as part of your Boolean expression, it needs to be evaluated. Here's code showing just that:\n\n```go\naccountBalance = 100\naccountCredit = 200\nif accountBalance + accountCredit > 0 {\n  fmt.Println(\"You have money to spend\")\n}\n```\n\nThe program above does the job, meaning it correctly evaluates whether you have money to spend. However, you might want to print something out if the condition is not met, for that you have `else`.\n\n### Introducing `else`\n\nYou would like to improve the preceding code. The `else` clause is run when `if` is evaluated to false. Here's how you can add it to the program:\n\n```go\naccountBalance = 100\naccountCredit = 200\nif accountBalance + accountCredit > 0 {\n  fmt.Println(\"You have money to spend\")\n} else {\n  fmt.Println(\"No money left, please add more funds\")\n}\n```\n\n## Using `else if`\n\n`if` and `else` take you far. Sometimes, it's not enough. You might need to grade a course at different levels depending on the points achieved on the exam. For this situation, you need an `else if` construct, a construct that will be evaluated if the `if` construct evaluates to false. It differs from `else` in that it also takes an expression. Here's an example where it's used:\n\n```go\nif testScore >= testScoreGrade5 {\n  fmt.Println(\"Top mark\")\n } else if testScore >= testScoreGrade4 {\n  fmt.Println(\"Pass with distinction\")\n } else if testScore >= testScoreGrade3 {\n  fmt.Println(\"Pass with distinction\")\n } else {\n  fmt.Println(\"Failed\")\n }\n```\n\n## Multiple expressions\n\nYour expression can examine more than one variable or condition. There are Boolean operators you can use to help you. Here are some operators you are likely to encounter:\n\n- `&&`, evaluates to true if values on the left and right side are both true. Here's an example of this operator in use:\n\n    ```go\n    hasGas := true\n    hasKeyInIgnition := true\n    if hasGas && hasKeyInIgnition {\n      fmt.Println(\"Can drive car\")\n     }\n    ```\n\n    In the preceding code, the expression will evaluate to true as both `hasGas` and `hasKeyInIgnition` is true.\n\n- `||` , evaluates to true if either left or right value is true. Here's an example of this operator in use:\n\n  ```go\n  hasBurger := true\n  hasSandwich := false\n\n  if hasBurger || hasSandwich {\n    fmt.Println(\"Can eat\")\n  }\n  ```\n\n  In the preceding code, `hasBurger` is true and that's enough for this expression to become true.\n\n- `!`, also known as NOT, it will negate the expression. Here's an example:\n\n   ```go\n   hasSandwich := false\n\n   if !hasSandwich {\n    mt.Println(\"No sandwiches, then I will starve, I only eat sandwiches\")\n   }\n   ```\n\n   Above, the expression will evaluate to true, thanks to the negation with `!`.\n\n## Assignment - create a program that tests your Boolean logic\n\nIn this assignment, you are creating a program that tests out various Boolean logic.\n\n1. Create a file *main.go* and give it the following content:\n\n   ```go\n    package main\n\n    import \"fmt\"\n    \n    func main() {\n     testScoreGrade5 := 80\n     testScoreGrade4 := 60\n     testScoreGrade3 := 50\n     testScore := 49\n    \n     hasGas := true\n     hasKeyInIgnition := true\n    \n     hasBurger := true\n     hasSandwich := false\n    \n     printMessage := true\n     if printMessage {\n      fmt.Println(\"Message\")\n     }\n    \n     if testScore >= testScoreGrade5 {\n      fmt.Println(\"Top mark\")\n     } else if testScore >= testScoreGrade4 {\n      fmt.Println(\"Pass with distinction\")\n     } else if testScore >= testScoreGrade3 {\n      fmt.Println(\"Pass with distinction\")\n     } else {\n      fmt.Println(\"Failed\")\n     }\n    \n     if hasGas && hasKeyInIgnition {\n      fmt.Println(\"Can drive car\")\n     }\n    \n     if hasBurger || hasSandwich {\n      fmt.Println(\"Can eat\")\n     }\n    \n     if !hasSandwich {\n      fmt.Println(\"No sandwiches, then I will starve, I only eat sandwiches\")\n     }\n    }\n   ```\n\n1. Run the command `go run main.go`, to run the program\n\n   ```bash\n   go run main.go\n   ```\n\n   You should see the following output:\n\n   ```output\n    Message\n    Failed\n    Can drive car\n    Can eat\n    No sandwiches, then I will starve, I only eat sandwiches\n   ```\n\n1. Try playing around with the code, how does the output change if you change `testScore` value to 51, 62, 3 or 90?\n\n## 🚀 Challenge\n\nA test score shouldn't be negative, how can you add a check for that?\n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n testScoreGrade5 := 80\n testScoreGrade4 := 60\n testScoreGrade3 := 50\n testScore := 49\n\n hasGas := true\n hasKeyInIgnition := true\n\n hasBurger := true\n hasSandwich := false\n\n printMessage := true\n if printMessage {\n  fmt.Println(\"Message\")\n }\n\n if testScore >= testScoreGrade5 {\n  fmt.Println(\"Top mark\")\n } else if testScore >= testScoreGrade4 {\n  fmt.Println(\"Pass with distinction\")\n } else if testScore >= testScoreGrade3 {\n  fmt.Println(\"Pass with distinction\")\n } else {\n  fmt.Println(\"Failed\")\n }\n\n if hasGas && hasKeyInIgnition {\n  fmt.Println(\"Can drive car\")\n }\n\n if hasBurger || hasSandwich {\n  fmt.Println(\"Can eat\")\n }\n\n if !hasSandwich {\n  fmt.Println(\"No sandwiches, then I will starve, I only eat sandwiches\")\n }\n}\n\n```\n\n## Review & Self Study\n\nHave a look at this [official tutorial on flow control](https://go.dev/tour/flowcontrol/6) using a Go sandbox.\n"
  },
  {
    "path": "01-basics/03-if-and-else/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\ttestScoreGrade5 := 80\n\ttestScoreGrade4 := 60\n\ttestScoreGrade3 := 50\n\ttestScore := 49\n\n\thasGas := true\n\thasKeyInIgnition := true\n\n\thasBurger := true\n\thasSandwich := false\n\n\tprintMessage := true\n\tif printMessage {\n\t\tfmt.Println(\"Message\")\n\t}\n\n\tif testScore >= testScoreGrade5 {\n\t\tfmt.Println(\"Top mark\")\n\t} else if testScore >= testScoreGrade4 {\n\t\tfmt.Println(\"Pass with distinction\")\n\t} else if testScore >= testScoreGrade3 {\n\t\tfmt.Println(\"Pass with distinction\")\n\t} else {\n\t\tfmt.Println(\"Failed\")\n\t}\n\n\tif hasGas && hasKeyInIgnition {\n\t\tfmt.Println(\"Can drive car\")\n\t}\n\n\tif hasBurger || hasSandwich {\n\t\tfmt.Println(\"Can eat\")\n\t}\n\n\tif !hasSandwich {\n\t\tfmt.Println(\"No sandwiches, then I will starve, I only eat sandwiches\")\n\t}\n}\n"
  },
  {
    "path": "01-basics/04-conversions/README.md",
    "content": "# Converting between types\n\nThis chapter covers how to convert between strings and numbers.\n\n## Introduction\n\nThis chapter will:\n\n- Introduce uses cases where data conversion makes sense.\n- Showcase how to use `strconv` library.\n\n## Why convert between types\n\nThere are different data types and a need to convert between them. For example, we often need to convert between text and numbers for presentational and other reasons. We also need to convert between numbers and decimals without losing information in the process.\n\nThe main package for dealing with conversions in Go is `strconv`.\n\n## Use case - command-line arguments\n\nLet's show a common case where you start off with strings and you need to make it into numbers, command-line arguments. To use command-line arguments in a program, you need the `os` package.  \n\n`os.Args` points to an array representing your command line arguments. To access a specific argument, you would use the index operator `[]` like so:\n\n```go\narg := os.Args[1]\n```\n\nYou can then start your program like so:\n\n```bash\ngo run main.go 1\n```\n\nThe 1 would then be stored in `arg`.\n\n### Finding the type\n\nWhat type is `arg` in our code above? There are some ways to find out:\n\n- **IDE**, if you use for example Visual Studio Code and the Go plugin, hovering over the code, it will tell you that `os.Args` is a string array, `string[]`.\n- **PrintF() and %T**. One of the easiest ways to find the type is typing like so:\n\n   ```go\n   Printf(\"%T\", os.Args[1])\n   Printf(\"%T\", 1)\n   ```\n\n   You would get an output like so:\n\n   ```output\n   string\n   int\n   ```\n\n- **Type coercion**, you could try to modify that code and coerce it to be an integer like so, now what?\n\n    ```go\n    var no int = os.Args[1]\n    ```\n\n    You get an error:\n\n    ```output\n    cannot use os.Args[1] (type string) as type int in assignment\n    ```\n\n- **Use reflection**. Another way to find the above is by using the `reflect` package like so:\n\n    ```go\n    package main\n    \n    import (\n      \"reflect\"\n      \"fmt\"\n      \"os\"\n    )\n    \n    func main () {\n      arg := os.Args[1]\n      fmt.Println(reflect.TypeOf(arg))\n    }\n    ```\n\n    Now, the program will print \"string\" as the type.\n\n### Addressing the problem with `strconv`\n\nOk, so we know what type something is, what if we need to use these command-line arguments, which are of type `string`, and feed them into let's say a calculator program?\n\nConsider the below code, that at present WOULDN'T compile:\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"os\"\n)\n\nfunc add(first int, second int) int {\n  return first + second\n}\n\nfunc main() {\n  add(os.Args[1], os.Args[2]) // this would NOT compile\n}\n```\n\nThe reason is that the values on `os.Args[1]` and `os.Args[2]` are `string` not `int`. To fix this issue, we need to use the conversion package `strconv`.\n\n## Convert from string to int with `strconv`\n\nTo convert strings to integers, we need to use `strconv` and call the `Atoi()` (stands for Ascii to integer) function like so:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"os\"\n \"strconv\"\n)\n\nfunc add(first int, second int) int {\n return first + second\n}\n\nfunc main() {\n no1, _ := strconv.Atoi(os.Args[1])\n no2, _ := strconv.Atoi(os.Args[2])\n var sum = add(no1, no2) \n fmt.Println(sum)\n}\n```\n\nNote `_`, this is a *don't care* symbol. What happens when you call `Atoi()` is that it returns two things, the number and an error if it fails.\n\n### Handling conversion error\n\nTo handle an error, we need to store it in a variable, `err` and inspect it. If it's not `nil`, then we have an error.\n\nHere's how we could encode that behaviour below:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"os\"\n \"strconv\"\n)\n\nfunc main() {\n no, err := strconv.Atoi(os.Args[1])\n fmt.Println(no)\n if err != nil {\n  fmt.Println(err)\n  fmt.Println(\"Couldn't convert: \" + os.Args[1])\n\n } else {\n  fmt.Println(no)\n }\n}\n```\n\nTry to compile the above program and run it like so:\n\n```bash\nmain 1 # 1\nmain hi # trconv.Atoi: parsing \"hi\": invalid syntax, Couldn't convert: hi\n```\n\n## Parse string to int\n\nThere's another way to convert a string to an int. That's by using the `ParseInt()` method. It does more than converting though, it does two things in fact:\n\n- **base**, you can select according to what base to interpret the number as.\n- **size**, bit size, from 0 to 64.\n\nThe syntax for the method looks like so:\n\n```go\nParseInt(<s string>, <base int>, <bit int>) (int64, error)\n```\n\nHere's some examples:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"reflect\"\n \"strconv\"\n)\n\nfunc main() {\n var no int = 100\n fmt.Println(reflect.TypeOf(no))\n\n var intStr string = \"100\"\n fourBaseEightBitInt, _ := strconv.ParseInt(intStr, 4, 8)    // becomes no 16 and int64\n tenBaseSixteenBitInt, _ := strconv.ParseInt(intStr, 10, 16) // no 100,  and int64\n fmt.Println(reflect.TypeOf(fourBaseEightBitInt))\n fmt.Println(reflect.TypeOf(tenBaseSixteenBitInt))\n}\n```\n\n## Integer to string\n\nYou might be dealing with the opposite; you have an integer, and you want it to be a string. In this case, you can use the `Itoa()` function, integer to ascii. Here's an example:\n\n```go\nvar noOfPlayers = 8\nstr := strconv.Itoa(noOfPlayers)\n\n```\n\n## Additional parsing\n\nThe `strconv` library is what you want if you start with a string, and you want to convert to and from another format. Learn more about [strconv library here](https://pkg.go.dev/strconv)\n\n## Assignment\n\nCreate an app that adds two numbers together. The values should come from the command line. Here's how the program should run:\n\n```bash\ngo run main.go 2 4\n6\n```\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"os\"\n \"strconv\"\n)\n\nfunc add(no int, secondNumber int) int {\n return no + secondNumber\n}\n\nfunc main() {\n no1, _ := strconv.Atoi(os.Args[1])\n no2, _ := strconv.Atoi(os.Args[2])\n var sum = add(no1, no2)\n fmt.Println(sum)\n}\n```\n\n## 🚀 Challenge\n\nWhat happens if run the program like so?\n\n```bash\ngo run main.go one two\n```\n\nHandle any conversion error and call `panic()` if there's a conversion error.\n"
  },
  {
    "path": "01-basics/04-conversions/assignment.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n)\n\nfunc add(no int, secondNumber int) int {\n\treturn no + secondNumber\n}\n\nfunc main() {\n\tno1, err := strconv.Atoi(os.Args[1])\n\tif err != nil {\n\t\tfmt.Errorf(\"Error converting %s to a number\", os.Args[1])\n\t\tpanic(err)\n\t}\n\tno2, err := strconv.Atoi(os.Args[2])\n\tif err != nil {\n\t\tfmt.Errorf(\"Error converting %s to a number\", os.Args[2])\n\t\tpanic(err)\n\t}\n\n\tvar sum = add(no1, no2)\n\tfmt.Println(sum)\n}\n"
  },
  {
    "path": "01-basics/04-conversions/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"strconv\"\n)\n\nfunc add(first int, second int) int {\n\treturn first + second\n}\n\nfunc main() {\n\tno := os.Args[1]\n\tfmt.Println(reflect.TypeOf(no))\n\tno1, _ := strconv.Atoi(os.Args[1])\n\tno2, _ := strconv.Atoi(os.Args[2])\n\tvar sum = add(no1, no2)\n\tfmt.Println(sum)\n\tfmt.Printf(\"%T\", os.Args[1])\n\tfmt.Printf(\"%T\", 1)\n}\n"
  },
  {
    "path": "01-basics/04-conversions/reflecting.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n)\n\nfunc main() {\n\tvar no int = 100\n\tfmt.Println(reflect.TypeOf(no))\n\n\tvar intStr string = \"100\"\n\tfourBaseEightBitInt, _ := strconv.ParseInt(intStr, 4, 8)    // becomes no 16 and 8bit\n\ttenBaseSixteenBitInt, _ := strconv.ParseInt(intStr, 10, 16) // no 100,  16 bit\n\tfmt.Println(fourBaseEightBitInt)\n\tfmt.Println(tenBaseSixteenBitInt)\n\tfmt.Println(reflect.TypeOf(fourBaseEightBitInt))\n\tfmt.Println(reflect.TypeOf(tenBaseSixteenBitInt))\n}\n"
  },
  {
    "path": "01-basics/05-loops/README.md",
    "content": "# Working with loops\n\nThis chapter covers working with loops in Go. Loops are used to repeat statements in your code.\n\n## Introduction\n\nThis chapter will cover:\n\n- Loop statements with `for`.\n- Device conditions on when to break a loop.\n- Apply `range` to iterate over an array.\n- Control the loop with `continue` and `break`.\n\n## The case for looping statements\n\nYou are likely to want to repeat a set of instructions. For example, you might have a list of orders where you need to process each order. Or you have a file that you need to read line by line or there might be some other calculation. Regardless of your situation, you are likely to need a looping construct, so what are your options in Go?\n\nYou are using the `for` loop. There are three major ways you can use it:\n\n- **increment steps**. With the help of a variable, you define a start point, a condition when to stop and an incrementation step. This is your \"classic\" for-loop. Here's what it looks like:\n\n   ```go\n   for i := 0; i < 10; i++ {\n     // run these statements\n   } \n   ```\n\n- **while**. In many programming languages you have a `while` keyword. Go doesn't have that, but what you can do is use the for-loop similarly. You omit the initialization step and increment step and get this code:\n\n  ```go\n  for <condition> {\n    // run these statements\n  }\n  ```\n\n- **for each**. lastly, you have the `for-each` like construct that operates on an array-like sequence. It uses the `range` keyword to function:\n\n   ```go\n   for i,s := range array {\n     // run these statements\n   }\n   ```\n\n## The `for` loop\n\nThe conventional for-loop has three different parts:\n\n- **initialization**, here you want to create a variable and assign it a starter value like so:\n\n   ```go\n   for i:= 0;\n   ```\n\n   Note the use of `;`, you usually don's use semicolons, but for this construct, you need it.\n\n- **condition**. The next step is evaluating whether you should continue incrementing or not. You define a Boolean expression here, that if `true`, continues to loop:\n\n   ```go\n   for i := 0; i< 10     \n   ```\n\n   `i < 10`, as long as a value is between 0 and 10 (becomes 10, then loop breaks), then it returns true, and the loop continues.\n\n- **increment**, in this step, the loop variable `i` is updated, updating it by 1 is common but you can add any increment size, negative or positive.\n\n   ```go\n   for i := 0; i< 10; i++ {\n\n   }\n   ```\n\n   Here, `i` is updated by 1. This loop will run ten times.\n\n## Repeat until the condition is met with `while`\n\nA simplified version of this loop can omit the initialization and increment steps. You are then left with the condition step only. This step tests whether a variable is `true` or `false` and the loop exits on false. Here's an example:\n\n```go\ni := 1\nfor i < 10 {\n  i++\n  // do something\n}\n```\n\nIn this case, we are declaring `i` outside of the loop. Within the loop, we need to change the value to something that will make the loop expression evaluate to false or it will loop forever.\n\nHere's another code, using the same idea, but this time we ask for input from the user:\n\n```go\nvar keepGoing = true\nanswer := \"\"\nfor keepGoing {\n  fmt.Println(\"Type command: \")\n  fmt.Scan(&answer)\n  if answer == \"quit\" {\n    keepGoing = false\n  }\n}\nfmt.Println(\"program exit\")\n```\n\nAn example run of the program could look like so:\n\n```bash\nType command: test\nType command: something\nType command: quit\nprogram exit\n```\n\n## Using for-each over a range\n\nFor this next loop construct, the idea is to operate over an array or known sequence. For each iteration you can get the index as well as the next item in the loop. Here's some example code:\n\n```go\narr := []string{\"arg1\", \"arg2\", \"arg3\"}\n for i, s := range arr {\n  fmt.Printf(\"index: %d, item: %s \\n\", i, s)\n }\n```\n\n`arr` is defined as an array and then the `range` construct is used to loop over the array. For each iteration, the current index is assigned to `i` and the array item is assigned to `s`. An output of the above code will look like so:\n\n```output\nindex: 0, item: arg1\nindex: 1, item: arg2\nindex: 2, item: arg3\n```\n\n## Controlling the loop with `continue` and `break`\n\nSo far, you've seen three ways you can use the `for` construct. There are also ways to control the loop. You can control the loop with the following keywords:\n\n- `break`, this will exit the loop construct\n\n   ```go\n   arr = []int{-1,2}\n   for i := 0; i< 2; i++ {\n     fmt.Println(arr[i])\n     if arr[i] < 0 {\n       break;\n     }\n   }     \n   ```\n\n   The output will be:\n\n   ```output\n   -1\n   ```\n\n   it won't output `2` as the loop exits after the first iteration.\n\n- `continue`, this will move on to the next iteration. If `break` exits the loop, `continue` skips the current iteration:\n\n   ```go\n   arr = []int{-1,2,-1, 3}\n   for i := 0; i< 4; i++ {\n     if arr[i] < 0 {\n       break;\n     }\n     fmt.Println(arr[i])\n   } \n   ```\n\n   The output will be:\n\n   ```output\n   2\n   3\n   ```\n\n## Assignment - create a command line loop\n\nWhen creating console apps, you often want to read user input. The user input could be data used in the program or it can be the user typing a command to do something like \"save\", \"print\", \"backup\" etc. We will build a program for the latter case.\n\n1. Create a file *main.go* and give it the following content:\n\n   ```go\n   package main\n\n   import \"fmt\"\n\n   func main() {\n   \n   }\n   ```\n\n1. Add the following code to the `main()` method:\n\n   ```go\n   var keepGoing = true\n   answer := \"\"\n   for keepGoing {\n     fmt.Println(\"Type command: \")\n     fmt.Scan(&answer)\n     if answer == \"quit\" {\n       keepGoing = false\n     }\n   }\n   fmt.Println(\"program exit\")\n   ```\n\n1. Run the code by typing `go run main.go`:\n\n   ```bash\n   go run main.go\n   ```\n\n   You should see an output like so:\n\n   ```output\n   Type command: command\n   Type command: quit\n   program exit \n   ```\n\n## 🚀 Challenge\n\n- Add a command \"print\" that ends up outputting \"printing file\".\n\n- See if you can use a `break` instead of the variable `keepGoing` to break the loop when the user types\"quit\".\n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n  var keepGoing = true\n   answer := \"\"\n   for keepGoing {\n     fmt.Println(\"Type command: \")\n     fmt.Scan(&answer)\n     if answer == \"quit\" {\n       keepGoing = false\n     }\n   }\n   fmt.Println(\"program exit\")\n}\n```\n"
  },
  {
    "path": "01-basics/05-loops/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t//\n\t// for i := 1; i < 10; i++ {\n\t// \tfmt.Println(i)\n\t// }\n\n\t// while\n\tvar keepGoing = true\n\tanswer := \"\"\n\tfor keepGoing {\n\t\tfmt.Println(\"Type command: \")\n\t\tfmt.Scan(&answer)\n\t\tif answer == \"quit\" {\n\t\t\tkeepGoing = false\n\t\t}\n\t}\n\tfmt.Println(\"program exit\")\n\n\t// for each\n\tarr := []string{\"arg1\", \"arg2\", \"arg3\"}\n\tfor i, s := range arr {\n\t\tfmt.Printf(\"index: %d, item: %s \\n\", i, s)\n\t}\n}\n"
  },
  {
    "path": "01-basics/06-user-input/README.md",
    "content": "# Reading user input\n\nYou will learn how to read user input, both a simpler technique and a more advanced one using formatters.\n\n## Introduction\n\nThis chapter will cover:\n\n- The `Scan()` method to read user input.\n- Reading one input.\n- Reading multiple inputs.\n- Working with formattters.\n\n## User input\n\nIt's an important thing to be able to read user input from the console. It gives the user a chance to interact with the program. Things to consider are how you are asking the user to input, is it one word, several inputs. Will the user separate input by space or newline? Regardless of what approach you go with, try to communicate the chosen approach to the user.\n\n## Managing user input with `fmt`\n\nSo far, you've seen how the `fmt` package can be used to print to the console. It can also be used to read user input.\n\nThe `fmt` library has a built-in `Scan()` method that we will use to capture the user input.\n\n## Reading one input\n\nYou might start out wanting to read one input from the user. That's what the `Scan()` method does by default.\n\nHere's some code showing how to collect user input:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n    var response string\n    fmt.Scan(&response)\n    fmt.Println(\"User typed: \", response)\n}\n```\n\nNote how you send in the string `response` as a reference, using the `&` operator. It's done this way as the `Scan()` method will modify the variable you send in.\n\nWhen you run this code, you will see the below output:\n\n```output\nhello\nUser typed: hello\n```\n\n## Reading multiple inputs\n\nYou can provide several arguments to the `Scan()` method. By providing several arguments, you can collect more than one user input and separate each input, in the `Scan()` function, with a comma. Here's how to apply this technique:\n\n```go\nvar a1, a2 string\n// multiple input\nfmt.Scan(&a1, &a2)\n\n// formatted string to print out the user input\nstr := fmt.Sprintf(\"a1: %s a2: %s\", a1, a2)\n```\n\nNote how `a1` and `a2` is sent into `Scan()` and they are comma-separated. So how will those codes run?\n\nWhen you run this code, there are two ways for the user to input. The user can either separate the values by space like so:\n\n```output\nhi you\na1: hi a2: you\n```\n\nor by newline:\n\n```output\nhi \nyou\na1: hi a2: you\n```\n\n## `Scanf()`, scan the input with formatters\n\nSo far, you've seen how you can collect input with spaces and endlines as separators. You can also be specific in how you collect input. Imagine that the user wants to type in an invoice number like so \"INV200\" or \"INV114\" and what you are interested in is the number part, or you are interested in the prefix as well?\n\nThe answer to solving this is in the `Scanf()` function. It takes formatters. With formatters, you're able to pick the part of the user input you are interested in and place that into the variable you want.\n\nIn the above-mentioned case, you can construct code looking like so:\n\n```go\nvar prefix string\nvar no int\n// inv110\nfmt.Scanf(\"%3s%d\", &prefix, &no)\nfmt.Printf(\"prefix: %s, invoice no: %d\", prefix, no)\n```\n\nThe interesting part lies in the first argument of `Scanf()`, namely `3s%d`. What this means is, take the first 3 characters, `%3s` and interpret them as a string. Then interpret and place the remaining as a number, `%d`.\n\nRunning this program, you will get an output like so:\n\n```output\ninv200\nprefix: inv, invoice no: 200\n```\n\n\"inv\" is placed in `prefix` and 200 in `no` variable.\n\n## Learn more\n\nTo learn more about this area, check out this link <https://pkg.go.dev/fmt#Scanf>\n\n## Assignment - read user input\n\nIn this assignment, you will read user input for a card game. The objective is to capture the names of the players.\n\n1. Create a file *main.go* with the following content:\n\n   ```go\n   package main\n\n   import \"fmt\"\n\n   func main() {\n\n   }\n   ```\n\n1. Add the following code to the `main()` method:\n\n   ```go\n   fmt.Println(\"Enter player names (separated by space or newline):\")\n   var player1, player2 string\n   fmt.Scan(&player1, &player2)\n   fmt.Println(\"Players are: \", player1, player2)\n   ```\n\n1. Run the program using `go run main.go`:\n\n   ```bash\n   go run main.go\n   ```\n\n   You should see the following output:\n\n   ```output\n   Enter player names (separated by space or newline):\n   Alice Bob\n   Players are:  Alice Bob\n   ```\n\n## 🚀 Challenge\n\nTry modifying the program so it takes several players first and then ensures all players get a name. Here's an example output of such a program:\n\n```output\nEnter number of players: \n3\nEnter Player 1 name: \nAlice\nEnter Player 2 name:\nBob\nEnter Player 3 name:\nJean\nPlayers are: Alice Bob Jean\n```  \n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"Enter player names (separated by space):\")\n var player1, player2 string\n fmt.Scan(&player1, &player2)\n fmt.Println(\"Players are: \", player1, player2)\n}\n```\n"
  },
  {
    "path": "01-basics/06-user-input/go.mod",
    "content": "module input\n\ngo 1.16\n"
  },
  {
    "path": "01-basics/06-user-input/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc Advanced() {\n\tvar no int\n\tnames := \"\"\n\tvar name string\n\tfmt.Println(\"Enter number of players:\")\n\tfmt.Scan(&no)\n\n\tfor i := 0; i < no; i++ {\n\t\tfmt.Printf(\"Enter Player %d name:\", i+1)\n\t\tfmt.Scan(&name)\n\t\tnames += name + \" \"\n\t}\n\tfmt.Println(\"Players are:\", names)\n}\n\nfunc main() {\n\t// var response string\n\tfmt.Println(\"hi\")\n\n\t// // one input\n\t// fmt.Scan(&response)\n\t// fmt.Println(\"User typed \", response)\n\n\t// var a1, a2 string\n\n\t// // multiple input\n\t// fmt.Scan(&a1, &a2)\n\n\t// // formatted string\n\t// str := fmt.Sprintf(\"a1: %s a2: %s\", a1, a2)\n\t// fmt.Println(str)\n\n\t// var prefix string\n\t// var no int\n\t// // in110\n\t// fmt.Scanf(\"%3s%d\", &prefix, &no)\n\t// fmt.Printf(\"prefix: %s, invoice no: %d\", prefix, no)\n\t// fmt.Println(\"Enter player names (separated by space):\")\n\t// var player1, player2 string\n\t// fmt.Scan(&player1, &player2)\n\t// fmt.Println(\"Players are: \", player1, player2)\n\tAdvanced()\n}\n"
  },
  {
    "path": "01-basics/07-functions/README.md",
    "content": "# Using functions\n\nIn this chapter, we will discuss how you can define and use functions. Functions are great when you have the same type of code used in many places. By using functions, you thereby reduce repetition.\n\n## Introduction\n\nThis chapter will cover:\n\n- What a function is and why use it.\n- How to define and call a function.\n- Returning multiple values.\n\n## Why functions\n\nAs soon as you have a set of statements you repeat in many places, it's a good use case for creating a function. Typical things you put in functions are logging to a file, performing a calculation or talking to a data source.\n\n## Your first function `main()`\n\nSo far, you've seen the function `main()`, define like so:\n\n```go\nfunc main(){\n}\n```\n\nThere's only one such function, it's called an entry point and represents the start of the program. You can however define other functions.\n\n## The anatomy of a function\n\nA function consists of various parts. By incorporating all these parts, you ensure you have a reusable piece of code you can use in many places.\n\nHere are the parts you need to care about:\n\n- `func`, the keyword `func`.\n- **parameters**, 0 to many parameters\n- **a function body**, i.e. statements that say what the function does.\n- **a return construct**, if the function returns something.\n\nHere's an example:\n\n```go\nfunc add(first int, second int) int {\n  return first + second\n}\n```\n\nIn the preceding code, the function is named `add()`. It has the parameters `first` and `second`. The function body, what the function does, consists of this code:\n\n```go\nreturn first + second\n```\n\n## Adding a return type\n\nTo add a return type, we add that after the function parenthesis in form of a type. Here's an example:\n\n```go\nadd(firstNumber int, secondNumber int) int {\n ...\n}\n```\n\nBecause we've added a return type of `int`, our function must return something. A way to return a value is by using the keyword `return`, like so:\n\n```go\nadd(firstNumber int, secondNumber int) int {\n  return firstNumber + secondNumber \n}\n```\n\n### Named return\n\nWe can also name the return parameter like so:\n\n```go\nadd(firstNumber int, secondNumber int) (sum int) {\n  sum = firstNumber + secondNumber \n  return\n}\n```\n\n- Note how `sum` is part of function prototype declaration `(sum int)` and then assigned a value `sum = firstNumber + secondNumber`.\n\n- There's also a `return` on its own row, this code will compile as there's a notion of a return variable.\n\n## Multiple returns\n\nIt's possible to return more than one value.\n\nJust like you returned a named parameter via `(sum int)`, you can comma separate like so `(sum int, product int)`. When returning multiple values, you can type like so:\n\n```go\nsum = first + second\nproduct = first * second\nreturn\n```\n\nBoth `sum` and `product` are assigned values and you have a closing `return`.\n\nPutting it altogether you get a function that looks like so:\n\n```go\nfunc calc(first int, second int) (sum int, product int) {\n  sum = first + second\n  product = first * second\n  return\n}\n```\n\nTo call the function, you type like so:\n\n```go\nsum, product := calc(1, 2)\nfmt.Println(sum)\nfmt.Println(product)\n```\n\nNote how you assign the two returned values to variables `sum` and `product`.\n\n## Assignment - adding a function to a program\n\n1. Create a file *main.go* and give it the following content:\n\n    ```go\n    package main\n    \n    import \"fmt\"\n    \n    func main() {\n    \n    }\n    ```\n\n1. Add a function `log()`, that we can use to print messages.\n\n   Added to the program, your code should now look like so:\n\n    ```go\n    package main\n    \n    import \"fmt\"\n    \n    func log() {\n      fmt.Println(\"message\")\n    }\n    \n    func main() {\n      log()\n    }\n    ```\n\nAt this point, the `log()` function isn't very flexible, it prints \"message\" every time it's invoked.\n\nTo make the `log()` function more flexible, lets add a parameter.\n\n### Adding a parameter\n\nA parameter needs a data type, in this case, we will make it of type `string`.\n\n1. Add the parameter within the parenthesis `()`, like so:\n\n    ```go\n    func log(message string) {\n      fmt.Println(message)\n    }\n    \n    // to use\n    log(\"hi\")\n    log(\"there\")\n    ```\n\nNote how the `log()` function takes the parameter `message` that is of type string. Our code is more flexible.\n\n## Solution\n\n```go\npackage main\n    \nimport \"fmt\"\n\nfunc log(message string) {\n  fmt.Println(message)\n}\n\nfunc main() {\n  log(\"hi\")\n  log(\"there\")\n}\n```\n"
  },
  {
    "path": "01-basics/07-functions/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n)\n\nfunc add(first int, second int) int {\n\treturn first + second\n}\n\nfunc add2(first int, second int) (sum int) {\n\tsum = first + second\n\treturn\n}\n\nfunc add3(first string, second string) int {\n\tint1, _ := strconv.Atoi(first)\n\tint2, _ := strconv.Atoi(second)\n\treturn int1 + int2\n}\n\nfunc calc(first int, second int) (sum int, product int) {\n\tsum = first + second\n\tproduct = first * second\n\treturn\n}\n\nfunc changeName(name *string) {\n\t*name = \"sara\"\n}\n\nfunc main() {\n\tvar name = \"chris\"\n\tsum := add(1, 2)\n\tfmt.Println(sum)\n\tfmt.Println(add2(2, 2))\n\tfmt.Println(add3(os.Args[1], os.Args[2]))\n\tsum, mult := calc(1, 2)\n\tfmt.Println(sum, mult)\n\tfmt.Println(name)\n\tchangeName(&name)\n\tfmt.Println(name)\n}\n"
  },
  {
    "path": "01-basics/07-functions/test.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n)\n\nfunc main() {\n\tno, err := strconv.Atoi(os.Args[1])\n\tfmt.Println(no)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\tfmt.Println(\"Couldn't convert: \" + os.Args[1])\n\n\t} else {\n\t\tfmt.Println(no)\n\t}\n}\n"
  },
  {
    "path": "01-basics/08-error-handling/README.md",
    "content": "# Handling errors\n\nIn this chapter, we will cover error handling.\n\n## Introduction\n\nThis chapter will cover:\n\n- Causing and handling errors with `panic` and `recover`.\n- Use the error pattern to use a more idiomatic approach to managing errors.\n\n## Errors\n\nOur apps aren't perfect, they will throw errors. Either they throw errors because of code we wrote or because of code written in a package we are using. Sometimes, that's even what the code is supposed to do when we feed it bad input.\n\nRegardless, our users expect us to handle these errors. Also, for our own sake, we need to log these errors in such a way that we can fix those errors if they are unexpected.\n\nThere are two major ways to handle errors in Go:\n\n- **panic/recover**. `panic` and `recover` are language constructs. If you know another programming language, they function like throw and catch. What does it mean though? It means there's an error, with an error message and stack trace that we can catch and recover from or let it crash the program.\n- **error pattern**. This is referred to as the idiomatic Go way of doing things. The idea is to return a value and an error object from a function call. If an error occurred, it contains an error object or `nil`, if no error.\n\n## Crash the program with `panic()`\n\nLet's take this function `Divide()`:\n\n```go\nfunc Divide(nominator int, divider int) float32 {\n  if divider == 0 {\n    panic(\"can't divide by 0\")\n  }\n  return float32(nominator) / float32(divider)\n}\n```\n\nIt has an `if` check. If `divider` is `0` then it calls `panic()`. So what happens then? You see something like:\n\n```output\npanic: can't divide by 0\n\ngoroutine 1 [running]:\nmain.Divide(...)\n        /<path>/panic.go:20\nmain.main()\n        /<path>/panic.go:33 +0x96\nexit status 2\n```\n\nAt the top is the error string you sent to `panic()`, the string \"can't divide by 0\". Then you have the stack trace, entries that indicate where the error started. Read it from the bottom, the error started on line 33, then you have line 20, which is this row:\n\n```go\npanic(\"can't divide by 0\")\n```\n\nOk, so we have a way to protect ourselves from input values that we don't want. But crashing the program, is that necessary? In some cases, it is, in some cases, it isn't. For the latter cases, we have `recover()`.\n\n### Capture the error with `recover()`\n\nUsing `recover()` is about capturing an error so our program can continue. We need to learn about a concept before proceeding. That concept is `defer`. `defer` is a language construct that delays the execution of a function until the nearby function returns. Here's an example:\n\n```go\ndefer fmt.Println(\"second\")\nfmt.Println(\"first\")\n```\n\nRunning this program, you should see:\n\n```go\nfirst\nsecond\n```\n\n> See `defer` as the last thing that happens.\n\nHow is this useful in the context of capturing an error? Capturing errors, if you want to capture it, is something you want to do as the last thing that happens. Take our `Divide()` function again:\n\n```go\nfunc Divide(nominator int, divider int) float32 {\n  defer errorHandler()\n  if divider == 0 {\n    panic(\"can't divide by 0\")\n  }\n  return float32(nominator) / float32(divider)\n}\n```\n\nNote how it now has a line in it that says `defer errorHandler()`. It will be run the last thing that happens. Depending on the value of `divider`, it will either call `panic()` or call the `return` statement as the last thing.\n\nOk, so what does `errorHandler()` look like?\n\n```go\nfunc errorHandler() {\n  if r := recover(); r != nil {\n    fmt.Println(\"Recovered \", r)\n  }\n}\n```\n\nIn `errorHandler()`, we invoke `recover()` and assign it to variable `r` and then we test it for `nil`. If it's NOT `nil` then we have an error and we print it out. If it is `nil` then the user notices nothing.\n\n## Improve the error handling\n\nThere are steps we can take to improve the error handling. So far, we're printing back an error message. Imagine if someone read this error from a log file, would they be able to understand where things went wrong and fix the input data or the code itself?\n\nThere are a couple of things we can do:\n\n- **Inspect the error**. Our error didn't only come with an error message, there's a stack trace as well.\n- **Logging**. If we want someone to work with these errors, we should look at logging them to a file.\n\n### Inspect the error with `runtime/debug`\n\nThere's a library `runtime/debug`. With this library, you can find out more about an error when it's thrown, information like stack trace, where the error originated. There's a function `Stack()` that produces the stack trace. Here's how to use it:\n\n```go\ndebug.Stack()\n```\n\n### Log the error with `log`\n\nWhile `runtime/debug` can produce a stack trace, what would be useful is logging all this error information to a file. To log to a file, use the `os` and `log` package like so:\n\n```go\nf, err := os.OpenFile(\"logs\", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)\n if err != nil {\n  log.Println(err)\n }\n log.SetOutput(f)\n```\n\n## Use the error pattern with the `errors` package\n\nOther languages tend to use Exceptions to signal that something is wrong.\n\nGo has a different and idiomatic approach. It wants you to create errors as return values to a function, next to the actual value being returned. You are then expected to inspect a function and see if it returns an error.\n\nThere's an `errors` package that can help us with the above approach.\n\n### Define an error\n\nTo define an error, we call the `New()` function with a string describing the error, here's an example:\n\n```go\nvar NoTooSmall = errors.New(\"the number is too small\")\n```\n\nNext, let's look at how to add the error to a function.\n\n### Return an error\n\nLet's start with function that uses a `panic()` as error handling:\n\n```go\nfunc ReturnPositive(no int) int {\n  if no > 0 {\n    return no\n  } else {\n    panic(\"No too small\")\n  }\n}\n```\n\nWe can improve this function, by ensuring it always returns the result and an error, like so:\n\n```go\nfunc ReturnPositive(no int) (int, error) {\n  if no > 0 {\n    return no, nil\n  } else {\n    return 0, NoTooSmall\n  }\n}\n```\n\nNote in the `if` clause that it returns `no` and `nil` when everything is fine. For the `else`, it returns a bogus value and our error `NoTooSmall`.\n\n### Inspect the result\n\nLet's see how we would call the `ReturnPositive()` function and use this new pattern we established:\n\n```go\nno, err := ReturnPositive(-2)\nif err != nil {\n  fmt.Println(\"error: \", err)\n} else {\n  fmt.Println(\"value:\", no)\n}\n```\n\nWhat you are seeing above is how we use an `if` clause to check for errors, if so, print out. On the `else`, we have our actual value.\n\n## Assignment I - add error handling\n\nIn this exercise, we'll add error handling to our program.\n\n1. Create a file *panic.go* and give it the following content:\n\n   ```go\n   package main\n\n   import (\n     \"fmt\"\n   )\n    \n    // func errorHandler() {\n    // if r := recover(); r != nil {\n    //  fmt.Println(\"Recovered \", r)\n    // }\n    // }\n    \n    func Divide(nominator int, divider int) float32 {\n     // defer errorHandler()\n     if divider == 0 {\n      panic(\"can't divide by 0\")\n     }\n     return float32(nominator) / float32(divider)\n    }\n    \n    func main() {\n     no := Divide(10, 0)\n     fmt.Println(no)\n     no = Divide(10, 1)\n     fmt.Println(no)\n    }\n   ```\n\n1. Run the program `go run panic.go`\n\n   ```bash\n   go run panic.go\n   ```\n\n   You should see output similar to:\n\n   ```output\n   panic: can't divide by 0\n\n    goroutine 1 [running]:\n    main.Divide(...)\n            /<path>/panic.go:20\n    main.main()\n            /path/panic.go:33 +0x96\n    exit status 2\n   ```\n\n   Note how these two statements was never run as the program crashed:\n\n   ```go\n   no = Divide(10, 1)\n   fmt.Println(no)\n   ```\n\n1. Uncomment the commented out part and run the app again.\n\n   You should now see the following output:\n\n   ```output\n   Recovered  can't divide by 0\n   0\n   10\n   ```\n\nCongrats, you've managed to implement error handling with `panic()` and `recover()`.\n\n## Solution I\n\n```go\npackage main\n\nimport (\n   \"fmt\"\n)\n   \nfunc errorHandler() {\n   if r := recover(); r != nil {\n      fmt.Println(\"Recovered \", r)\n   }\n}\n   \nfunc Divide(nominator int, divider int) float32 {\n  defer errorHandler()\n  if divider == 0 {\n    panic(\"can't divide by 0\")\n  }\n  return float32(nominator) / float32(divider)\n}\n   \nfunc main() {\n  no := Divide(10, 0)\n  fmt.Println(no)\n  no = Divide(10, 1)\n  fmt.Println(no)\n}\n```\n\n## Assignment II - improve error logging\n\nLet's improve our *panic.go* file by adding error logging:\n\n1. Locate the `errorHandler()` and change it to the following:\n\n   ```go\n   func errorHandler() {\n     if r := recover(); r != nil {\n       log.Println(r, string(debug.Stack()))\n     }\n   }\n   ```\n\n1. Ensure that *panic.go* looks like so:\n\n   ```go\n    package main\n\n    import (\n     \"fmt\"\n     \"log\"\n     \"os\"\n     \"runtime/debug\"\n    )\n    \n    func errorHandler() {\n     if r := recover(); r != nil {\n      log.Println(r, string(debug.Stack()))\n     }\n    }\n    \n    func Divide(nominator int, divider int) float32 {\n     defer errorHandler()\n     if divider == 0 {\n      panic(\"can't divide by 0\")\n     }\n     return float32(nominator) / float32(divider)\n    }\n    \n    func main() {\n     f, err := os.OpenFile(\"logs\", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)\n     if err != nil {\n      log.Println(err)\n     }\n     log.SetOutput(f)\n    \n     log.Println(\"starting program\")\n     no := Divide(10, 0)\n     fmt.Println(no)\n    \n     no = Divide(10, 1)\n     fmt.Println(no)\n     f.Close()\n    }\n   ```\n\n1. Run this program:\n\n   ```go\n   go run panic.go\n   ```\n\n   You should see this output:\n\n   ```output\n   0\n   10\n   ```\n\n   It was able to run all statements without being affected by the error that was thrown.\n\n1. Inspect the *logs* file that was just created, it should have content like the below:\n\n   ```output\n     2022/03/11 15:03:59 starting program\n\n    2022/03/11 15:03:59 can't divide by 0 goroutine 1 [running]:\n    runtime/debug.Stack(0xc000111d30, 0x10b1b40, 0x10eae78)\n     /usr/local/Cellar/go/1.16/libexec/src/runtime/debug/stack.go:24 +0x9f\n    main.errorHandler()\n     /<path>/panic.go:14 +0x5b\n    panic(0x10b1b40, 0x10eae78)\n     /usr/local/Cellar/go/1.16/libexec/src/runtime/panic.go:965 +0x1b9\n    main.Divide(0xa, 0x0, 0x0)\n     /<path>/panic.go:21 +0xa5\n    main.main()\n     /<path>/panic.go:34 +0x115\n   ```\n\n## Solution II\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"log\"\n  \"os\"\n  \"runtime/debug\"\n)\n\nfunc errorHandler() {\n  if r := recover(); r != nil {\n    log.Println(r, string(debug.Stack()))\n  }\n}\n\nfunc Divide(nominator int, divider int) float32 {\n  defer errorHandler()\n  if divider == 0 {\n    panic(\"can't divide by 0\")\n  }\n  return float32(nominator) / float32(divider)\n}\n\nfunc main() {\n  f, err := os.OpenFile(\"logs\", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)\n  if err != nil {\n    log.Println(err)\n  }\n  log.SetOutput(f)\n\n  log.Println(\"starting program\")\n  no := Divide(10, 0)\n  fmt.Println(no)\n\n  no = Divide(10, 1)\n  fmt.Println(no)\n  f.Close()\n}\n```\n"
  },
  {
    "path": "01-basics/08-error-handling/logs",
    "content": "2022/03/11 15:03:59 starting program\n2022/03/11 15:03:59 can't divide by 0 goroutine 1 [running]:\nruntime/debug.Stack(0xc000111d30, 0x10b1b40, 0x10eae78)\n\t/usr/local/Cellar/go/1.16/libexec/src/runtime/debug/stack.go:24 +0x9f\nmain.errorHandler()\n\t/Users/chnoring/Documents/dev/projects/go-projects/book/01-basics/08-error-handling/panic.go:14 +0x5b\npanic(0x10b1b40, 0x10eae78)\n\t/usr/local/Cellar/go/1.16/libexec/src/runtime/panic.go:965 +0x1b9\nmain.Divide(0xa, 0x0, 0x0)\n\t/Users/chnoring/Documents/dev/projects/go-projects/book/01-basics/08-error-handling/panic.go:21 +0xa5\nmain.main()\n\t/Users/chnoring/Documents/dev/projects/go-projects/book/01-basics/08-error-handling/panic.go:34 +0x115\n\n"
  },
  {
    "path": "01-basics/08-error-handling/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar NoTooSmall = errors.New(\"the number is too small\")\n\nfunc ReturnPositive(no int) (int, error) {\n\tif no > 0 {\n\t\treturn no, nil\n\t} else {\n\t\treturn 0, NoTooSmall\n\t}\n\n}\n\nfunc main() {\n\tfmt.Println(\"hi\")\n\tno, err := ReturnPositive(-2)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t} else {\n\t\tfmt.Println(no)\n\t}\n\n}\n"
  },
  {
    "path": "01-basics/08-error-handling/panic.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"runtime/debug\"\n)\n\nfunc errorHandler() {\n\tif r := recover(); r != nil {\n\t\t// fmt.Println(\"Recovered \", r)\n\t\t// fmt.Println(string(debug.Stack()))\n\t\tlog.Println(r, string(debug.Stack()))\n\t}\n}\n\nfunc Divide(nominator int, divider int) float32 {\n\tdefer errorHandler()\n\tif divider == 0 {\n\t\tpanic(\"can't divide by 0\")\n\t}\n\treturn float32(nominator) / float32(divider)\n}\n\nfunc main() {\n\tf, err := os.OpenFile(\"logs\", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)\n\tif err != nil {\n\t\tlog.Println(err)\n\t}\n\tlog.SetOutput(f)\n\n\tlog.Println(\"starting program\")\n\tno := Divide(10, 0)\n\tfmt.Println(no)\n\n\tno = Divide(10, 1)\n\tfmt.Println(no)\n\tf.Close()\n}\n"
  },
  {
    "path": "02-data-types/01-arrays/README.md",
    "content": "# Arrays and slices\n\nIn this chapter, we will cover arrays and slices.\n\n## Introduction\n\nThis chapter will cover:\n\n- Declaring and inspecting an array.\n- Accessing elements in the array.\n- Working with slices.\n\n## Arrays\n\nAn array is a group of elements that are connected. You want to use an array when you have a group of something, like many orders, cars, and rows in a file.\n\nThe idea with an Array is to collect all that data in one structure. You also want to be able to iterate over it and carry out an operation on it as a group.\n\n## Declare an array\n\nTo declare an array, you need to specify the following properties:\n\n- **capacity**, how many elements it holds.\n- **type**, what type of elements it holds.\n- **array content**, you can assign it elements at creation or do so later.\n\nHere's the syntax:\n\n```go\n[<capacity>]<type>{...element}\n```\n\nIt starts with the square brackets, `[]`. Within the square brackets, you set the capacity, and how many elements it can hold.\n\nand here's a more real example:\n\n```go\ncities := [5]string{\"NY\", \"LA\"}\n```\n\nIn the preceding code, an array of strings is declared. It has a capacity for 5 elements and two of the places are filled with \"NY\" and \"LA\". Note also because we set the capacity to 5 and the number of elements it's assigned is 2, there are 3 spaces free.\n\n### Capacity by inference\n\nYou don't have to set capacity to an explicit number, you can set it to `...`, in which case the capacity will be set to the number of elements you assign to it, like so:\n\n```go\nids := [...]int{1, 2, 3, 4}\n```\n\nThe preceding code has 4 elements, and that's also its capacity.\n\n## Accessing elements\n\nThe way to access an element is by using its index. The index is 0-based, meaning the first index is 0 and its last is the length -1.\n\n```go\nids := [...]int{1, 2, 3, 4}\nids[0] // 1\nids[3] // 4\n```\n\n## Length and capacity\n\nImagine we have the following array declared:\n\n```go\ncities := [5]string{\"NY\", \"LA\"}\n```\n\n- **length**. The length is defined as the number of elements in the array. You can use the `len()` method to find this out:\n\n   ```go\n   len(cities) // 2\n   ```\n\n- **capacity**. The capacity is how many elements the array can hold. `cap()` is the method you use to find the capacity:\n\n   ```go\n   cap(cities) // 5\n   ```\n\n## Slices\n\nA slice is a part of an array. A slice is created when the slice operator is being used. Here's the syntax for the slice operator:\n\n```go\ns[i:p]\n```\n\n- `s`, the array\n- `i`, the first index of the array to take elements from\n- `p`, The variable p corresponds to the last element in the underlying array that can be used in the new slice. I.e. cut right before this index.\n\n```go\nitems := [5]int{1,2,3,4,5}\npart = items[1:3] // 2,3\n```\n\n### Adding elements\n\nA slice differs from an array, you can add items to it. The `append()` method lets you add elements to it. The syntax for `append()` is as follows:\n\n```go\nappend(slice, element)\n```\n\nHere's how you can append to a slice:\n\n```go\nvar numbers []int\nnumbers = append(numbers, 1)\nnumbers = append(numbers, 2) // 1,2\n```\n\n### Removing elements\n\nRemove an element by constructing a new slice.\n\n```go\nletters := []string{\"A\", \"B\", \"C\", \"D\", \"E\"}\nremove := 2 // remove index\n// 0 - remove index, remove +1 to end   \nletters = append(letters[:remove], letters[remove+1:]...)\n// [A B D E]\n```\n\n### Create a slice with `make()`\n\nYou can use the `make()` method to create a slice. Here's how:\n\n```go\nslice := make([]int, 5) // creates a slice with length 5 and capacity 5\n```\n\nYou can set these to different values:\n\n```go\nslice2 := make([]int, 2, 5)\nfmt.Println(slice2)\nfmt.Println(len(slice2))\nfmt.Println(cap(slice2))\n```\n\nHere, the slice has a length of 2, and a capacity of 5.\n\n### Copy elements\n\n```go\narr := [3]int{1, 2, 3}\ndest := make([]int, 5)\ncopy(dest, arr[0:2]) // copies slice {1,2} into dest\nfmt.Println(dest) // [1 2 0 0 0]\n```\n\n## Assignment - store log entries\n\nCreate an array meant for log entries. It can be used in the following way:\n\n```console\ncommand> new\nhere's a new entry\ncommand> new\nhere's another entry\ncommand> list\nhere's a new entry\nhere's another entry\ncommand> quit\nbye\n```\n\nSo, you need to have a way to store multiple strings and list them when asked for.\n\nHere's some starter code to deal with console input:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n)\n\nfunc main() {\n // create array\n\n var response string\n for {\n  fmt.Print(\"command> \")\n  fmt.Scan(&response)\n  if response == \"quit\" {\n   break\n  } else if response == \"new\" {\n   fmt.Print(\"Entry:\")\n   fmt.Scan(&response)\n   // save entry to list\n   fmt.Println(\"Saving entry\")\n  } else if response == \"list\" {\n   // list entries\n   fmt.Println(\"Listing entries\")\n  } else {\n   fmt.Println(\"Unknown command\", response)\n  }\n\n }\n fmt.Println(\"bye\")\n}\n```\n\nAdd your own code where the comments are\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n)\n\nfunc main() {\n // create array\n arr := make([]string, 0)\n\n var response string\n for {\n  fmt.Print(\"command> \")\n  fmt.Scan(&response)\n  if response == \"quit\" {\n   break\n  } else if response == \"new\" {\n   fmt.Print(\"Entry:\")\n   fmt.Scan(&response)\n\n   // save entry to list\n   arr = append(arr, response)   \n   fmt.Println(\"Saving entry\")\n  } else if response == \"list\" {\n   // list entries\n   fmt.Println(\"Listing entries\")\n   for i := 0; i < len(arr); i++ {\n    fmt.Println(arr[i])\n   }\n  } else {\n   fmt.Println(\"Unknown command\", response)\n  }\n\n }\n fmt.Println(\"bye\")\n}\n```\n"
  },
  {
    "path": "02-data-types/01-arrays/assignment.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// create array\n\tarr := make([]string, 0)\n\n\tvar response string\n\tfor {\n\t\tfmt.Print(\"command> \")\n\t\tfmt.Scan(&response)\n\t\tif response == \"quit\" {\n\t\t\tbreak\n\t\t} else if response == \"new\" {\n\t\t\tfmt.Print(\"Entry:\")\n\t\t\tfmt.Scan(&response)\n\t\t\tarr = append(arr, response)\n\t\t\t// save entry to list\n\t\t\tfmt.Println(\"Saving entry\")\n\t\t} else if response == \"list\" {\n\t\t\t// list entries\n\t\t\tfmt.Println(\"Listing entries\")\n\t\t\tfor i := 0; i < len(arr); i++ {\n\t\t\t\tfmt.Println(arr[i])\n\t\t\t}\n\t\t} else {\n\t\t\tfmt.Println(\"Unknown command\", response)\n\t\t}\n\n\t}\n\tfmt.Println(\"bye\")\n}\n"
  },
  {
    "path": "02-data-types/01-arrays/main.go",
    "content": "// create an array\n// inferred length\n// get element\npackage main\n\nimport \"fmt\"\n\nvar array [3]int\n\nfunc main() {\n\tcities := [5]string{\"NY\", \"LA\"}\n\tids := [...]int{1, 2, 3, 4}\n\tarray[0] = 1\n\tvar matrix [2][2]int\n\tmatrix[0][0] = 1\n\n\tfmt.Println(array[0])\n\tfmt.Println(cities[0])\n\tfmt.Println(ids[3])\n\tfmt.Println(matrix[0][0])\n\n\titems := [5]int{1, 2, 3, 4, 5}\n\tpart := items[2:4] // 2,3\n\tfmt.Println(\"part\", part)\n\n\tvar numbers []int\n\tnumbers = append(numbers, 1)\n\tfmt.Println(\"num:\", numbers)\n\tnumbers = append(numbers, 2)\n\tfmt.Println(\"num:\", numbers)\n\n\tmonths := []string{\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"}\n\tquarter1 := months[0:3]\n\tquarter2 := months[3:6]\n\tquarter3 := months[6:9]\n\tquarter4 := months[9:12]\n\tfmt.Println(quarter1, len(quarter1), cap(quarter1))\n\tfmt.Println(quarter2, len(quarter2), cap(quarter2))\n\tfmt.Println(quarter3, len(quarter3), cap(quarter3))\n\tfmt.Println(quarter4, len(quarter4), cap(quarter4))\n\n}\n"
  },
  {
    "path": "02-data-types/01-arrays/slice.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tarr := [3]int{1, 2, 3}\n\tslice := make([]int, 5)\n\tfmt.Println(slice)\n\tfmt.Println(len(slice))\n\tfmt.Println(cap(slice))\n\n\tslice2 := make([]int, 2, 5)\n\tfmt.Println(slice2)\n\tfmt.Println(len(slice2))\n\tfmt.Println(cap(slice2))\n\n\tdest := make([]int, 5)\n\tcopy(dest, arr[0:2]) // copies slice into dest\n\tfmt.Println(dest)\n}\n"
  },
  {
    "path": "02-data-types/02-structs /README.md",
    "content": "# Structs\n\nIn this chapter, we will learn about structs. A struct is a complex data type capable of holding many fields. It can also be extended to hold behaviour.\n\n## Introduction\n\nThis chapter will cover:\n\n- Declaring and inspecting a struct.\n- Embedding a struct within another struct.\n- Adding implementations to structs.\n\n## Why structs\n\nLet's start with a simple scenario, you have an account balance. You might store it in a variable like so:\n\n```go\naccountBalance int32\n```\n\nNow that's great, but if you want to describe something more complex, like a bank account? A bank account consists of a variety of information like an ID, balance, account owner and so on. You could try representing each one of those properties as integers like so:\n\n```go\nvar accountBalance int32\nvar owner string\nvar id int\n```\n\nHowever, what happens if you need to operate on more than one bank account, I mean you could try to store it like so:\n\n```go\nvar accountBalance int32\nvar owner string\nvar id int\n\nvar accountBalance2 int32\nvar owner2 string\nvar id2 int\n```\n\nIt doesn't scale though, what you need is a more complex type, like a `struct` that's able to group all this information like so:\n\n```go\ntype Account struct {\n  accountBalance int32\n  owner string\n  id int\n}\n```\n\n## Defining a struct\n\nOk, so we understand why we need a struct, to gather related information, and we've seen one example so far `Account`. But let's try breaking the parts down and see how we go about defining a struct. Here's what the syntax looks like:\n\n```go\ntype <a name for the struct> struct {\n  ... fields\n}\n```\n\nLet's show another example but this time we create a struct for an address:\n\n```go\ntype Address struct {\n city   string\n street string\n postal string\n}\n```\n\n### Create a struct instance\n\nTo create an instance from a struct, we can use one of two approaches:\n\n- **define a variable**, and set the fields after the variable declaration:\n\n   ```go\n   var address Address\n   address.city = \"London\"\n   address.street = \"Buckingham palace\"\n   address.postal = \"SW1\"\n   ```\n\n- **define all at once**, we can set all the values in one go as well:\n\n   ```go\n   address2 := Address{\"New York\", \"Central park\", \"111\"}\n   ```\n\n## Embedding a struct\n\nWe can also embed a struct in another struct. Let's see we have our `Address` struct, an address is something that a higher level struct like `Person` can use. Here's how that can look:\n\n```go\ntype Person struct {\n name    string\n address Address\n}\n```\n\nIn this code, the `Person` struct has a field `address` of type `Address`.\n\nTo instantiate a struct, we can type like so:\n\n```go\nperson := Person{\n  name: \"chris\",\n  address: Address{\n   city: \"Stockholm\",\n  },\n }\n```\n\n### Relying on default naming\n\nNote how we created a field `address`, we can skip typing a few characters by defining it like so instead:\n\n```go\ntype Employee struct {\n Address\n company string\n}\n```\n\nNote how we omit the name for the field and just type `Address`, this means the field name and field type will be the same name. Creating an instance from it is similar:\n\n```go\nemployee := Employee{\n  Address: Address{\n   city: \"LA\",\n  },\n  company: \"Microsoft\",\n }\n```\n\n## Adding implementation to structs\n\nStructs are by their very nature just data fields that describe something complex. You can add behaviour to it though by creating functions that operate on a struct. Here's an example:\n\n```go\nfunc (a Address) string() string {\n return fmt.Sprintf(\"City: %s, Street: %s, Postal address: %s\", a.city, a.street, a.postal)\n}\n```\n\nWe've added a `string()` method. The method *belongs* to `Address` and we can see that with `(...)` right after the `func` keyword that takes `a Address`. The rest of the implementation returns a formatted string via `Sprintf()`.  Given the following code:\n\n```go\nvar address Address\naddress.city = \"London\"\naddress.street = \"Buckingham palace\"\naddress.postal = \"SW1\"\nfmt.Println(address.string())\n```\n\nWe would get the following output when calling `string()`:\n\n```output\nCity: London, Street: Buckingham palace, Postal address: SW1\n```\n\n## Assignment - defining a struct\n\nDefine a struct representing a row in a shopping basket for an e-commerce store.\n\nHere's example data:\n\n```output\nTitle, Description, Quantity, Price per unit, Total\nLEGO set, 4000 pieces, 1, 600GBP, 600GBP \n```\n\n### Write a program representing the shopping basket\n\nWrite a program that iterates over the shopping basket and calculates the total:\n\n```output\nTitle, Description, Quantity, Price per unit, Total\nLEGO set, 4000 pieces, 1, 600GBP, 600GBP\nPlushy, plush toy, 3, 5 GBP, 15GBP \n\nTotal: 615 GBP\n```\n\n## Solution\n\nPart I\n\n```go\npackage main\n\nimport (\n \"fmt\"\n)\n\ntype Row struct {\n Title       string\n Description string\n Quantity    int\n UnitPrice   float32\n}\n\nfunc main() {\n row := Row{\n  Title:       \"LEGO set\",\n  Description: \"4000 pieces\",\n  Quantity:    1,\n  UnitPrice:   600,\n }\n fmt.Println(row)\n}\n```\n\nPart II\n\n```go\npackage main\n\nimport (\n \"fmt\"\n)\n\ntype Row struct {\n Title       string\n Description string\n Quantity    int\n UnitPrice   float32\n}\n\nfunc main() {\n row := Row{\n  Title:       \"LEGO set\",\n  Description: \"4000 pieces\",\n  Quantity:    1,\n  UnitPrice:   600,\n }\n row2 := Row{\n  Title:       \"Plushy\",\n  Description: \"plush toy\",\n  Quantity:    3,\n  UnitPrice:   5,\n }\n\n basket := make([]Row, 0)\n basket = append(basket, row)\n basket = append(basket, row2)\n\n var sum int = 0\n for i := 0; i < len(basket); i++ {\n  current := basket[i]\n  fmt.Println(current)\n  sum += current.Quantity * int(current.UnitPrice)\n }\n fmt.Println(\"Total\", sum)\n}\n\n```\n"
  },
  {
    "path": "02-data-types/02-structs /assignment.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\ntype Row struct {\n\tTitle       string\n\tDescription string\n\tQuantity    int\n\tUnitPrice   float32\n}\n\nfunc main() {\n\trow := Row{\n\t\tTitle:       \"LEGO set\",\n\t\tDescription: \"4000 pieces\",\n\t\tQuantity:    1,\n\t\tUnitPrice:   600,\n\t}\n\trow2 := Row{\n\t\tTitle:       \"Plushy\",\n\t\tDescription: \"plush toy\",\n\t\tQuantity:    3,\n\t\tUnitPrice:   5,\n\t}\n\n\tbasket := make([]Row, 0)\n\tbasket = append(basket, row)\n\tbasket = append(basket, row2)\n\n\tvar sum int = 0\n\tfor i := 0; i < len(basket); i++ {\n\t\tcurrent := basket[i]\n\t\tfmt.Println(current)\n\t\tsum += current.Quantity * int(current.UnitPrice)\n\t}\n\tfmt.Println(\"Total\", sum)\n}\n"
  },
  {
    "path": "02-data-types/02-structs /go.mod",
    "content": "module struct\n\ngo 1.16\n"
  },
  {
    "path": "02-data-types/02-structs /main.go",
    "content": "package main\n\nimport \"fmt\"\n\n// normal struct\ntype Address struct {\n\tcity   string\n\tstreet string\n\tpostal string\n}\n\n// embedded with different name\ntype Person struct {\n\tname    string\n\taddress Address\n}\n\nfunc (a *Address) setAddress(copy Address) {\n\ta.city = copy.city\n\ta.street = copy.street\n\ta.postal = copy.postal\n}\n\nfunc (a Address) string() string {\n\treturn fmt.Sprintf(\"City: %s, Street: %s, Postal address: %s\", a.city, a.street, a.postal)\n}\n\n// embedded with same name\ntype Employee struct {\n\tAddress\n\tcompany string\n}\n\nfunc main() {\n\tvar address Address\n\taddress.city = \"London\"\n\taddress.street = \"Buckingham palace\"\n\taddress.postal = \"SW1\"\n\tfmt.Println(address.city)\n\tfmt.Println(address.string())\n\n\taddress2 := Address{\"New York\", \"Central park\", \"111\"}\n\taddress3 := Address{city: \"LA\", street: \"Hollywood Boulevard\", postal: \"123\"}\n\n\tfmt.Println(address2.city)\n\n\taddress2.setAddress(address3)\n\tfmt.Println(address2.city)\n\tfmt.Println(address3.city)\n\n\tperson := Person{\n\t\tname: \"chris\",\n\t\taddress: Address{\n\t\t\tcity: \"Stockholm\",\n\t\t},\n\t}\n\tfmt.Println(person.address.city)\n\n\temployee := Employee{\n\t\tAddress: Address{\n\t\t\tcity: \"LA\",\n\t\t},\n\t\tcompany: \"Microsoft\",\n\t}\n\n\t// employee.company = \"test\"\n\tfmt.Println(employee.company)\n}\n"
  },
  {
    "path": "02-data-types/03-maps/README.md",
    "content": "# Using maps\n\nA map is a complex data structure that enables you to store things in a key-value fashion. This lets you implement scenarios like phone books, translation dictionaries and more.\n\n## Introduction\n\nThis chapter will cover:\n\n- Defining a map.\n- Reading the values of map by key but also iterating over it.\n- Change the content of a map.\n\n## The use case for a map\n\nYou will have scenarios when you code that there are things you need to look up. If you use a dictionary for example you might look up how you can translate a word from English to Spanish or vice versa. In programming, you have similar situations, maybe you want to know what service is run on a certain port for example. There are also databases that are based on the concept of having a unique key that points to a certain value.\n\nHow all this is implemented is via map structure. The idea is that you define a key and value and collect all those in a group, a map.\n\n## Creating a map\n\nTo create a map in Go, we need to use the following syntax:\n\n```go\nmap[<key type>]<value type>{ ... entries }\n```\n\nHere's an example of creating a map structure that could hold a phone book:\n\n```go\nphonebook := map[int]string{ 555123: \"Robin Hood\", 555404: \"Sheriff of Nottingham\"}\n```\n\nWe define a map structure with key type `int` and value type string. Then we assign it a value with `{}`. Each entry is defined according to `<key>: <value>` and separated by a comma. So how do we read a value?\n\n### Create a map with `make()`\n\nAnother way to create a map us by using the `make()` function. `make()` returns a initialized map if you give it a type like so:\n\n```go\ndictionaryEnSv = make(map[string]string)\n```\n\n### Adding entries\n\nTo add entries to the map, you need to provide it with a key and value entry like so:\n\n```go\ndictionaryEnSv[\"hello\"] = \"hej\"\n```\n\n## Read a value by key\n\nImagine now that we have these two entries, and you want the value given that you have in entry 555404, how would we do that? We use the square brackets like so `[]`:\n\n```go\nphonebook[555404] // \"Sheriff of Nottingham\"\n```\n\n### Check for existing entry\n\nSo, you learned that `phonebook[555404]` gives you a value back. What if it doesn't exist? If you give it a key that's not stored in the map then you get nothing back as a result:\n\n```go\nphonebook[888] // this prints as empty in the console\n```\n\nThere's a better way to check this because accessing an entry with a key returns two values, the value, and a Boolean. The Boolean indicates if this key exists in the map. See this code:\n\n```go\n_, exist := phonebook[888]\nfmt.Println(exist) // false\n```\n\nHere you get the value back, but you choose to ignore for this one-time occasion to only focus on `exist`, a Boolean that tells you if the entry exists.\n\nYou can even use this construct in an if statement:\n\n```go\nif _, exist := phonebook[888] {\n  // number exist, call person\n}\n```\n\n## Iterate over a map\n\nWe can iterate over a map with a `for` construct and a `range`. Here's how you can iterate:\n\n```go\nfor key, value := range phonebook {\n  fmt.Println(key, value)\n}\n```\n\n## Delete an entry\n\nTo remove an entry from a map, you can use the `delete()` method. The `delete()` method takes the map and the key to delete as parameters, like so:\n\n```go\ndelete(phonebook, 555404)\n```\n\n## Assignment - build a phone book\n\nHere are your contacts:\n\n```output\nAlice 555-123 \nBob 555-124\nJean 555-125\n```\n\n```console\nWelcome to your phonebook.\nCommand> store\nEnter contact: Rob 555-126\nContact saved\nCommand> list\nAlice 555-123 \nBob 555-124\nJean 555-125\nRob 555-126\nCommand> lookup\nEnter name: Alice\nAlice has number: 555-123\n```\n\nHINT: you might need to use both a map and a slice.\n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n var command string\n contacts := make(map[string]string)\n fmt.Println(\"Welcome to your phonebook\")\n\n for {\n  fmt.Print(\"Command> \")\n  fmt.Scan(&command)\n  if command == \"store\" {\n   fmt.Print(\"Enter contact: \")\n   var contact string\n   var no string\n   fmt.Scan(&contact, &no)\n   contacts[contact] = no\n   fmt.Println(\"Contact saved\")\n  } else if command == \"list\" {\n   for key, value := range contacts {\n    fmt.Println(key, value)\n   }\n  } else if command == \"lookup\" {\n   fmt.Print(\"Enter name: \")\n   var contact string\n   fmt.Scan(&contact)\n   fmt.Println(contacts[contact])\n  } else if command == \"quit\" {\n   break\n  } else {\n   fmt.Println(\"Unknown command: \", command)\n  }\n }\n fmt.Println(\"Bye\")\n}\n\n```\n\n## Challenge\n\nRight now, there's no error checking. Add a check so that if you look up a contact that doesn't exist, you should get an error message. Here's how it could work:\n\n```console\ncommand> lookup\nEnter name: Jane\nContact doesn't exist, do you want to add it? y/n: y\nEnter contact: Jane 123\nContact saved\n```\n"
  },
  {
    "path": "02-data-types/03-maps/assignment.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tvar command string\n\tcontacts := make(map[string]string)\n\tfmt.Println(\"Welcome to your phonebook\")\n\n\tfor {\n\t\tfmt.Print(\"Command> \")\n\t\tfmt.Scan(&command)\n\t\tif command == \"store\" {\n\t\t\tfmt.Print(\"Enter contact: \")\n\t\t\tvar contact string\n\t\t\tvar no string\n\t\t\tfmt.Scan(&contact, &no)\n\t\t\tcontacts[contact] = no\n\t\t\tfmt.Println(\"Contact saved\")\n\t\t} else if command == \"list\" {\n\t\t\tfor key, value := range contacts {\n\t\t\t\tfmt.Println(key, value)\n\t\t\t}\n\t\t} else if command == \"lookup\" {\n\t\t\tfmt.Print(\"Enter name: \")\n\t\t\tvar contact string\n\t\t\tfmt.Scan(&contact)\n\t\t\tfmt.Println(contacts[contact])\n\t\t} else if command == \"quit\" {\n\t\t\tbreak\n\t\t} else {\n\t\t\tfmt.Println(\"Unknown command: \", command)\n\t\t}\n\t}\n\tfmt.Println(\"Bye\")\n}\n"
  },
  {
    "path": "02-data-types/03-maps/main.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tcars := map[string]string{\"make\": \"Ferrari\", \"model\": \"F40\"}\n\tfmt.Println(cars[\"make\"])\n\tfmt.Printf(\"cars\\t%v\\n\", cars)\n\t_, exist := cars[\"model\"]\n\n\tfmt.Println(exist)\n\tval, exist := cars[\"m\"]\n\tfmt.Println(val)\n\tfmt.Println(exist)\n}\n"
  },
  {
    "path": "02-data-types/04-interfaces/README.md",
    "content": "# Interfaces\n\nThis chapter covers what an interface is and what to use it for.\n\n## Introduction\n\nThis chapter will cover:\n\n- What is an interface and how does it differ from a struct.\n- How to add behaviour.\n- Implement an interface.\n- Type assertions.\n- Changing a value.\n\n## Interface\n\nTo describe what an interface is, let's start by talking about structs and how they are different from an interface.\n\nWith structs, we can define properties we want a concept to have, like for example a car:\n\n```go\ntype Car struct {\n  make string \n  model string\n}\n```\n\nAn interface is meant to communicate something different, a behaviour. Instead of describing the car itself, as a struct does, it describes what a car can do.  \n\n## Interface - describing a behaviour\n\nNow that we've described how an interface differs from a struct, let's talk about the motivation for using an interface. There are a couple of good reasons for when to use an interface:\n\n- **Adding behaviour**. When you want your types to have a behaviour, that's when you want an interface\n- **Communicate via contract**. Often, when you call other code, you want to reveal as little of your concrete implementation as possible. Instead of saying, here's a car, you might want to say, here's something that can run. It enables your code to be flexible and you don't have to implement specific code for each type but can instead write code that deals with a certain behaviour.\n\n### Define an interface\n\nTo define an interface, you need the keywords `type` and `interface` and you need a set of methods, one or many that a type should implement. Here's an example interface:\n\n```go\ntype Describable interface {\n  describe() string\n}\n```\n\nHere's another example:\n\n```go\ntype Point struct {\n  x int\n  y int\n}\n\ntype Shape interface {\n  area() int\n  location() Point\n}\n```\n\n## Implement an interface\n\nEverything that's a type can implement an interface. More than one type can implement the same interface. Let's look at how a type `Rectangle` can implement the `Shape` interface:\n\n```go\ntype Rectangle struct {\n  x int\n  y int\n}\n\nfunc (r Rectangle) area() int {\n  return r.x * r.y\n}\n\nfunc (r Rectangle) location() Point {\n  return P{ x: r.x, y: r.y }\n}\n```\n\nSo, what's going on here? Let's look at the first method `area()`:\n\n```go\nfunc (r Rectangle) area() int {\n  return r.x * r.y\n}\n```\n\nIt looks like a regular function but there's this `(r Rectangle)` right before the function name. That's a signal to Go that you are implementing a certain function on the type `Rectangle`. There's also a second implementation for `location()`.\n\nBy implementing both these methods, `Rectangle` has now fully implemented the `Shape` interface.\n\n### Pass an interface\n\nOk, so we've fully implemented an interface, what does it allow me to do? Well, there are two things you can do:\n\n- **Call properties and behaviour**. At this point, you are ready to create an instance and call both properties and methods (its new behaviour):\n\n   ```go\n   var rectangle Rectangle = Rectangle{x: 5, y: 2}\n   fmt.Println(rectangle.area()) // prints 10\n   ```\n\n   Great, our `Rectangle` type has both the properties `x` and `y` as well as the behaviour from `Shape`.\n\n- **Pass an interface**. Imagine you wanted to pass the behaviour to a function to make it flexible:\n\n   ```go\n   func printArea(shape Shape) {\n     fmt.Println(shape.area())\n   }\n   ```\n\n   To make that happen, lets change slightly how we construct our `Rectangle instance`:\n\n   ```go\n   var shape Shape = Rectangle{x: 5, y: 2}\n   printArea(rectangle) // prints 10\n   ```\n\n### Implement `Square`\n\nTo see the power in what we just created, let's create another struct `Square` and have it implement `Shape`:\n\n```go\ntype Square struct {\n  side int\n}\n\nfunc (s Square) area() int {\n  return s.square * s.square\n}\nfunc (s Square) location() Point {\n  return Point{x: s.side, y: s.side}\n}\n\nfunc main() {\n  var shape Shape = Rectangle{x: 5, y: 2}\n  var shape2 Shape = Square{side: 5}\n  printArea(shape) // prints 10\n  printArea(shape2) // prints 25\n}\n```\n\nThe power lies in the fact that `printArea()` doesn't have to deal with the internals of `Rectangle` or `Shape`, it just needs the parameter to implement `Shape`, a behaviour.\n\n### Full code\n\nHere's the full code:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Rectangle struct {\n x int\n y int\n}\n\ntype Point struct {\n x int\n y int\n}\n\ntype Square struct {\n side int\n}\n\ntype Shape interface {\n area() int\n location() Point\n}\n\nfunc printArea(shape Shape) {\n fmt.Println(shape.area())\n}\n\nfunc (r Rectangle) area() int {\n return r.x * r.y\n}\n\nfunc (r Rectangle) location() Point {\n return Point{x: r.x, y: r.y}\n}\n\nfunc (s Square) area() int {\n return s.side * s.side\n}\n\nfunc (s Square) location() Point {\n return Point{x: s.side, y: s.side}\n}\n\nfunc main() {\n var shape Shape = Rectangle{x: 5, y: 2}\n var shape2 Shape = Square{side: 5}\n printArea(shape)  // prints 10\n printArea(shape2) // prints 25\n}\n```\n\n## Type assertions\n\nSo far, a `Rectangle` or `Square` implements the `Shape` interface\n\nLet's have a closer look at this code:\n\n```go\nvar shape Shape = Rectangle{x: 5, y: 2}\nvar shape2 Shape = Square{side: 5}\nprintArea(shape)  // prints 10\nprintArea(shape2) // prints 25\n```\n\nWe've said for `shape` and `shape2` to be of type `Shape`. That's great for being sent to the `printArea()` method. What if we need to access a `Rectangle` property on `shape`, can we? Let's try:\n\n```go\nvar shape Shape = Rectangle{x: 5, y: 2}\nfmt.Println(shape.x) // shape.x undefined (type Shape has no field or method x)\n```\n\nOk, not working, we need to find a way to reach the underlying fields. We can use something called *type assertion* like so:\n\n```go\nvar shape Shape = Rectangle{x: 5, y: 2}\nfmt.Println(shape.(Rectangle).x) // 5\n```\n\nOk, that works, so `.(<type>)` works, if the underlying type is the correct type.\n\n## Change a value\n\nSo, one thing about our approach so far is that we have implemented interfaces with methods that read data from the underlying struct instances. What if we want to change data, can we do that?\n\nLet's look at an example:\n\n```go\npackage main\nimport \"fmt\"\n\ntype Car struct {\n speed int\n model string\n make string\n}\n\ntype Runnable interface {\n run()\n}\n\nfunc (c Car) run() {\n c.speed = 10\n}\n\nfunc main() {\n  c := Car{make: \"Ferrari\", model: \"F40\", speed: 0}\n  c.run()\n  fmt.Println(c.speed) // ?\n}\n```\n\nRunning this code, it returns `0`. So, looking at our `run()` method:\n\n```go\nfunc (c Car) run() {\n c.speed = 10\n}\n```\n\nshouldn't this work? Well, no, because you are not changing the instance. For that, you need to send a reference.\n\nA slight alteration to the `run()` method, with `*`:\n\n```go\nfunc (c *Car) run() {\n c.speed = 10\n}\n```\n\nand your code now does what it's supposed to.\n\n## Assignment\n\nStart with the following code:\n\n```go\npackage main \n\ntype Point struct {\n x float32\n y float32\n}\n\ntype Vehicle struct {\n velocity float32\n Point\n}\n\nfunc main() {\n v := Vehicle{\n  velocity: 0,\n  Point: Point{\n   x: 0,\n   y: 0,\n  },\n }\n v.fly()\n fmt.Println(v.velocity)\n v.land()\n fmt.Println(v.velocity)\n}\n```\n\nImplement the following interface:\n\n```go\ntype Spaceship interface {\n fly()\n land()\n position() Point\n}\n```\n\nThe output from running the program should be:\n\n```output\n10\n0\n```\n\n## Solution\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Point struct {\n x float32\n y float32\n}\n\ntype Vehicle struct {\n velocity float32\n Point\n}\n\ntype Spaceship interface {\n fly()\n land()\n position() Point\n}\n\nfunc (v *Vehicle) fly() {\n v.velocity = 10\n}\n\nfunc (v *Vehicle) land() {\n v.velocity = 0\n}\n\nfunc (v Vehicle) position() Point {\n return v.Point\n}\n\nfunc main() {\n v := Vehicle{\n  velocity: 0,\n  Point: Point{\n   x: 0,\n   y: 0,\n  },\n }\n v.fly()\n fmt.Println(v.velocity)\n v.land()\n fmt.Println(v.velocity)\n}\n```\n"
  },
  {
    "path": "02-data-types/04-interfaces/assignment.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Point struct {\n\tx float32\n\ty float32\n}\n\ntype Vehicle struct {\n\tvelocity float32\n\tPoint\n}\n\ntype Spaceship interface {\n\tfly()\n\tland()\n\tposition() Point\n}\n\nfunc (v *Vehicle) fly() {\n\tv.velocity = 10\n}\n\nfunc (v *Vehicle) land() {\n\tv.velocity = 0\n}\n\nfunc (v Vehicle) position() Point {\n\treturn v.Point\n}\n\nfunc main() {\n\tv := Vehicle{\n\t\tvelocity: 0,\n\t\tPoint: Point{\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t},\n\t}\n\tv.fly()\n\tfmt.Println(v.velocity)\n\tv.land()\n\tfmt.Println(v.velocity)\n}\n"
  },
  {
    "path": "02-data-types/04-interfaces/cast.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n)\n\nfunc elementAt(elements interface{}, index int) (interface{}, error) {\n\tswitch t := elements.(type) {\n\tcase []int:\n\t\treturn t[index], nil\n\tcase []string:\n\t\treturn t[index], nil\n\tdefault:\n\t\tfmt.Println(t)\n\t\treturn nil, errors.New(\"unsupported\")\n\t}\n}\n\nfunc main() {\n\tintArr := []int{1, 2, 3}\n\tstringArr := []string{\"one\", \"two\", \"three\"}\n\n\tvalue, err := elementAt(intArr, 2)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(value)\n\tvalue, err = elementAt(stringArr, 1)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(value)\n}\n"
  },
  {
    "path": "02-data-types/04-interfaces/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\ntype Runnable interface {\n\trun()\n}\n\ntype Describable interface {\n\tdescription() string\n}\n\ntype Car struct {\n\tspeed int\n\tmodel string\n\tmake  string\n}\n\ntype Hero struct {\n\tname string\n}\n\nfunc DescribeThings(describable Describable) {\n\tfmt.Println(describable.description())\n}\n\nfunc RunThings(car *Car) {\n\tcar.run()\n}\n\nfunc (c *Car) run() {\n\tc.speed = 10\n}\n\nfunc (c Car) description() string {\n\treturn fmt.Sprintf(\"Model: %s, Make: %s\", c.model, c.make)\n}\n\nfunc (hero Hero) description() string {\n\treturn fmt.Sprintf(\"The heroes name is: %s\", hero.name)\n}\n\nfunc main() {\n\n\tvar describable Describable\n\tdescribable = Car{speed: 0, make: \"Ferrari\", model: \"F40\"}\n\tDescribeThings(describable)\n\n\tvar describable2 Describable\n\tdescribable2 = Hero{name: \"Conan\"}\n\tDescribeThings(describable2)\n\n\tc := Car{speed: 0, make: \"Porsche\", model: \"911\"}\n\tp := &c\n\tRunThings(p)\n\tfmt.Println(c.speed)\n\n}\n"
  },
  {
    "path": "02-data-types/04-interfaces/shape.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Rectangle struct {\n\tx int\n\ty int\n}\n\ntype Point struct {\n\tx int\n\ty int\n}\n\ntype Square struct {\n\tside int\n}\n\ntype Shape interface {\n\tarea() int\n\tlocation() Point\n}\n\nfunc printArea(shape Shape) {\n\tfmt.Println(shape.area())\n}\n\nfunc (r Rectangle) area() int {\n\treturn r.x * r.y\n}\n\nfunc (r Rectangle) location() Point {\n\treturn Point{x: r.x, y: r.y}\n}\n\nfunc (s Square) area() int {\n\treturn s.side * s.side\n}\nfunc (s Square) location() Point {\n\treturn Point{x: s.side, y: s.side}\n}\n\nfunc main() {\n\tvar shape Shape = Rectangle{x: 5, y: 2}\n\tvar shape2 Shape = Square{side: 5}\n\tprintArea(shape)  // prints 10\n\tprintArea(shape2) // prints 25\n\tfmt.Println(shape.(Rectangle).x)\n}\n"
  },
  {
    "path": "02-data-types/04-interfaces/test.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Car struct {\n\tspeed int\n\tmodel string\n\tmake  string\n}\n\ntype Runnable interface {\n\trun()\n}\n\nfunc (c *Car) run() {\n\tc.speed = 10\n}\n\nfunc main() {\n\tc := Car{make: \"Ferrari\", model: \"F40\", speed: 0}\n\tc.run()\n\tfmt.Println(c.speed) // ?\n}\n"
  },
  {
    "path": "03-projects/01-first-project/README.md",
    "content": "# Your first project\n\nIn this chapter, we will cover how to create your first project in Go.\n\n## Introduction\n\nThis chapter will cover:\n\n- Creating a project.\n- Organize your files.\n\n## Module use cases\n\nThere are two interesting use cases with modules:\n\n- **Consuming a module**, you will use a combination of core modules and external 3rd party modules\n- **Creating a module**, in some cases you will create code that you or someone else will be able to use. For this scenario, you can create a module and upload it to GitHub.\n\n## Consume internal files\n\nYou want to split up your app in many different files. Let's say you have the following files:\n\n```output\n/app\n  main.go\n  /helper\n    helper.go \n```\n\nWhat you are saying above is that your program consists of many files and that you want code in the fiile *main.go* to use code from *helper.go* for example.\n\nTo handle such a case, you need the following:\n\n- **a project**. By creating a project, you create a top-level reference that you can use in the `import` directive.\n- **an import** that points to the project root name as well as the path to the module you want to import.\n\nYou can use `go mod init`, this will initialize your project.\n\n## Creating a project\n\nTo create a project, you run `go mod init` and a name for a project, for example, \"my-project\":\n\n   ```bash\n   go mod init my-project\n   ```\n\n   You end up with a *go.mod* file looking something like so:\n\n   ```go\n   module my-project\n\n   go 1.16\n   ```\n\n   The *go.mod* file tells you the name of your project and the currently used version of Go. It can contain other things as well like libraries you are dependent on.\n\n## The import statement\n\nImagine now we have this file structure in our project:\n\n```output\n/app\n  main.go\n  /helper\n    helper.go \n```\n\nwith *helper.go* looking like so:\n\n```go\npackage helper\n    \nimport \"fmt\"\n\nfunc Help() {\n  fmt.Println(\"This is a helper function\")\n}\n```\n\nto use the public `Helper()` function from *main.go*, we need to import it.\n\nIn *main.go* we need an import statement like so:\n\n```go\nimport (\n  \"my-project/helper\"\n)\n```\n\nWe are now able to invoke the `Help()` function from *main.go* like so:\n\n```go\nhelper.Help()\n```\n\n## Assignment - create a project\n\nIn this assignment, you will create a project.\n\n1. Create a project like so:\n\n    ```go\n    go mod init my-project\n    ```\n\n1. create the **helper** directory and *helper.go* file and give it the following content:\n\n    ```go\n    // helper.go\n    \n    package helper\n    \n    import \"fmt\"\n    \n    func Help() {\n     fmt.Println(\"This is a helper function\")\n    }\n    ```\n\n1. Create the *main.go* file and give it the following content:\n\n   ```go\n   package main\n\n   import (\n     \"my-project/helper\"\n   )\n    \n   func main() {\n     helper.Help()\n   }\n   ```\n\n   Note this import `\"my-project/helper\"`, it ensures the `helper` package is in scope.\n\n1. Compile and run\n\n   ```bash\n   go run main.go\n   ```\n\n## Solution\n\nhelper/helper.go\n\n```go\npackage helper\n\nimport \"fmt\"\n\nfunc Help() {\n fmt.Println(\"help\")\n}\n```\n\nmain.go\n\n```go\npackage main\n\nimport \"my-project/helper\"\n\nfunc main() {\n helper.Help()\n}\n```\n\n## Challenge\n\nSee if you can create another function in *helper.go*, this time, make the function name lowercase, what happens if you try to import it?\n"
  },
  {
    "path": "03-projects/01-first-project/go.mod",
    "content": "module my-project\n\ngo 1.16\n"
  },
  {
    "path": "03-projects/01-first-project/helper/helper.go",
    "content": "package helper\n\nimport \"fmt\"\n\nfunc Help() {\n\tfmt.Println(\"help\")\n}\n"
  },
  {
    "path": "03-projects/01-first-project/main.go",
    "content": "package main\n\nimport \"my-project/helper\"\n\nfunc main() {\n\thelper.Help()\n}\n"
  },
  {
    "path": "03-projects/02-consume-external/README.md",
    "content": "# Consume an external module\n\nIn this chapter, we are looking at downloading and using external modules.\n\n## Introduction\n\nThis chapter will cover:\n\n- Creating a project.\n- Adding an external module to your project.\n- Use the external library in your app.\n\n## External module\n\nTo consume an external module, you need to:\n\n- **Import it**, involves using the `import` instruction and fully qualifying the address to the module's location.\n- **Use it in code**, call the code from the module that you mean to use\n- **Ensure it's downloaded**, so your code can be run.\n\n## Import module\n\nTo import a module, you can do one of two things:\n\n- `go get <path to module>`, this will fetch the module and download it and make it available for your project to use.\n- `go mod tidy`, this command checks the imports used in your program and fetches the module if not fetched already.\n\n## Use it in code\n\nTo use your module in code, you need to add it to the `import` section and then invoke it where you need it in the application code.\n\n```go\nimport (\n  \"github.com/<user>/<repo name>\"\n)\n\nfunc main() {\n  <repo name>.<Function>()\n}\n```\n\nHere's an example:\n\n```go\npackage main\n    \nimport (\n\"fmt\"\n\"github.com/softchris/math\"\n)\n\nfunc main() {\n  math.Add(1,1) // 2\n}\n```\n\n## Assignment - consume an external module\n\nLet's create a new project\n\n1. Run `go mod init`:\n\n    ```go\n    go mod init hello\n    ```\n\n    Note how *go.mod* was created with the following content:\n\n    ```go\n    module hello\n    \n    go 1.16\n    ```\n\n### Add reference to an external lib\n\nNext, lets create some code that will use the external library:\n\n1. Create the file *main.go*\n\n    ```go\n    package main\n    \n    import (\n      \"fmt\"\n      \"github.com/softchris/math\"\n    )\n    ```\n\n1. To the same file, add a `main()` function and call the external `Add` method from the `math` package:\n\n    ```go\n    func main() {\n      sum := math.Add(1,2)\n      fmt.Println(sum)\n    }\n    ```\n\n### Fetch the lib\n\nNow, we need to resolve the external library.\n\n1. Run `go mod tidy`:\n\n    ```bash\n    go mod tidy\n    ```\n\n    Your *go.mod* is updated:\n\n    ```go\n    require github.com/softchris/math v0.2.0\n    ```\n\n    There's also *go.sum* file with the following content:\n\n    ```go\n    github.com/softchris/math v0.2.0 h1:88L6PLRBGygS3LY5KGIJhyw9IZturmd2ksU+p13OPa4=\n\n    github.com/softchris/math v0.2.0/go.mod h1:v8WzhjKC+ipuH+i9IZ0Ta2IArniTP53gc5TgCINCqAo=\n    ```\n\n    This is Go's way of keeping track of how to build the app by referencing to the go module in question.\n\n1. Run `go run`:\n\n   ```go\n   go run main.go\n   ```\n\n   Running the program gives you the following output:\n\n   ```output\n   3\n   ```\n\n## Solution\n\ngo.sum\n\n```go\ngithub.com/softchris/math v0.2.0 h1:88L6PLRBGygS3LY5KGIJhyw9IZturmd2ksU+p13OPa4=\ngithub.com/softchris/math v0.2.0/go.mod h1:v8WzhjKC+ipuH+i9IZ0Ta2IArniTP53gc5TgCINCqAo=\n\n```\n\ngo.mod\n\n```go\nmodule hello\n\ngo 1.16\n\nrequire github.com/softchris/math v0.2.0\n\n```\n\nmain.go\n\n```go\npackage main\n    \nimport (\n  \"fmt\"\n  \"github.com/softchris/math\"\n)\n\nfunc main() {\n  sum := math.Add(1,2)\n  fmt.Println(sum)\n}\n```\n\n## Challenge\n\nSee if you can find another module you want to use in your project. Add it to the project and use it in your code.\n"
  },
  {
    "path": "03-projects/02-consume-external/go.mod",
    "content": "module hello\n\ngo 1.16\n\nrequire github.com/softchris/math v0.2.0\n"
  },
  {
    "path": "03-projects/02-consume-external/go.sum",
    "content": "github.com/softchris/math v0.2.0 h1:88L6PLRBGygS3LY5KGIJhyw9IZturmd2ksU+p13OPa4=\ngithub.com/softchris/math v0.2.0/go.mod h1:v8WzhjKC+ipuH+i9IZ0Ta2IArniTP53gc5TgCINCqAo=\n"
  },
  {
    "path": "03-projects/02-consume-external/log-tester/go.mod",
    "content": "module log-tester\n\ngo 1.16\n\nrequire github.com/softchris/logger v0.1.0\n"
  },
  {
    "path": "03-projects/02-consume-external/log-tester/go.sum",
    "content": "github.com/softchris/logger v0.1.0 h1:Kqw7t9C3Y7BtHDLTx/KXEqHy5x8EJxrLian742S0di0=\ngithub.com/softchris/logger v0.1.0/go.mod h1:rrzWjMsM3tqjetDBDyezI8mFCjGucF/b5RSAqptKF/M=\n"
  },
  {
    "path": "03-projects/02-consume-external/log-tester/helper/helper.go",
    "content": "package helper\n\nimport \"fmt\"\n\nfunc Help() {\n\tfmt.Println(\"This is a helper function\")\n}\n"
  },
  {
    "path": "03-projects/02-consume-external/log-tester/main.go",
    "content": "package main\n\nimport (\n\t\"log-tester/helper\"\n\n\t\"github.com/softchris/logger\"\n)\n\nfunc main() {\n\tlogger.Log(\"hey there\")\n\thelper.Help()\n}\n"
  },
  {
    "path": "03-projects/02-consume-external/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/softchris/math\"\n)\n\nfunc main() {\n\tsum := math.Add(1, 2)\n\tfmt.Println(sum)\n}\n"
  },
  {
    "path": "03-projects/03-create-shared-module/README.md",
    "content": "# Create a module meant for sharing\n\nIn this chapter, we will cover how you can create a module you can share with others.\n\n## Introduction\n\nThis chapter will cover:\n\n- Creating a project.\n- Testing the module locally.\n- Tag the module with different versions.\n- Try consuming the module as an external library.\n\n## Create a module\n\nWhen you build a module meant for sharing, there's some gotchas:\n\n- You need to create a package.\n- Your package won't be called main.\n- There's the concept of public and private parts of your code.\n- You can test it locally.\n- Upload your package to GitHub for wide distribution.\n\n## Assignment - create a module meant for sharing and consume it\n\nTo create a module meant for wider use you need to first initialize a module.\n\n1. Create a directory *logger* for your new package:\n\n   ```go\n   mkdir logger\n   cd logger   \n   ```\n\n1. Run `go mod init <address at github>`, for example:\n\n   ```bash\n   go mod init github.com/softchris/logger\n   ```\n\n   This will create a *go.mod* file in your directory.\n\n   ```output\n   logger/\n     go.mod\n   ```\n\n   The file looks like so:\n\n   ```go\n   module github.com/softchris/logger\n\n   go 1.16\n   ```\n\n   It contains the package name and the version of Go it means to use.\n\n1. Create a file to host your package code, for example *log.go* and give it the following content:\n\n   ```go\n    package logger\n\n    import (\n     \"fmt\"\n    )\n    \n    var Version string = \"1.0\"\n    \n    func Log(mess string) {\n     fmt.Println(\"[LOG] \" + mess)\n    }\n   ```\n\n   - Note `package logger` instead of `main`.\n   - The uppercase variables and methods makes the publicly available. Anything named with lowercase will be private for the package.\n\n### Test it locally\n\nYou can test your package locally. To do so you need a separate package that you can import your package from.\n\n1. Move up a directory:\n\n   ```bash\n   cd ..\n   ```\n\n1. Create a new directory **logger-test**:\n\n   ```bash\n   mkdir logger-test\n   cd logger-test\n   ```\n\n1. Create a package, it will be used for testing only:\n\n   ```bash\n   go mod init logger-test\n   ```\n\n1. Create a file *main.go* and add the following code:\n\n   ```go\n    package main\n\n    import \"github.com/softchris/logger\"\n    \n    func main() {\n     logger.Log(\"hey there\")\n    }\n   ```\n\n   At this point, you are consuming the \"logger\" package but it's pointing to GitHub and your package doesn't live there yet. However, you can repoint to a local address on your machine, let's do that next.\n\n1. Open *go.mod* and add the following:\n\n   ```go\n   require github.com/softchris/logger v0.0.0\n\n   replace github.com/softchris/logger => ../logger\n   ```\n\n   Two things are happening here:\n  \n   - you are asking for the \"logger\" package:\n  \n      ```go\n      require github.com/softchris/logger v0.0.0\n      ```\n\n   - you are making it point to your local system instead of GitHub\n\n      ```go\n      replace github.com/softchris/logger => ../logger\n      ```\n\n1. Run the package with `go run`:\n\n    ```bash\n    go run main.go\n    ```\n\n    You should see:\n\n    ```output\n    [LOG] hey there\n    ```\n  \n### Publish a package\n\nTo publish your package, you can put it on GitHub.\n\n1. Create a git repo with `git init`:\n\n   ```bash\n   git init\n   ```\n\n1. Create the repo on GitHub.\n\n1. Make you do at least one commit:\n\n    ```bash\n    git add .\n    git commit -m \"first commit\"\n    ```\n\n1. Do the following to upload your package to GitHub:\n\n   ```bash\n   git remote add origin https://github.com/softchris/logger.git\n\n   git branch -M main\n   git push -u origin main\n   ```\n\n1. Tag your package with `git tag`:\n\n   ```bash\n   git tag v0.1.0\n   git push origin v0.1.0\n   ```\n\n   Now your package has the tag 0.1.0\n\n### Test it out\n\n1. Go to your project \"logger-test\":\n\n   ```bash\n   cd ..\n   cd logger-test\n   ```\n\n1. Open up *go.mod* and remove these lines:\n\n   ```go\n   require github.com/softchris/logger v0.0.0\n\n   replace github.com/softchris/logger => ../logger\n   ```\n\n1. Run `go mod tidy`, this will force Go to go look for the package:\n\n   Your *go.mod* should now contain:\n\n   ```go\n   require github.com/softchris/logger v0.1.0\n   ```\n\n   Also, your *go.sum* should contain:\n\n   ```go\n   github.com/softchris/logger v0.1.0 h1:Kqw7t9C3Y7BtHDLTx/KXEqHy5x8EJxrLian742S0di0=\n\n   github.com/softchris/logger v0.1.0/go.mod h1:rrzWjMsM3tqjetDBDyezI8mFCjGucF/b5RSAqptKF/M=\n   ```\n\n1. Run the program with `go run`:\n\n   ```bash\n   go run main.go\n   ```\n\n   You should see:\n\n   ```output\n   [LOG] hey there\n   ```\n\n## Challenge\n\nSee if you can add a feature to your new package. Give it a new tag via Git. Then ensure your app is using this new version.\n"
  },
  {
    "path": "03-projects/04-testing/README.md",
    "content": "# Test your code in Go\n\nIn this chapter, we will look at creating and running unit tests.\n\n## Introduction\n\nThis chapter will cover:\n\n- Why you should test your code.\n- The testing library in Go.\n- Authoring and running a test.\n- Controlling how to run your tests.\n- Produce coverage reports.\n\n## Why we test\n\nIt's good to test your code to ensure it works as intended. In this chapter, we're looking at unit tests specifically.\n\n## What Go provides\n\nGo has a package `testing` that gives us two things to start out with:\n\n- a parameter for the test. The `testing` library exposes a `t *testing.T` parameter. By putting it as a parameter to a function, said function becomes a test.\n\n   ```go\n   func TestAdd(t *testing.T) {}\n   ```\n\n- a way to assert the result. `testing` also exposes `t.Errorf()`. By invoking it with a string, the test counts as failed. To pass a test you do nothing:\n\n   ```go\n   t.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 4)\n   ```\n\nHere's an example test function:\n\n```go\nfunc TestAdd(t *testing.T) {\n total := Add(2, 2)\n if total != 4 {\n  t.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 4)\n }\n t.Log(\"running TestAdd\")\n}\n```\n\n- First, the code to test is called:\n\n   ```go\n   total := Add(2, 2)\n   ```\n\n- Secondly, the assertion is made, to see if it succeeded or failed:\n\n   ```go\n   if total != 4 {\n     t.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 4)\n   }\n   ```\n\n   if the result is not the expected, then `t.Errorf()` is called to state what's gone wrong.\n\n## Your first test\n\nMake sure you've created a project with `go mod init`. Then create a file structure like so:\n\n```output\nmain.go\nmath/\n  math.go\n```\n\nWhat you want to do next is to create a test file. You want to keep the test file as close to the code you want to test as possible. Because you want to test *math.go* you create `math_test.go` file in the math/ directory like so:\n\n```output\nmain.go\nmath/\n  math.go\n  math_test.go\n```\n\n### Authoring and running your first test\n\nNow that you have the file structure above, ensure the *math_test.go* file has the following content:\n\n```go\npackage math\n\nimport (\n \"testing\"\n)\n\nfunc TestAdd(t *testing.T) {\n  total := Add(2, 2)\n  if total != 4 {\n    t.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 4)\n  }\n  t.Log(\"running TestAdd\")\n}\n```\n\nTo run a test, you invoke the `go test` command. Here are different ways to run your tests:\n\n- `go test`, runs the test in the current working directory. Here's what it looks like:\n\n   ```output\n   ok      test-example/math       0.258s\n   ```\n\n- `go test -v`, runs a verbose version. Here's what it can look like:\n\n   ```output\n   === RUN   TestAdd\n    math_test.go:12: running TestAdd\n\n   --- PASS: TestAdd (0.00s)\n   PASS\n   ok      test-example/math       0.422s\n   ```\n\n   In the verbose version, you see the name of the test and if it failed.\n\n- `go test ./..`, recursive run. If you run the command like so it will run all the tests in the subfolders as well.\n\n## Control the test run\n\nThere are ways to control how many tests are run. Here are some ways:\n\n- **Run test by pattern**. . You can provide a pattern to have Go run some of the tests, which matches it by a substring or even at a certain depth and more. Here's how:\n  \n    ```console\n    go test -run <pattern>\n    ```\n\n- **Skip a test**. `t.Skip()` by calling this inside the test, the test is skipped.\n- **Run a single test**. You can run a single test by running a pattern that specifies the package and the name of the test, here's how:\n\n   ```console\n   go test -run TestAdd ./math\n   ```\n\n   Here's the package is called math and the name of the test is `TestAdd()`.\n\n## Coverage\n\nThere's a built-in tool for dealing with coverage. To learn more about the tool, you can type:\n\n```console\ngo tool cover -help\n```\n\nit will list a set of commands.\n\nThe tool is centred on the concept of having an out file. The out file contains instructions on where your code is covered by tests and where it isn't. An out file can look something like this:\n\n```output\nmode: set\ntest-example/math/math.go:3.32,5.2 1 1\ntest-example/math/math.go:7.37,9.2 1 1\ntest-example/math/math.go:11.47,13.2 1 0\n```\n\nThis is a format readable by the tool.\n\nIt's a prerequisite to generate said \"out file\" before you can view your code's coverage. Place yourself in the directory you mean to measure coverage on and run this command:\n\n```console\ngo test -coverprofile=c.out\n```\n\nNow you are ready to run a command that shows the result in a browser:\n\n```console\ngo tool cover -html=c.out\n```\n\nThe above command spins up a browser and the output look something like so:\n\n![coverage](coverage.png)\n\nThe coverage report tells us that the the green portions are covered by tests whereas the red portions should have tests covering it.\n\n## Learn more\n\nThere's a lot more to learn on testing with Go, have a look at package documentation, [docs](https://pkg.go.dev/testing)\n\n## Challenge\n\nCreate a test for a piece of code you wrote. Run the test. See if you can produce a coverage report and implement any gaps pointed out by the report.\n"
  },
  {
    "path": "03-projects/04-testing/go.mod",
    "content": "module test-example\n\ngo 1.16\n"
  },
  {
    "path": "03-projects/04-testing/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\tm \"test-example/math\"\n)\n\nfunc main() {\n\tfmt.Println(m.Add(1, 1))\n}\n"
  },
  {
    "path": "03-projects/04-testing/math/c.out",
    "content": "mode: set\ntest-example/math/math.go:3.32,5.2 1 1\ntest-example/math/math.go:7.37,9.2 1 1\ntest-example/math/math.go:11.47,13.2 1 0\n"
  },
  {
    "path": "03-projects/04-testing/math/math.go",
    "content": "package math\n\nfunc Add(lhs int, rhs int) int {\n\treturn lhs + rhs\n}\n\nfunc Subtract(lhs int, rhs int) int {\n\treturn lhs - rhs\n}\n\nfunc Divide(lhs float32, rhs float32) float32 {\n\treturn lhs / rhs\n}\n"
  },
  {
    "path": "03-projects/04-testing/math/math_test.go",
    "content": "package math\n\nimport (\n\t\"testing\"\n)\n\nfunc TestAdd(t *testing.T) {\n\ttotal := Add(2, 2)\n\tif total != 4 {\n\t\tt.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 4)\n\t}\n\tt.Log(\"running TestAdd\")\n}\n\nfunc TestSub(t *testing.T) {\n\ttotal := Subtract(2, 2)\n\tif total != 0 {\n\t\tt.Errorf(\"Sum was incorrect, Actual: %d, Expected: %d\", total, 0)\n\t}\n\tt.Log(\"running TestSubtract\")\n}\n"
  },
  {
    "path": "04-webdev/01-json/README.md",
    "content": "# Working with JSON\n\nIn this chapter, you will work with the JSON data format.\n\n## Introduction\n\nIn this chapter, you will learn the following:\n\n- The JSON data format.\n- How to read JSON data and map it to existing structures in Go.\n- How to create JSON and persist it in files.\n\n## JSON\n\nJSON is a lightweight data format for storing and transporting data. The acronym stands for **J**ava**S**cript **O**bject **n**otation.\n\nThe format is commonly used in Web services. Usually, data is encoded as JSON and sent via HTTP. A client, for example, a web browser, consumes the JSON data and uses it to render a frontend with the help of HTML and CSS. It's also common for JSON to be used to communicate between services.\n\nHere's an example of what the format looks like:\n\n```json\n{\n  \"products\": [{\n    \"id\": 1,\n    \"name\": \"a product\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"another product\"\n  }]\n}\n```\n\nThe above depicts a list of products. Each key needs to be encased with quotes and values can be everything from primitives like numbers, strings, Booleans etc to more complex types like an array or an object.\n\nwhat is this format, and what contexts is it used in.\n\n## Reading JSON\n\nTo work with JSON, you need to use the `encoding/json` library. It allows you to both read and write JSON data.\n\nTo read JSON data you need to first have a structure in your Go code read to map to the JSON data. Imagine having the following JSON data:\n\n```json\n{\n  \"products\" : [\n    {\n      \"id\": 1,\n      \"name\": \"some product\"\n    }\n  ]\n}\n```\n\nTo map this in Go, you need a struct that matches its structure like so:\n\n```go\ntype Product struct {\n  Id int\n  Name string\n}\n\ntype Response struct {\n  Products []Product\n}\n```\n\n### Notation\n\nThe first step is to create the structures needed to match your JSON data. But you also need to do one more thing, add notations. The problem we are looking to solve is how the `Product` property is called `Id` and not `id` as it's called in the JSON data.\n\n> Won't that just work?\n\nUnfortunately, not\n\n> Why don't you just name the struct property `id`\n\nThe library `encoding/json`, is a separate package from the main package, meaning we need to make a field name, defined in the main package, uppercase for the `encoding/json` package to find it.\n\nSo that means, we need to add the following annotations to our above created structs:\n\n```go\ntype Product struct {\n  Id int `json: \"id\"`\n  Name string `json: \"name\"`\n}\n\ntype Response struct {\n  Products []Product `json: \"products\"`\n}\n```\n\nWhat these annotations do is to say, in the JSON data, look for properties with these names and map them to the following property. Like in this example from above:\n\n```go\nId int `json: \"id\"`\n```\n\n### Reading the data\n\nOk, so we've defined the structures in Go that we will map our JSON data to. So how do we read from a JSON source? Well, JSON is usually stored in one of two ways:\n\n- a string literal, like so `{ \"name\": \"my product\", \"id\": 1 }`\n- in a JSON file:\n\n   ```json\n   {\n     \"id\": 1,\n     \"name\": \"my product\"\n   }\n   ```\n\nLet's show how to work with both approaches:\n\n**Reading from a string literal**\n\nWe will use the `Unmarshal()` function and provide it with the string literal as the first parameter and the data to write the result to as the second parameter.\n\n```go\npackage main\n\nimports (\n  \"fmt\"\n  \"encoding/json\"\n)\n\nfunc main() {\n  str := `{ \"name\": \"my product\", \"id\": 1 }`\n  product := Product{}\n  json.Unmarshal([]byte(str), &product)\n  fmt.Println(product) // prints the object\n}\n```\n\nNote how we also convert the response to a byte array `[]byte(str)` and how the data is written in the second parameter to the `product` instance as a reference, `&product`.\n\n**read from a file**\n\nTo read from a file, we will use the `io/ioutil` library and its `ReadFile()` function. Like with the string literal, the `Unmarshal()` function will be used to write the data to a struct instance.\n\n```go\npackage main\n\nimport (\n \"encoding/json\"\n \"fmt\"\n \"io/ioutil\"\n \"iohelper/dir\"\n \"iohelper/file\"\n \"log\"\n)\n\ntype Products struct {\n Products []Product `json: products`\n}\n\ntype Product struct {\n Id   int    `json: \"id\"`\n Name string `json: \"name\"`\n}\n\nfunc main(){\n  file, _ := ioutil.ReadFile(\"products.json\")\n\n  data := Products{}\n\n  _ = json.Unmarshal([]byte(file), &data)\n\n  for i := 0; i < len(data.Products); i++ {\n    fmt.Println(\"Product Id: \", data.Products[i].Id)\n    fmt.Println(\"Name: \", data.Products[i].Name)\n  }\n}\n```\n\n## Writing JSON\n\nWe've seen so far how we can read JSON data either from a string literal or from a file, but what about writing data?\n\nTwo cases are important for us:\n\n- Writing data to a structure. We are working with structs so any changes we do on the structs need to be converted back to JSON.\n- Generate JSON from data. In the second case, we might be working with a raw string literal or even with pure primitives, how would we do that?\n\nLet's address both these cases. What these cases have in common is the `Marshal()` function. The `Marshal()` method can take a primitive or a struct and taking that into JSON:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"encoding/json\"\n)\n\ntype Person struct {\n  Id int `json: \"id\"`\n  Name string`json: \"name\"`\n}\n\nfunc main() {\n  aBoolean, _ := json.Marshal(true)\n  aString, _ := json.Marshal(\"a string\")\n  person := Person{\n    Id: 1\n    Name: \"a person\"\n  }\n  aPerson, _ := json.Marshal(&person)\n  fmt.Println(string(aBoolean)) // true\n  fmt.Println(string(aString))  // a string\n  fmt.Println(string(person))  // { \"id\": 1, \"name\": \"a person\" }\n}\n```\n\n## Assignment\n\nGiven the following file *response.json*, find a way to read the data and display it on the screen:\n\n```json\n{\n  \"orders\": [\n   {\n    \"id\": 1,\n    \"items\": [\n      { \"id\": 1, \"quantity\": 3, \"total\": 34.3 },\n     { \"id\": 2, \"quantity\": 2, \"total\": 17.8 }\n    ]\n   },\n   {\n    \"id\": 2,\n    \"items\": [\n      { \"id\": 3, \"quantity\": 3, \"total\": 10.0 },\n      { \"id\": 4, \"quantity\": 2, \"total\": 100.5 }\n    ]\n   }\n  ]\n}\n```\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"encoding/json\"\n \"fmt\"\n \"io/ioutil\"\n)\n\ntype OrderItem struct {\n Id       int     `json: \"id\"`\n Quantity int     `json: \"quantity\"`\n Total    float32 `json: \"total\"`\n}\n\ntype Order struct {\n Id    int         `json: \"id\"`\n Items []OrderItem `json: items`\n}\n\ntype Response struct {\n Orders []Order `json: orders`\n}\n\nfunc main() {\n file, _ := ioutil.ReadFile(\"orders.json\")\n\n data := Response{}\n\n _ = json.Unmarshal([]byte(file), &data)\n fmt.Println(data)\n for i := 0; i < len(data.Orders); i++ {\n  fmt.Println(\"Order Id: \", data.Orders[i].Id)\n\n  for j := 0; j < len(data.Orders[i].Items); j++ {\n   item := data.Orders[i].Items[j]\n   fmt.Println(\"Item id\", item.Id)\n   fmt.Println(\"Item quantity\", item.Quantity)\n   fmt.Println(\"Item total\", item.Total)\n  }\n }\n}\n\n```\n\n## 🚀 Challenge\n\nSee if you can add `products` to your JSON file. Here's the JSON for it:\n\n```json\n\"products\" :[{\n  \"id\": 1\n  \"name\" \"product\"\n}]\n```\n\nWhat structs do you need and how would you iterate over them?\n\n## Learn more\n\n<https://gobyexample.com/json>\n"
  },
  {
    "path": "04-webdev/01-json/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\ntype Person struct {\n\tName string `json: \"name\"`\n\tAge  int    `json: \"age\"`\n}\n\nfunc main() {\n\tstr := `{ \"name\": \"chris\", \"age\": 20 }`\n\tperson := Person{}\n\tjson.Unmarshal([]byte(str), &person)\n\tfmt.Println(person)\n}\n"
  },
  {
    "path": "04-webdev/01-json/orders.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n)\n\ntype OrderItem struct {\n\tId       int     `json: \"id\"`\n\tQuantity int     `json: \"quantity\"`\n\tTotal    float32 `json: \"total\"`\n}\n\ntype Order struct {\n\tId    int         `json: \"id\"`\n\tItems []OrderItem `json: items`\n}\n\ntype Response struct {\n\tOrders []Order `json: orders`\n}\n\nfunc main() {\n\tfile, _ := ioutil.ReadFile(\"orders.json\")\n\n\tdata := Response{}\n\n\t_ = json.Unmarshal([]byte(file), &data)\n\tfmt.Println(data)\n\tfor i := 0; i < len(data.Orders); i++ {\n\t\tfmt.Println(\"Order Id: \", data.Orders[i].Id)\n\n\t\tfor j := 0; j < len(data.Orders[i].Items); j++ {\n\t\t\titem := data.Orders[i].Items[j]\n\t\t\tfmt.Println(\"Item id\", item.Id)\n\t\t\tfmt.Println(\"Item quantity\", item.Quantity)\n\t\t\tfmt.Println(\"Item total\", item.Total)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "04-webdev/01-json/orders.json",
    "content": "{\n  \"orders\": [\n   {\n    \"id\": 1,\n    \"items\": [\n      { \"id\": 1, \"quantity\": 3, \"total\": 34.3 },\n     { \"id\": 2, \"quantity\": 2, \"total\": 17.8 }\n    ] \n   },\n   {\n    \"id\": 2, \n    \"items\": [\n      { \"id\": 3, \"quantity\": 3, \"total\": 10.0 },\n      { \"id\": 4, \"quantity\": 2, \"total\": 100.5 }\n    ] \n   } \n  ]\n}"
  },
  {
    "path": "04-webdev/01-json/person.json",
    "content": "{\n  \"name\": \"chris\",\n  \"age\": 20\n}"
  },
  {
    "path": "04-webdev/02-web-dev/README.md",
    "content": "# Build a Web API\n\nA Web API is usually what we interact with to serve data to our services or a client. Said client may either be web page or tool like curl. In this chapter, we will learn to build a Web API that will process requests via HTTP.\n\n## Introduction\n\nIn this chapter, you will learn the following:\n\n- What's a Web API.\n- The `net/http` library, and its capabilities at high-level.\n- Responding to a request.\n- Working with request data like router and query parameters but also the body.\n- Using ServeMux, and why it may the preferred choice.\n\n## Web API\n\nCommon responsibilities for web services are to respond to requests:\n\n- **asking for data** and serve data like JSON, XML images, CSS, HTML\n- **asking to modify a resource** either by creating, updating, or deleting it.\n\n## The `net/http` library\n\nThere's a library `net/http` that will help us build a web server. Building a web server with this library involves the following:\n\n- Create a server instance.\n- Define route requests and how to respond to them.\n- Start the server instance, making sure it's accessible on a certain address and port.\n\n### Create a server instance\n\nIn `net/http`,  `http` represents your service instance.\n\n```go\nimport (\n \"fmt\"\n \"net/http\"\n)\n\nfunc main() {\n  // do something with `http`\n}\n```\n\n### Define routes\n\nA route is you defining logical separations in your app like `products`, `orders` or some other area it makes sense to divide your app in.\n\nTo define a route, you define a route pattern and function that is invoked when the route is hit:\n\n```go\nfunc hello(w http.ResponseWriter, req *http.Request) {\n  fmt.Fprintf(w, \"hello\\n\")\n}\n\nfunc main(){\n  http.HandleFunc(\"/hello\", hello)\n}\n```\n\nIn the code above, the string \"/hello\" is a route pattern that states that all web requests to \"/hello\" should be handled by the `hello()` function.\n\n### Response and Request\n\nA close inspection of the `hello()` function reveals that it takes a `ResponseWriter` and `Request`:\n\n```go\nfunc hello(w http.ResponseWriter, req *http.Request) {\n  fmt.c(w, \"hello\\n\")\n}\n```\n\nThe expectation is that you inspect the `req` object, your request for any data that decides what to return. Then you are to use `w` to produce a response. In this case, you are returning a string by passing `w` to `Fprintf()`. `FPrintf()` takes a writer. The writer is anything IO, so it could be, be writing to a file for example as well, or as in this case an HTTP response stream.\n\n### Start the server\n\nOk, we've gone through routes, producing a response, how would we get this server activated so it starts responding to requests?\n\nYou use the `ListenAndServe()` function that takes a port like so:\n\n```go\nhttp.ListenAndServe(\":8090\", nil)\n```\n\n## Responding to a request\n\nAn incoming request could be asking for a specific route like /products or /orders for example, or it could be asking for a specific static file like an image, a text file or maybe CSS. The request itself gives us a hint, about not only the logical domain it wants data from, like orders or products but what data type it wants, or it might even present credentials for authentication. The hint is known as headers.\n\n### Header\n\nThere's a concept called headers. A header is giving off a piece of information that could say what piece of content it is, how big the content is, or it could be a token helping you authenticate for example.\n\nHeaders can exist both on the incoming request as well as the response.\n\n### Serving different types of content\n\nServing different types of content means that we are working on the response. To serve various content type, we need to instruct the response on what type of content it is so that a consuming client knows how to interpret it, (in some cases, clients like a web browser can figure that out anyway through a process called content sniffing).\n\nTo serve a specific type of content, there are two things you need to do:\n\n- **set the content type**, you set the content type by calling:\n\n   ```go\n   w.Header().Set(\"Content-Type\", \"image/jpeg\")\n   ```\n\n   Here the content type is an image of subtype jpeg. There are many content types you could be setting like plain text, CSS, JSON, XML and more.\n\n- **produce the response**. Producing a response means writing to the response stream. That can be done by calling the `Write()` method on the `ResponseWriter` instance we are passed when we handle a route. There are other methods capable of writing to said stream as well.\n\n### Serving image data\n\nTo serve an image, you need to load it into memory, set the content type and write it to the response stream like below code:\n\n```go\nfunc GetImage(w http.ResponseWriter, r *http.Request) {\n    f, _ := os.Open(\"/image.jpg\")\n    \n    // Read the entire JPG file into memory.\n    reader := bufio.NewReader(f)\n    content, _ := ioutil.ReadAll(reader)\n    \n    // Set the Content Type header.\n    w.Header().Set(\"Content-Type\", \"image/jpeg\")\n    \n    // Write image to the response.\n    w.Write(content)\n}\n```\n\n- First, we open the image:\n\n   ```go\n   f, _ := os.Open(\"/image.jpg\")\n   ```\n\n- Secondly, we read the file into memory:\n\n   ```go\n   reader := bufio.NewReader(f)\n   content, _ := ioutil.ReadAll(reader)\n   ```\n\n- Thirdly, set the `Content-Type` header and tell it it's a JPEG image, with the value \"image/jpeg\":\n\n   ```go\n   w.Header().Set(\"Content-Type\", \"image/jpeg\")\n   ```\n\n- Finally, we write the content to the response:\n\n   ```go\n   w.Write(content)\n   ```\n\n### Serving JSON data\n\nJust like with serving images, we need to follow a similar approach of configuring the correct content-type header and then constructing the response. Here's the code:\n\n```go\npackage main\n\nimport (\n  \"encoding/json\"\n)\n\ntype Person struct {\n  Id int\n  Name string\n}\n\nfunc ReturnJson(w http.ResponseWriter, r *http.Request) {\n  w.Header().Set(\"Content-Type\", \"application/json\")\n\n  p := Person {\n    Id: 1\n    Name: \"a person\"\n  }\n\n  json.NewEncoder(w).Encode(p)\n}\n\nfunc main() {\n  http.HandleFunc(\"/json\", ReturnJson)\n}\n```\n\n- First, we set the content type, by setting the value \"application/json\":\n\n   ```go\n   w.Header().Set(\"Content-Type\", \"application/json\")\n   ```\n\n- Secondly, we construct the data we are about to send out:\n\n   ```go\n   p := Person {\n    Id: 1\n    Name: \"a person\"\n  }\n   ```\n\n- Finally, we encode the data as JSON and write it to the response stream:\n\n   ```go\n   json.NewEncoder(w).Encode(p)\n   ```\n\nIt's also possible to use the `Marshal()` function like so, instead of `json.NewEncoder()`:\n\n```go\ndata, err := json.Marshal(p)\nw.Write(data)\n```\n\n## Working with the request\n\nThere are various ways, additionally to headers, to instruct the server program what to do:\n\n- **HTTP verb**, the HTTP verb expresses intention. The POST verb means to create a resource and the GET verb says to only read the data for example. There are many HTTP verbs that we will cover later in this chapter. These two below requests mean different things:\n\n   ```text\n   GET /products # fetching a list of products\n   POST /products # creating a new product resource\n   ```\n\n- **body**, The body can contain a payload, data we can use to create or update a resource usually. Here's an example:\n\n   ```json\n   {\n     \"name\" : \"a new product\" \n   }\n   ```\n\n- **router parameters**. As part of a route request, you can have parameters that carry meaning. If the client asks for the route `/products/5` then the 5 can mean the calling client is after a specific product whose unique identifier is 5.\n- **query parameter**. At the end of the route, there can be a query section. That section can give further instruction to the request to for example reduce the size of the returning data. Does the query part start with a question mark? and is followed by key-value pairs separated by ampersands, &. It can look like so: `/products?page=1&pageSize=20`  \n\n### Parsing a body\n\nThe request has a `Body` property. Depending on what's in the body, you might need to decode it. Below code is decoding a piece of JSON and writing it to the response stream:\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"encoding/json\"\n)\n\ntype Person struct {\n  Id int\n  Name string\n}\n\nfunc handleRequest(w http.ResponseWriter, r *http.Request) {\n  var p Person\n\n  json.NewDecoder(r.Body).Decode(&p)\n  // save person to storage\n\n  fmt.Fprintf(w)\n}\n\nfunc main() {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/person/\", handleRequest)\n\n  err := http.ListenAndServe(\":4000\", mux)\n}\n```\n\n### Read a route parameter\n\nThere's no built-in way to access a route parameter so you would have to parse it like so:\n\n```go\ntokens := strings.Split(r.URL.Path, \"/\")\n// check each part\n```\n\nor use for example a regular expression to parse out the parts.\n\nAnother choice is using a library like the following:\n\n- [httprouter](https://github.com/julienschmidt/httprouter)\n- [Gorilla Mux](http://www.gorillatoolkit.org/pkg/mux)\n\nHere's an example using `httprouter`:\n\n```go\nfunc Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {\n    fmt.Fprintf(w, \"The id us, %s!\\n\", ps.ByName(\"id\"))\n}\n\nfunc main() {\n    router := httprouter.New()\n    router.GET(\"/products/:id\", Hello)\n\n    log.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n### Read a query parameter\n\nThe query part of the route is accessible via the `Query()` function on the `URL` property of the request instance:\n\n```go\nr.URL // /products?page=3&pageSize=20\nr.URL.Query() // ?page=3&pageSize=20\n```\n\nTo access a specific parameter know that the `Query()` function returns a `Values` map.\n\n```go\nr.URL.Query()[\"page\"] // 3\n```\n\nIt's possible to call the `Get()` function as well, but only if there is only one parameter:\n\n```go\nr.URL.Query().Get(\"page\")\n```\n\n### HTTP method\n\nThe method means different things and should be handled differently. To access the request method, there's a `Method` property on the request, `r`.\n\n```go\nr.Method\n```\n\nThere's also defined constant like `MethodGet`, `MethodPost` on `http`, so you could write code like so:\n\n```go\nfunc handleRoute(w http.ResponseWriter, r *http.Request) {\n  if r.Method == http.MethodGet {\n    fmt.Println(\"It's a GET request\") \n  }\n}\n```\n\n## ServeMux, a better way\n\nSo far, you've created an HTTP server by calling `ListenAndServe()` with a port argument and nil. But there's another way to do it. You could be using something called servemux. A servemux is also known as a router. Much like using the `http` directly to add routes, you instead add those routes on the servemux. Let's show some code:\n\n```go\nmux := http.NewServeMux()\nmux.Handle(\"/hello\", handleHello)\nhttp.ListenAndServe(\":8090\", mux)\n```\n\nIn the preceding code, you instantiate the servemux by calling `NewServeMux()`. Then, you set up a route and its handler by calling `Handle()`. Finally, you call `ListenAndServe()` but this time around you pass the `mux` instance instead of `nil`.\n\nSo how is this better than the other way we've used so far? The first way we learned about, uses a `DefaultServeMux` and risks exposing profiling endpoints, which is bad. Another reason is connecting the routes directly to `http` changes the global state, which is looked down upon in Go generally.\n\n## Assignment - build a first web app\n\nYour web app should have at least one route. The said route should write to the response stream. The web app should start at a specific port, for example, 5500.\n\n## Solution\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n)\n\nfunc handleRequest(w http.ResponseWrite, r *http.Request) {\n  fmt.Fprintf(w, \"Hi there\")\n}\n\nfunc main() {\n  http.HandleFunc(\"/hello\", handleRequest) \n  http.ListenAndServe(\":8090\", nil)\n}\n```\n\n## Challenge\n\n- list details on the request such as the route, the verb used and the query parameters.\n- See if you can serve up different types of data like JSON or images.\n"
  },
  {
    "path": "04-webdev/02-web-dev/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc hello(w http.ResponseWriter, req *http.Request) {\n\tfmt.Fprintf(w, \"hello\\n\")\n\n}\n\nfunc headers(w http.ResponseWriter, req *http.Request) {\n\tfor name, headers := range req.Header {\n\t\tfor _, h := range headers {\n\t\t\tfmt.Fprintf(w, \"%v: %v\\n\", name, h)\n\t\t}\n\t}\n}\n\nfunc main() {\n\thttp.HandleFunc(\"/hello\", hello)\n\thttp.HandleFunc(\"/headers\", headers)\n\n\thttp.ListenAndServe(\":8090\", nil)\n}\n\n// todo, JSON body\n// router params\n// query params\n// sqlite?\n"
  },
  {
    "path": "05-misc/01-logs/README.md",
    "content": "# Better logging with a logging library\n\nOnce you start writing code, you realize quite early that you need to print things to the screen as well as sometimes to a file or even a log service. What you want to say is usually what type of logging you want to do.\n\n## Introduction\n\nIn this chapter, you will learn the following:\n\n- Why and what to log.\n- Using the `log` library.\n\n## Reasons to log\n\nThere are many reasons to log, here are some reasons:\n\n- **Information**, there might be a case where you want to provide some type of information that could be of use to the one using the program.\n- **Success**. A success message is a little more than just information, it indicates that you succeeded with something.\n- **Warning**. When you have a warning, something happened that you should be aware of. It's usually not serious enough to shut down the app but it should make you vigilant, it could be that memory is running low for example.\n- **Error**. When you get an error, you tend to end up in a state where it's no longer a wise choice to continue.\n- **Performance**. It's common to measure how long something takes, for the sake of improving things this information can be useful.\n- **Other**. There are also other reasons why you would log something, usually, that's connected to your business.\n\n## What to log\n\nThe general rule is the more you can log the better. Especially if it's an error you want to fix you might want to log things like:\n\n- When it happened\n- What happened\n- Specific error info\n\nFor every case, you want to log, have a log at how the log message will be used, will a team be logging through these logs, and what would help them. See if you can interview someone on that team.\n\n## Using `log`\n\nIn general, you want to log in places where things might go wrong such as when you make web requests, work with I/O and so on.\n\nIn general, use these as guidelines for when to log:\n\n- **Faulty input**. If the program risks producing a faulty response, there was a problem converting/casting a number or it received an unexpected input for example.\n- **Error state**. If the program ends up in a state from which it can't recover, for example, unable to fetch a batch of data from a data source.\n\nYou don't want logs on every single line of code.  \n\n### Standard log `Println()`\n\nTo produce a standard log message, you can use the `Println()` function in the `log` package. It takes a string and will produce a log message that combines a date, time, and your error message.\n\nHere's some code using `Println()`:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"log\"\n)\n\nfunc main() {\n  log.Println(\"log message\")\n}\n```\n\nIt will produce an output like so:\n\n```output\n2022/03/24 12:42:13 log message\n```\n\n### Use `Fatal()` for errors\n\n`Println()` produces a normal looking log message with a date, time and message. `Fatal()` is used when you want to end the program. What `Fatal()` does is to print out the message you give it and call `os.Exit(1)`.\n\nHere's how it can be used:\n\n```go\nlog.Fatal(\"quit program due to <specify reason>\")\n```\n\n### Log to a file\n\nIf you develop an app, you are likely to run it and keep an eye on the console for what the app prints out.\n\nHowever, as your app becomes ready for production, you want to make sure that all logs that can be useful to analyse is kept somewhere, either sent to a log service or stored in a file.\n\nThat way, you ensure that you can analyze these logs later to understand where things went wrong or if you want to analyze the performance of your program.\n\nTo log into a file, you can use the `SetOutput()` function. It takes a file handler as input. Thereby, you can use these three lines of code to log:\n\n```go\nf, err := os.OpenFile(\"testlogfile\", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n\ndefer f.Close()\n\nlog.SetOutput(f)\n```\n\n- In the first line, you open up a file \"testlogfile\" and ensure you can append it to it.\n\n   ```go\n   f, err := os.OpenFile(\"testlogfile\", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n   ```\n\n- In the second line, you ensure the file is closed the last thing that happens in the program.\n\n   ```go\n   defer f.close()\n   ```\n\n- Finally you call `SetOutput()` which ensures all log message are sent to file \"testlogfile\", and not shown in the console.\n\n   ```go\n   log.SetOutput(f)\n   ```\n\n## Assignment\n\nIn this assignment, you will add the `log` library to your code.\n\n1. Create a file *records.csv* with the following content:\n\n   ```text\n   item,quantity\n\n   112, 2\n   94, 3\n   ```\n\n1. Create a file *app.go* and give it the following content:\n\n   ```go\n    package main\n\n    import (\n     \"fmt\"\n     \"io/ioutil\"\n     \"os\"\n    )\n    \n    func ProcessFile(path string) {\n     filebuffer, err := ioutil.ReadFile(path)\n     if err != nil {\n      fmt.Println(\"Error: \", err)\n      os.Exit(1)\n     }\n     inputdata := string(filebuffer)\n     fmt.Println(\"Do something with input: \\n\", inputdata)\n    }\n    \n    func main() {\n     fileName := \"records.csv\"\n    \n     fmt.Printf(\"processing file '%s' \\n\", fileName)\n     ProcessFile(fileName)\n    }\n   ```\n\n1. Run the file with `go run`:\n\n   ```go\n   go run app.go\n   ```\n\n   You should see the following output:\n\n   ```output\n   processing file 'records.csv'\n\n   Do something with input:\n   item,quantity\n   112, 2\n   94, 3\n   ```\n\n1. Add the `log` package to the import and replace all calls to `fmt` with `log`, like so:\n\n   ```go\n    package main\n\n    import (\n     \"io/ioutil\"\n     \"log\"\n    )\n    \n    func ProcessFile(path string) {\n     filebuffer, err := ioutil.ReadFile(path)\n     if err != nil {\n      log.Fatal(\"Error: \", err)\n     }\n     inputdata := string(filebuffer)\n     log.Print(\"Do something with input: \\n\", inputdata)\n    }\n    \n    func main() {\n     fileName := \"records.csv\"\n    \n     log.Printf(\"processing file '%s' \\n\", fileName)\n     ProcessFile(fileName)\n    }\n   ```\n\n   Let's see how the output differs.\n\n1. Run the program with `go run`:\n\n   ```go\n   go run main.go\n   ```\n\n   your output should be similar to:\n\n   ```output\n    2022/03/28 13:57:57 processing file 'records.csv'\n\n    2022/03/28 13:57:57 Do something with input:\n    item,quantity\n    112, 2\n    94, 3\n   ```\n\n1. Next, lets change the name of `fileName` to \"record.csv\", to trigger an error (there's no such file).\n\n   ```go\n   fileName := \"record.csv\"\n   ```\n\n1. Now, run the app `go run`:\n\n   ```bash\n   go run app.go\n   ```\n\n   You should see a similar output:\n\n   ```output\n   2022/03/28 14:04:52 processing file 'record.csv'\n\n   2022/03/28 14:04:52 Error: open record.csv: no such file or directory\n   exit status 1\n   ```\n\n   This time around though you see the program exciting with exit status 1.\n\n   The conclusion is that it's better to rely on the `log` library because you get dates and times, and you type less. But there's more, we can log to a file, let's see how we do that next.\n\n### Log to a file\n\nSomeone examining the output of the program is likely to inspect a log file overlooking the terminal. Let's instruct `log` to log to a file instead.\n\n1. At the start of the `main()` function, add the following code:\n\n   ```go\n     logFile := \"logfile\"\n\n     f, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n    \n     if err != nil {\n      log.Fatal(\"Could not log to file: \", logFile)\n     }\n     defer f.Close()\n   ```\n\n   Now you have instructed `log` to write all entries to the file *logfile*.\n\n1. Run the program again, `go run`:\n\n   ```bash\n   go run main.go\n   ```\n\n   You should now see the following output:\n\n   ```output\n   exit status 1\n   ```\n\n   All your log entries have moved to *logfile*, let's see what it looks like:\n\n   ```text\n   2022/03/28 14:11:24 processing file 'record.csv'\n\n   2022/03/28 14:11:24 Error: open record.csv: no such file or directory\n   ```\n\n   Great, now we have all entries in a central place, which should make it easier for us to analyze.\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"io/ioutil\"\n \"log\"\n \"os\"\n)\n\nfunc ProcessFile(path string) {\n filebuffer, err := ioutil.ReadFile(path)\n if err != nil {\n  log.Fatal(\"Error: \", err)\n }\n inputdata := string(filebuffer)\n log.Print(\"Do something with input: \\n\", inputdata)\n}\n\nfunc main() {\n fileName := \"record.csv\"\n logFile := \"logfile\"\n\n f, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n\n if err != nil {\n  log.Fatal(\"Could not log to file: \", logFile)\n }\n defer f.Close()\n\n log.SetOutput(f)\n\n log.Printf(\"processing file '%s' \\n\", fileName)\n ProcessFile(fileName)\n}\n```\n"
  },
  {
    "path": "05-misc/01-logs/batch.go",
    "content": "package main\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc ProcessFile(path string) {\n\tfilebuffer, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\tlog.Fatal(\"Error: \", err)\n\t}\n\tinputdata := string(filebuffer)\n\tlog.Print(\"Do something with input: \\n\", inputdata)\n}\n\nfunc main() {\n\tfileName := \"record.csv\"\n\tlogFile := \"logfile\"\n\n\tf, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n\n\tif err != nil {\n\t\tlog.Fatal(\"Could not log to file: \", logFile)\n\t}\n\tdefer f.Close()\n\n\tlog.SetOutput(f)\n\n\tlog.Printf(\"processing file '%s' \\n\", fileName)\n\tProcessFile(fileName)\n}\n"
  },
  {
    "path": "05-misc/01-logs/logfile",
    "content": "2022/03/28 14:11:24 processing file 'record.csv' \n2022/03/28 14:11:24 Error: open record.csv: no such file or directory\n"
  },
  {
    "path": "05-misc/01-logs/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n)\n\nvar ErrorDivideBeZero = errors.New(\"Divide by zero\")\n\nfunc Divide2(nominator int, divider int) (float32, error) {\n\tif divider <= 0 {\n\t\treturn 0, ErrorDivideBeZero\n\t}\n\treturn float32(nominator) / float32(divider), nil\n}\n\nfunc Divide(nominator int, divider int) float32 {\n\tif divider <= 0 {\n\t\tpanic(\"divider below zero\")\n\t}\n\treturn float32(nominator) / float32(divider)\n}\n\nfunc main() {\n\tf, err := os.OpenFile(\"testlogfile\", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)\n\n\tdefer f.Close()\n\tlog.SetOutput(f)\n\n\tlog.Println(\"starting batch job\", time.Now())\n\tfmt.Println(Divide(10, 2))\n\tval, err := Divide2(10, 0)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t\t// fmt.Println(err)\n\t\t// os.Exit(-1)\n\t}\n\tfmt.Println(val)\n\tlog.Println(\"stopping batch job\", time.Now())\n}\n"
  },
  {
    "path": "05-misc/01-logs/records.csv",
    "content": "item,quantity\n112, 2\n94, 3"
  },
  {
    "path": "05-misc/01-logs/testlogfile",
    "content": "2022/03/09 21:44:02 starting batch job 2022-03-09 21:44:02.92816 +0000 GMT m=+0.000518959\n2022/03/09 21:44:22 starting batch job 2022-03-09 21:44:22.138381 +0000 GMT m=+0.000334896\n2022/03/09 21:44:22 stopping batch job 2022-03-09 21:44:22.13893 +0000 GMT m=+0.000883596\n2022/03/09 21:45:20 starting batch job 2022-03-09 21:45:20.613968 +0000 GMT m=+0.000357770\n2022/03/09 21:45:20 Divide by zero\n2022/03/24 12:42:13 starting batch job 2022-03-24 12:42:13.933843 +0000 GMT m=+0.006561061\n2022/03/24 12:42:13 Divide by zero\n"
  },
  {
    "path": "05-misc/02-strings/README.md",
    "content": "# Working with strings\n\nThere are many reasons why we need to work with strings in different ways. Below are some situations that you are likely to encounter and that the `strings` library has a solution for:\n\n- **user input**, or other types of storage may contain special characters that you need to cater for.\n- **inspection**, does the string contain what we need for our business logic?\n- **parsing**, splitting the file until we get what we need, could be things like a number or date for example.\n- **presentation**, sometimes we need to present the text in certain way in a UI for example, to highlight said information.\n\n## Handling special characters\n\nLets say we read user input and we want to interpret what we get as a number. To make our program robust, we're ok with the user typing spaces or newline characters. The following input should be allowed:\n\n```text\n114\n   114\n114\\n\n```\n\nThere's three methods of interest to handle such a case for us, namely `Trim()`, `TrimLeft()` and `TrimRight()`.\n\n- `Trim()`, what it does is remove whitespace characters from both left and right side.\n- `TrimLeft()`. It removes whitespace from the left side only, and if you specify special characters as well.\n- `TrimRight()`. It removes whitespace from the right side only, and if you specify special characters as well.\n\nAll these functions above have as their second parameter a so called *cutset* parameter, where you specify what character you want to get rid of. You can for example specify to remove space, newline and tab characters like so:\n\n```go\n\" \\n\\t\"\n```\n\nHere's some code that shows all three methods in use:\n\n```go\nfmt.Printf(\"%s , string length %d \\n\", s, len(s))\n res := strings.Trim(s, \" \")\n fmt.Printf(\"%s , string length %d \\n\", res, len(res))\n\n s2 := \"   114  \"\n fmt.Printf(\"%s , string length %d \\n\", s2, len(s2))\n res = strings.TrimLeft(s2, \" \")\n fmt.Printf(\"%s , string length %d \\n\", res, len(res))\n\n s3 := \"   114  \"\n fmt.Printf(\"%s , string length %d \\n\", s3, len(s3))\n res = strings.TrimRight(s3, \" \")\n fmt.Printf(\"%s , string length %d \\n\", res, len(res))\n```\n\nThe above string has three whitespaces to the left and two to the right, giving it a total length of 8.\n\nThe output of the above code is:\n\n```output\n  114   , string length 8 \n114 , string length 3 \n   114   , string length 8 \n114   , string length 5 \n   114   , string length 8 \n   114 , string length 6 \n```\n\nLets break down the output per row.\n\nFor this output, using `Trim()`, the spaces are removed on both sides and we end up with something looking left aligned:\n\n```output\n\"114\"\n```\n\nThe next output, using `TrimLeft()`, shows how the right spaces are still there:\n\n```output\n\"114   \"\n```\n\nOur final row, using `TrimRight()`, shows a right alignment and how the spaces on the left side still remains:\n\n```output\n\"   114\"\n```\n\n## Inspect with `Contains()`\n\nImagine you want to inspect a string to verify whether it contains a certain substring.\n\nFor that, you can use the `Contains()` function. Its syntax looks like so:\n\n```go\nstrings.Contains(stringSource, pattern)\n```\n\nYou can then for example use it to process a list from a point of sale system, and for each item check if it contains a certain prefix:\n\n```go\nrows := []string{\"order: 5\", \"order: 10\", \"order: 5\", \"separator\"}\n\n\nfor item :=  range rows {\n  if strings.Contains(\"order\") {\n    // process order\n  }\n  // ignore\n}\n```\n\n## Parsing with `Split()`\n\nLets continue with processing rows from our point of sale system. This time, we will be looking at a specific item and extract the information we need. For this, we will use the `Split()` function:\n\n```go\nrows := []string{\"order: 5\", \"order: 10\", \"order: 5\", \"separator\"}\n\nfor item :=  range rows {\n  if strings.Contains(\"order\") {\n     tokens := strings.Split(item, \":\") // [ \"order\", \" 5\"]\n     value := strings.Trim(tokens[1])\n     fmt.Println(value)\n  }\n  // ignore\n}\n```\n\nBy using this code:\n\n```go\nstrings.Split(item, \":\")\n```\n\non this string \"order: 5\", we end up with an array `[\"order\", \"5\"]` and `strings.Trim(tokens[1])` would then refer to 5.\n\n> TIP: If we need to treat the 5 above as a number, as part of calculation, we would need to convert it to a number first\n\n## Presentation\n\nSay you have customer management system and there's a lot of data to present. To give importance to certain data, we can use functions to highlight their visual appearance.\n\nTake the following multiline customer string:\n\n```text\nJean Normand\n123 Way\nWashington\n```\n\nIf you use `ToUpper()` on city you get a result like so:\n\n```output\nJean Normand\n123 Way\nWASHINGTON\n```\n\nWith `ToLower()` you ensure all characters are formatted as lowercase.\n\n## Assignment\n\nWrite a program that given a struct containing, name, address and city ensures that the name is lowercase and the address is uppercase.\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"strings\"\n)\n\ntype Person struct {\n Name    string\n Address string\n City    string\n}\n\nfunc main() {\n person := Person{Name: \"jean Normand\", Address: \"123 Way\", City: \"Washington\"}\n\n fmt.Println(strings.ToUpper(person.Name))\n fmt.Println(person.Address)\n fmt.Println(strings.ToUpper(person.City))\n}\n```\n"
  },
  {
    "path": "05-misc/02-strings/contains.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc main() {\n\tfmt.Println(strings.Contains(\"hello all\", \"el\"))\n  \n}\n"
  },
  {
    "path": "05-misc/02-strings/presentation.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype Person struct {\n\tName    string\n\tAddress string\n\tCity    string\n}\n\nfunc main() {\n\tperson := Person{Name: \"Jean Normand\", Address: \"123 Way\", City: \"Washington\"}\n\n\tfmt.Println(strings.ToLower(person.Name))\n\tfmt.Println(person.Address)\n\tfmt.Println(strings.ToUpper(person.City))\n}\n"
  },
  {
    "path": "05-misc/02-strings/strings.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc main() {\n\ts := \"   114  \"\n\n\tfmt.Printf(\"%s , string length %d \\n\", s, len(s))\n\tres := strings.Trim(s, \" \")\n\tfmt.Printf(\"%s , string length %d \\n\", res, len(res))\n\n\ts2 := \"   114  \"\n\tfmt.Printf(\"%s , string length %d \\n\", s2, len(s2))\n\tres = strings.TrimLeft(s2, \" \")\n\tfmt.Printf(\"%s , string length %d \\n\", res, len(res))\n\n\ts3 := \"   114  \"\n\tfmt.Printf(\"%s , string length %d \\n\", s3, len(s3))\n\tres = strings.TrimRight(s3, \" \")\n\tfmt.Printf(\"%s , string length %d \\n\", res, len(res))\n}\n"
  },
  {
    "path": "05-misc/03-regex/README.md",
    "content": "# Use regular expressions to parse text\n\nIn this chapter, you'll learn how to use Regular Expressions to search and replace text.\n\n## What is RegEx and what to use it for\n\nRegular Expressions or RegEx for short, is used for searching and replacing text. Technically a RegEx is a sequence of characters that specifies a search pattern.\n\n## Why use RegEx\n\nRegEx primary usage area is for searching text, replacing it and also extracting text. There do exist string libraries that can do some of the functionality RegEx is capable of. Sometimes using those string libraries might even be the best thing to do. However, sometimes a RegEx pattern is better.\n\n> Fair word of warning though, RegEx is hard to get right. You are encouraged to learn more of how they work cause they are quite powerful.\n\nMy hope is by you reading this chapter, that you will find RegEx less intimidating and see it as a valuable tool in your toolbox.\n\n## Where is it used ?\n\nRegEx shows up in many different contexts:\n\n- **Text editors, any programs with a search**. In most text editors, for example Visual Studio Code, you can search for files and inside of files with a RegEx search pattern.\n- **Code**, many programming languages and runtimes have libraries that helps you use RegEx.  \n\n## Your first RegEx\n\nLet's construct a simple RegEx to get a feel for it. Here it is:\n\n```text\nan\n```\n\nif you apply this search pattern `an` to the following text:\n\n```text\nhighlands is a part of Scotland\n```\n\nIt will match like so:\n\n> highl**an**ds is a part of Scotl**an**d\n\nFor simpler cases, where you are looking to see if a specific word matches, in one or more places in a sentence, a pattern like the above is enough.\n\n### RegEx in Go\n\nTo start using RegEx in Go, there's the regexp library. There are two approaches:\n\n- `regexp` directly, here's an example:\n\n   ```go\n   matched, err := regexp.FindString(\"an\", \"highlands is a part of Scotland\")\n   ```\n\n   Here, you get a boolean back that returns true if there's a match.\n\n- **compiled**, in this way, you compile a regular expression and then calls a method on it, like so:\n\n   ```go\n   r, _ := regexp.Compile(\"an\")\n   matches := r.FindAllString(\"highlands is a part of Scotland\", -1)\n   ```\n\n   The above returns a string array with all the matches, in this case `[\"an\", \"an\"]`.\n\n   In this version, you have more functions available.  \n\n## Character classes\n\nCharacter classes are able to distinguish between different types of characters. Different types can be newlines, digits, letters and so on.\n\nLet's have a look at some common types you are likely to encounter:\n\n|Type  |Description  |\n|---------|---------|\n|.     | This type matches any character except for a carriage return        |\n|\\     | This type escapes what's coming next        |\n| \\w | matches any character from the latin alphabet including underscore _ |\n| \\d | matches any digit |\n| \\D | this is the inverse of \\d and matches any character that's not a digit |\n| \\s | matches a white space character like space tab, line feed etc. |\n\nLets show an example:\n\n```go\nmatched, err := regexp.FindString(\"\\d\", \"abc123\")\n```\n\nThere would be a match above due to 123. However, there would be no match against \"abc\" as there's no digits in it.\n\n## Repetition\n\nIf you want to express repetition, there's two characters of interest:\n\n- `+`, matches 1 to many characters.\n\n   ```text\n   \\w+\n   ```\n\n   Given the string \"aaaa bab\" it would match:  \n\n   **aaaaab** **bab** as the above describes matching characters but not the white space.\n\n   ```go\n   r, _ := regexp.Compile(\"\\\\w+\")\n   matches := r.FindAllString(\"aaaa bab\", -1)\n   ```\n\n   Note the extra `\\`, we need that because of the way we construct our Regex.\n\n- `*`, matches 0 to many characters. Lets say you want to match a postal address that starts with \"PA\" and may contain 0 or many numbers. It should then match strings:\n\n   ```text\n   PA\n   PA111 \n   ```\n\n   We can use a `*` to construct this looking like so:\n\n   ```go\n   regexp.MatchString(\"PA*\", \"PA\")\n   regexp.MatchString(\"PA*\", \"PA111\")\n   ```\n\n- `?`, also known as a greedy or optional quantifier. It looks backwards and makes it optional and takes it, if it can. Consider this case:\n\n   ```text\n   http\n   https\n   ```  \n\n   If you want to match them both, you can type:\n\n   ```text\n   https?\n   ```  \n\n   Another example is:\n\n   ```text\n   r, _ := regexp.Compile(\"an.\")\n   matches := r.FindAllString(\"and ant an\", -1)\n   ```\n\n   The above will only match **and** and **ant** but not *an*. If we modify the regex to `an.?` it will match **and ant an**.\n\n## Anchors and boundaries\n\nThere are different anchors you can use like for example:\n\n- `^`, beginning of the string. The following states that the string needs to begin with the following string \"INV\" to signify the start of an invoice row:\n\n   ```text\n   ^INV\n   ```\n\n- `$`, end of the string. An example could be matching a string ends with a certain domain \".com\":\n\n   ```text\n   \\.com$\n   ```\n\n## Groups\n\nGroups are way to capture part of a string and have that returned. It's very useful for parsing out the info you need. Consider this example parsing out the info from a CSV row:\n\n```text\nName: myarticle, Price: 114, Quantity: 3 \n```\n\nTo get the data you need, you want everything after the colon, :. You can construct a RegEx like so:\n\n```go\n\\w+:\\s?(\\w+)\n```\n\nwhat we are doing is defining we want to capture a group using parenthesis `()` but that group should happen after:\n\n- a number of letters, `\\w+`\n- followed by a colon, `:`\n- followed by 0 or 1 space `\\s?`\n- then our group `(\\w+)`, one ore more letters\n\nAll this ends up capturing myarticle, 114 and 3.\n\n## Named groups\n\nA named group is a group you want to capture where the groups have names. Why would you want that? Well, say that you want to break down a URL in pieces and wants to know what's what. Given a URL \"http://myapi.com/products?page=1\", you have:\n\n- `http`, the protocol.\n- `myapi.com`, the domain.\n- `/products`, is the route.\n- `?page=1`, is the query parameters.\n\nSo how can we break it apart and give it a name?\n\nWell, to break it apart, we will use something called named groups, it will allow us to look at our matches and know what's what. So instead of getting:\n\n```text\nhttp\n```\n\nWe will get a key and value that says:\n\n```text\nprotocol: http\n```\n\nSyntax wise, we need to use `?<name of our group>` within our parenthesis ().\n\nYou use the following syntax:\n\n```text\n(?<mygroup>\\w+)\n```\n\nIn Go, we need a `P` right after the question mark, so the code for this would be:\n\n```go\nr, err := regexp.Compile(`(?P<mygroup>\\w+):`)\n```\n\n### Extract the data from a URL\n\nLet's approach this problem then given the string \"http://myapi.com/products?page=1\":\n\n- matching the protocol:\n\n    ```text\n    ^(?<protocol>\\w+):\n    ```\n\n- domain, to match the domain as well, we're looking to capture everything after http:// and until the next /:\n\n   ```text\n   ^(?<protocol>\\w+):\\/\\/(?<domain>\\w+\\.\\w+)\\/?\n   ```\n\n- route, ok so we've matched up \"http://mydomain.com\" so far, now lets match the route, i.e what happens after the / but before any questions marks, ?\n- query params\n\nHere's what our Go code would look like:\n\n```go\nr, err := regexp.Compile(`^(?P<protocol>\\w+):\\/\\/(?P<domain>\\w+\\.\\w+)\\/(?P<route>\\w+)\\/?`)\n```\n\nOk, so we have the pattern, what about printing the parsed parts?\n\nTo pair the named groups with their values, we need to combine values from both the Regex and the response. First, we call `FindStringSubmatch()`, that will give us the values.\n\n```go\nm := r.FindStringSubmatch(\"http://myapi.com/products\")\n```\n\nThen, we need to match the names with these values. We will need to call `r.SubexpNames()` and iterate over the response.\n\n```go\nresult := make(map[string]string)\n for i, name := range r.SubexpNames() {\n  if i != 0 && name != \"\" {\n   result[name] = m[i]\n  }\n }\n```\n\nNote this line where each name is assigned a value:\n\n```go\nresult[name] = m[i]\n```\n\nFinally, to get the values, we can print them out as they are now in a map structure:\n\n```go\nfmt.Println(result[\"protocol\"]) // http\nfmt.Println(result[\"domain\"]) // myapi.com\nfmt.Println(result[\"route\"]) // products\n```\n\n## Assignment - create a Go program that parses a URL\n\nFrom the above use case on named groups, write a Go program that takes a URL and analyzes it. It should work like so:\n\n```output\nType URL: http://myapi.com/products\nThe URL consist of:\nprotocol: http\ndomain: myapi.com\nroute: products\n```\n\n### Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"log\"\n \"regexp\"\n)\n\nfunc main() {\n var url string\n fmt.Println(\"Type URL: \")\n fmt.Scan(&url)\n\n r, err := regexp.Compile(`^(?P<protocol>\\w+):\\/\\/(?P<domain>\\w+\\.\\w+)\\/(?P<route>\\w+)\\/?`)\n if err != nil {\n  log.Fatal(\"Error compiling: \", err)\n }\n m := r.FindStringSubmatch(url)\n if m == nil {\n  panic(\"mo match\")\n }\n result := make(map[string]string)\n for i, name := range r.SubexpNames() {\n  if i != 0 && name != \"\" {\n   result[name] = m[i]\n  }\n }\n fmt.Println(\"The URL consist of:\")\n fmt.Println(result[\"protocol\"])\n fmt.Println(result[\"domain\"])\n fmt.Println(result[\"route\"])\n}\n\n```\n\n## Replacing\n\nA common use case for Regex is when it's used to replace something with something else.\n\nThere's more than one method in Go you could be using but one you could use is `ReplaceAllString()` that sits on the compiled RegEx object:\n\n```go\nr := regexp.MustCompile(`aa`)\n s := r.ReplaceAllString(\"aabbcc\", \"cc\") // s = ccbbcc\n```\n\nThe above replaces all occurrences of `aa` with `cc` on the string `aabbcc`.\n\nYou can also use capture groups and replace a captured group with a string. Here's an example:\n\n```go\nr := regexp.MustCompile(`(\\d)`)\n s := r.ReplaceAllString(\"productid:114\", \"0${1}\") // s = productid:0114\n```\n\nin the above case, we replace 114 with itself but we also prepend it with a 0.\n\n### Use case, replace XML Nodes\n\nImagine you are working with XML for example and want to rename all nodes with a certain name.\n\nHere's your XML\n\n```xml\n<books>\n    <book>\n      <author>Shakespeare</author>\n      <title>Romeo and Juliet</title>\n      <pages>400</pages>\n      <type>paperback</type>\n      <cost>17</cost>\n    </book>\n    <book>\n      <author>Shakespeare</author>\n      <title>Hamlet</title>\n      <pages>270</pages>\n      <type>paperback</type>\n      <cost>15</cost>\n    </book>\n</books>\n```\n\nImagine `title` should be replaced by `name`, how do we do that?\n\nWell, it would be straight forward to replace title by name. Let's say we have this file content though:\n\n```xml\n<books>\n    <book>\n      <author>Shakespeare</author>\n      <title>The title is Romeo and Juliet</title>\n      <pages>400</pages>\n      <type>paperback</type>\n      <cost>17</cost>\n    </book>\n\n</books>\n```\n\nThen we would not only rename the element `title` to `name` but also the content would be replaced o \"The title is Romeo and Juliet\", that's NOT what we want.\n\nWe need to restrict the replace operation to only target element, like so:\n\n```text\n\\<\\/?(title)\\>\n```\n\nThe above would match for example `<title>` and `</title>`. If we try this however on this XML, we almost get what we want:\n\n```xml\n<author>Shakespeare</author>\n```\n\nbecomes\n\n```xml\nnameShakespearename\n```\n\nWhat happened, why did we loose `<>` ? We need a way to express keeping what was there before AND replace the name. A way to do that is to express capture groups on `<>` and the element name, like so:\n\n```text\n(\\<\\/?)(title)(\\>)\n```\n\nNow we have three groups, we need to fit the result together, and this is something we can express like so:\n\n```text\n${1}name${3}\n```\n\n- `${1}` corresponds to capture group matching `<` or `</`\n- `name` is the string we replace `title` with.\n- `{3}` corresponds to capture group matching `>`.\n\n## Assignment - replace content\n\nTake the file *books.xml* containing:\n\n```xml\n<books>\n    <book>\n      <author>Shakespeare</author>\n      <title>Romeo and Juliet</title>\n      <pages>400</pages>\n      <type>paperback</type>\n      <cost>17</cost>\n    </book>\n    <book>\n      <author>Shakespeare</author>\n      <title>Hamlet</title>\n      <pages>270</pages>\n      <type>paperback</type>\n      <cost>15</cost>\n    </book>\n</books>\n```\n\nand replace:\n\n- author with name\n- cost with price\n\nTIP: you might need to apply the replace twice.\n\n## Solution II\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"regexp\"\n)\n\nfunc main() {\n file := `<books>\n    <book>\n      <author>Shakespeare</author>\n      <title>Romeo and Juliet</title>\n      <pages>400</pages>\n      <type>paperback</type>\n      <cost>17</cost>\n    </book>\n    <book>\n      <author>Shakespeare</author>\n      <title>Hamlet</title>\n      <pages>270</pages>\n      <type>paperback</type>\n      <cost>15</cost>\n    </book>\n</books>`\n\n r := regexp.MustCompile(`(\\<\\/?)(title)(\\>)`)\n s := r.ReplaceAllString(file, \"${1}name${3}\")\n fmt.Println(s)\n\n r = regexp.MustCompile(`(\\<\\/?)(cost)(\\>)`)\n s = r.ReplaceAllString(s, \"${1}price${3}\")\n fmt.Println(s)\n}\n```\n"
  },
  {
    "path": "05-misc/03-regex/regex.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"regexp\"\n)\n\nfunc main() {\n\tvar url string\n\tfmt.Println(\"Type URL: \")\n\tfmt.Scan(&url)\n\t//\n\t// \"^([a-z]*\\\\.)+[a-z]*@\n\tr, err := regexp.Compile(`^(?P<protocol>\\w+):\\/\\/(?P<domain>\\w+\\.\\w+)\\/(?P<route>\\w+)\\/?`)\n\tif err != nil {\n\t\tlog.Fatal(\"Error compiling: \", err)\n\t}\n\tm := r.FindStringSubmatch(url)\n\tif m == nil {\n\t\tpanic(\"mo match\")\n\t}\n\tresult := make(map[string]string)\n\tfor i, name := range r.SubexpNames() {\n\t\tif i != 0 && name != \"\" {\n\t\t\tresult[name] = m[i]\n\t\t}\n\t}\n\tfmt.Println(\"The URL consist of:\")\n\tfmt.Println(result[\"protocol\"])\n\tfmt.Println(result[\"domain\"])\n\tfmt.Println(result[\"route\"])\n}\n"
  },
  {
    "path": "05-misc/03-regex/regex2.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n)\n\nfunc main() {\n\tfile := `<books>\n    <book>\n      <author>Shakespeare</author>\n      <title>Romeo and Juliet</title>\n      <pages>400</pages>\n      <type>paperback</type>\n      <cost>17</cost>\n    </book>\n    <book>\n      <author>Shakespeare</author>\n      <title>Hamlet</title>\n      <pages>270</pages>\n      <type>paperback</type>\n      <cost>15</cost>\n    </book>\n</books>`\n\n\tr := regexp.MustCompile(`(\\<\\/?)(title)(\\>)`)\n\ts := r.ReplaceAllString(file, \"${1}name${3}\")\n\tfmt.Println(s)\n\n\tr = regexp.MustCompile(`(\\<\\/?)(cost)(\\>)`)\n\ts = r.ReplaceAllString(s, \"${1}price${3}\")\n\tfmt.Println(s)\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/README.md",
    "content": "# Goroutines and channels\n\nA goroutine is a lightweight thread managed by the Go runtime.\n\nChannels is how you communicate between routines.\n\n## Introduction\n\nIn this chapter you will:\n\n- Understand the difference between concurrency and parallelism\n- Use Goroutines to run your functions\n- Create and use channels to communicate between your Goroutines\n- Apply Goroutines to an app that searches files for faster execution.\n\n## Concurrency, what's the benefit\n\nConcurrency is the task of running and managing the multiple computations at the same time. While *parallelism* is the task of running multiple computations simultaneously.\n\nSo what are some benefits:\n\n- **Faster processing**. The benefit is getting tasks done faster. Imagine that you are searching a computer for files, or processing data, if it's possible to work on these workloads in parallel, you end up getting the response back faster.\n- **Responsive apps** Another benefit is getting more responsive apps. If you have an app with a UI, imagine it would be great if you can perform some background work without interrupting the responsiveness of the UI.\n\n## Goroutines\n\nA goroutine is a lightweight thread managed by the Go runtime. What you do is to add the keyword `go` in front of a function. Here's an example:\n\n```go\ngo myFunction()\n```\n\nImagine the following code running, what would happen?\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc myFunction() {\n for i := 0; i < 3; i++ {\n  fmt.Println(\"my function: \", i)\n }\n}\nfunc anotherFunction() {\n for i := 4; i <7; i++ {\n  fmt.Println(\"another function: \", i)\n }\n}\n\nfunc main() {\n go myFunction()\n anotherFunction()\n}\n```\n\nIt would only print the result from `anotherFunction()` as it takes a short while for the go routine to start up. You can have the go routine execute as well by adding a little delay, like so:\n\n```go\nfunc main() {\n go myFunction()\n anotherFunction()\n time.Sleep(1 * time.Second)\n}\n```\n\nThe result is now the following:\n\n```output\nanother function:  4\nanother function:  5\nanother function:  6\nmy function:  0\nmy function:  1\nmy function:  2\n```\n\nThe function with the go routine finishes last. Lets modify the code slightly and have the two functions use a delay, so we simulate workloads taking different time to finish:\n\n```go\nfunc myFunction() {\n time.Sleep(1500 * time.Millisecond)\n for i := 0; i < 3; i++ {\n  fmt.Println(\"my function: \", i)\n }\n}\nfunc anotherFunction() {\n time.Sleep(500 * time.Millisecond)\n for i := 4; i < 7; i++ {\n  fmt.Println(\"another function: \", i)\n }\n}\n\nfunc main() {\n go myFunction()\n go anotherFunction()\n time.Sleep(2 * time.Second)\n}\n```\n\nat this point, `anotherFunction()` finishes first as it has the shortest delay, which is to be expected. Here's what the output looks like now:\n\n```output\nanother function:  4\nanother function:  5\nanother function:  6\nmy function:  0\nmy function:  1\nmy function:  2\n```\n\n### Use case - a file search\n\nImagine you have case where you need to find a file on disk. If you write a function like so, it will search a directory and report back the result if the file is found:\n\n```go\nfunc SearchFiles(dir string, lookFor string) string {\n log.Println(\"[SEARCHING] \", dir)\n files, err := ioutil.ReadDir(dir)\n if err != nil {\n  log.Fatal(err)\n }\n\n for _, file := range files {\n  log.Println(dir+file.Name(), file.IsDir())\n  if file.Name() == lookFor {\n   return \"[FOUND] \" + filepath.Join(dir, file.Name())\n  }\n }\n return \"[NOT FOUND] \" + dir\n}\n```\n\nImagine you now run this code like so, to search many directories:\n\n```go\nresult := make([]string, 0)\nappend(result, SearchFile(\"./tmp\", \"myfile.txt\"))\nappend(result, SearchFile(\"./tmp2\", \"myfile.txt\"))\nappend(result, SearchFile(\"./tmp3\", \"myfile.txt\"))\nappend(result, SearchFile(\"./tmp4\", \"myfile.txt\"))\n\nfor i := 0 i< len(result); i++ {\n  fmt.Println(result[i])\n}\n```\n\nIf found, you will get an output similar to the below, depending on whether *myfile.txt* is found in any of the searched directories:\n\n```go\n[FOUND] ./tmp/myfile.txt\n[NOT FOUND] ./tmp2/myfile.txt\n[NOT FOUND] ./tmp3/myfile.txt\n[NOT FOUND] ./tmp4/myfile.txt\n```\n\nNow to speed up this process, it would be great if you are able to search many directories at once, so you could type something like so:\n\n```go\ngo SearchFile(\"./tmp\", \"myfile.txt\")\ngo SearchFile(\"./tmp2\", \"myfile.txt\")\ngo SearchFile(\"./tmp3\", \"myfile.txt\")\ngo SearchFile(\"./tmp4\", \"myfile.txt\")\n```\n\nThis works, it now searches all directories, in parallel. However, now we don't have a way to get the response back as we can't write like so:\n\n```go\nresult := make([]string, 0)\ngo append(result,SearchFile(\"./tmp\", \"myfile.txt\")) // won't compile, says \"go discards results\"\n```\n\nSo how can we get the result from a go routine, the answer is by using channels, so lets discuss those next.\n\n## Channels\n\nA channel is how we can communicate cross go routines but also between go routines and the part of our code not using a go routine.\n\nThe idea is to send a value to a channel, and have part of our code listen to values from a channel.\n\n### Creating a channel\n\nTo create a channel, you need the keyword `chan` and the data type of the messages you are about to send into it. Here's an example:\n\n```go\nch := make(chan int)\n```\n\nIn the above example, a channel `ch` will be created that accepts messages of type `int`. \n\n### Sending a value to a channel\n\nTo send to a channel, you need to use this operator `<-`, it look like a left pointing arrow and is meant to be read as the direction something is sent. Here's an example of sending a message to a channel:\n\n```go\nch <- 2\n```\n\nIn the above code, the number 2 is sent into the channel `ch`.\n\n### Listening to a channel\n\nTo listen to a channel, you again use the arrow `<-`, but this time you need a receiving variable on the left side and the channel on the right side, like so:\n\n```go\nvalue := <- ch\n```\n\n### Matching sending and receiving\n\nLet's say you have the following code:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc produceResults(ch chan int) {\n ch <- 1\n ch <- 2\n}\n\nfunc main() {\n ch := make(chan int)\n go produceResults(ch)\n\n var result int\n result = <-ch\n fmt.Println(result)\n result = <-ch\n fmt.Println(result)\n}\n```\n\nYou are invoking `produceResults()` and it sends messages to the channel twice:\n\n```go\nch <- 1\nch <- 2\n```\n\nin `main()`, you receive the results:\n\n```go\nvar result int\nresult = <-ch\nfmt.Println(result)\nresult = <-ch\nfmt.Println(result)\n```\n\nSo what happens if you produce more values than you receive like so?\n\n```go\nch <- 1\nch <- 2\nch <- 3\n```\n\nanswer: you will miss out on the extra value.\n\nWhat if it's the opposite, you try to receive one more value than you actually get?\n\n```go\nvar result int\nresult = <-ch\nfmt.Println(result)\nresult = <-ch\nfmt.Println(result)\nresult = <-ch\nfmt.Println(result)\n```\n\nAt this point, your code will deadlock, like so: **fatal error: all goroutines are asleep - deadlock!**. Your code will never finish as that value will never arrive. \n\nThe lesson here is that you need to keep track of how many results you might get and only try to receive that many. \n\nThere's another way to receive values, and that's by using a `select` like so:\n\n```go\nfor i := 0; i < 2; i++ {\n  select {\n  case x, ok := <-ch:\n   if ok {\n    fmt.Println(x)\n   }\n  }\n }\n```\n\nThe idea is to *match* the receiving of a value like so:\n\n```go\ncase x, ok := <-ch:\n```\n\nWhat you are getting is two things, the value itself `x` and `bool` we name `ok`. If we managed to get a value ok, then `ok` holds the value `true`. What happens if it's not ok then? It would be `false` if the channel is closed and can no longer produce any more values, so lets discuss that next.\n\n### Closing a channel\n\nA channel is open until you close it. You can actively close it by calling `close()` with the channel as an input parameter:\n\n```go\nclose(ch)\n```\n\nHowever, when we close a channel, we need to test for it. If we attempt to receive a value from a closed channel, it will cause a crash. To test whether the channel is open or not, we can use the `select` we just wrote:\n\n```go\n  select {\n  case x, ok := <-ch:\n   if ok {\n    fmt.Println(x)\n   } else {\n     break // channel is closed\n   }\n  }\n``` \n\nThe value of `ok` is now false.\n\nTo apply the concept of closing a channel, we add `close()` to `produceResults()` and we have our for loop run one more time than there's values, like so:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n)\n\nfunc produceResults(ch chan int) {\n ch <- 1\n ch <- 2\n // ch <- 3\n close(ch)\n}\n\nfunc main() {\n ch := make(chan int)\n go produceResults(ch)\n // time.Sleep(1 * time.Second)\n\n for i := 0; i < 3; i++ {\n  select {\n  case x, ok := <-ch:\n   if ok {\n    fmt.Println(x)\n   } else {\n    fmt.Println(\"channel closed\")\n   }\n  }\n }\n}\n```\n\nThe output of running said code is:\n\n```output\n1\n2\nchannel closed\n```\n\nWe can see how the `else` clause is matched on the third iteration. \n\nNow, we might have more long running tasks, at which point we need to sit and wait until the channel tells us it closed. Here's code to handle that:\n\n```go\nlabel:\n for {\n  select {\n  case x, ok := <-ch:\n   if ok {\n    fmt.Println(x)\n   } else {\n    fmt.Println(\"channel closed\")\n    break label\n   }\n  }\n }\n```\n\nWhat's happening here is that we set up a for loop that runs forever, until closed. To ensure we break out of the for loop and not just the `select`, we add `label:`\n\nTODO, you can use range over the channel as well.\n\n## Assignment - `SearchFiles()` with channels\n\nLet's take all our learning and add channels to the program we wrote containing a file searcher. \n\n## Challenge\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"io/ioutil\"\n \"log\"\n \"path/filepath\"\n)\n\nfunc SearchFiles(dir string, lookFor string, ch chan string) {\n log.Println(\"[SEARCHING] \", dir)\n files, err := ioutil.ReadDir(dir)\n if err != nil {\n  log.Fatal(err)\n }\n\n for _, file := range files {\n  log.Println(dir+file.Name(), file.IsDir())\n  if file.Name() == lookFor {\n   ch <- \"[FOUND] \" + filepath.Join(dir, file.Name())\n   return\n  }\n }\n ch <- \"[NOT FOUND] \" + dir\n}\n\nfunc main() {\n ch := make(chan string)\n\n go SearchFiles(\"./test/\", \"test2.txt\", ch)\n go SearchFiles(\"./other/\", \"test2.txt\", ch)\n\n var res = \"\"\n for i := 0; i < 2; i++ {\n  res = <-ch\n  log.Println(res)\n }\n}\n```"
  },
  {
    "path": "05-misc/04-goroutines/channel.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc run(ch chan int, no int) {\n\tch <- no\n}\n\nfunc main() {\n\tch := make(chan int)\n\n\tgo run(ch, 1)\n\tgo run(ch, 2)\n\ttime.Sleep(1 * time.Second)\n\nblock:\n\tfor {\n\t\tselect {\n\t\tcase x, ok := <-ch:\n\t\t\tif ok {\n\t\t\t\tfmt.Println(x)\n\t\t\t} else {\n\t\t\t\tfmt.Println(\"channel closed\")\n\n\t\t\t\tbreak block\n\t\t\t}\n\t\tdefault:\n\t\t\tfmt.Println(\"No value to read, exiting\")\n\n\t\t\tbreak block\n\t\t}\n\t}\n\tfmt.Println(\"Done with values\")\n\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/channel1.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc produceResults(ch chan int) {\n\t// time.Sleep(2 * time.Second)\n\tch <- 1\n\tch <- 2\n\t// ch <- 3\n\tclose(ch)\n}\n\nfunc main() {\n\tch := make(chan int)\n\tgo produceResults(ch)\n\t// time.Sleep(1 * time.Second)\n\n\t// \tfor i := 0; i < 3; i++ {\n\t// \t\tselect {\n\t// \t\tcase x, ok := <-ch:\n\t// \t\t\tif ok {\n\t// \t\t\t\tfmt.Println(x)\n\t// \t\t\t} else {\n\t// \t\t\t\tfmt.Println(\"channel closed\")\n\t// \t\t\t}\n\t// \t\t}\n\t// \t}\n\t// }\n\nlabel:\n\tfor {\n\t\tselect {\n\t\tcase x, ok := <-ch:\n\t\t\tif ok {\n\t\t\t\tfmt.Println(x)\n\t\t\t} else {\n\t\t\t\tfmt.Println(\"channel closed\")\n\t\t\t\tbreak label\n\t\t\t}\n\t\t\t// default:\n\t\t\t// fmt.Println(\"nothing\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/file-search.go",
    "content": "package main\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"path/filepath\"\n)\n\nfunc SearchFiles(dir string, lookFor string) string {\n\tlog.Println(\"[SEARCHING] \", dir)\n\tfiles, err := ioutil.ReadDir(dir)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfor _, file := range files {\n\t\tlog.Println(dir+file.Name(), file.IsDir())\n\t\tif file.Name() == lookFor {\n\t\t\treturn \"[FOUND] \" + filepath.Join(dir, file.Name())\n\t\t}\n\t}\n\treturn \"[NOT FOUND] \" + dir\n}\n\nfunc main() {\n\tresult := make([]string, 0)\n\tgo append(result, SearchFiles(\"./test\", \"test2.txt\"))\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/first.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc myFunction() {\n\ttime.Sleep(1500 * time.Millisecond)\n\tfor i := 0; i < 3; i++ {\n\t\tfmt.Println(\"my function: \", i)\n\t}\n}\nfunc anotherFunction() {\n\ttime.Sleep(500 * time.Millisecond)\n\tfor i := 4; i < 7; i++ {\n\t\tfmt.Println(\"another function: \", i)\n\t}\n}\n\nfunc main() {\n\tgo myFunction()\n\tgo anotherFunction()\n\ttime.Sleep(2 * time.Second)\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/main.go",
    "content": "package main\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"path/filepath\"\n)\n\nfunc SearchFiles(dir string, lookFor string, ch chan string) {\n\tlog.Println(\"[SEARCHING] \", dir)\n\tfiles, err := ioutil.ReadDir(dir)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfor _, file := range files {\n\t\tlog.Println(dir+file.Name(), file.IsDir())\n\t\tif file.Name() == lookFor {\n\t\t\tch <- \"[FOUND] \" + filepath.Join(dir, file.Name())\n\t\t\treturn\n\t\t}\n\t}\n\tch <- \"[NOT FOUND] \" + dir\n}\n\nfunc main() {\n\tch := make(chan string)\n\n\tgo SearchFiles(\"./test/\", \"test2.txt\", ch)\n\tgo SearchFiles(\"./other/\", \"test2.txt\", ch)\n\n\tvar res = \"\"\n\tfor i := 0; i < 2; i++ {\n\t\tres = <-ch\n\t\tlog.Println(res)\n\t}\n}\n"
  },
  {
    "path": "05-misc/04-goroutines/other/test.txt",
    "content": ""
  },
  {
    "path": "05-misc/04-goroutines/other/test3.txt",
    "content": ""
  },
  {
    "path": "05-misc/04-goroutines/test/test.txt",
    "content": "dfdf"
  },
  {
    "path": "05-misc/04-goroutines/test/test2.txt",
    "content": ""
  },
  {
    "path": "05-misc/05-sqlite/README.md",
    "content": "# Working with a database\n\nYou will be working with a sqlite database and read and write values to it.\n\n## Introduction\n\nIn this chapter you will:\n\n- Create a database and its structure.\n- Write to the database.\n- Read from the database.\n\n## Select a sqlite driver\n\nTo connect with a sqlite database we've got a few libraries to choose from. These libraries will provide you with a sqlite driver that you need to successfully connect with your database. Here are some common ones:\n\n- SQLite (uses cgo): <https://github.com/mattn/go-sqlite3> [*]\n- SQLite (uses cgo): <https://github.com/gwenn/gosqlite> - Supports SQLite dynamic data typing\n- SQLite (uses cgo): <https://github.com/mxk/go-sqlite>\n- SQLite: (uses cgo): <https://github.com/rsc/sqlite>\n- SQLite: (pure go): <https://modernc.org/sqlite>\n\nRefer to this link to see libraries for other databases:\n\n- <https://github.com/golang/go/wiki/SQLDrivers>\n.\n\n## Use `sqlite3` from the console\n\nTo work with your database, it's beneficial to use sqlite from the command line. Consult the official [downloads page](https://www.sqlite.org/download.html) for sqlite and ensure you pick the executable for your operating system.  Installing sqlite will give you an executable.\n\nWith the executable, you can:\n\n- Create a database.\n- Run SQL commands.\n- Run other commands supported by the executable.\n\n### Create a database\n\nTo create a database, you give it the name of the database like so:\n\n```console\nsqlite3 activities.db\n```\n\nThe preceding command will give you a database in a file called \"activities.db\"\n\n> It will also start up a shell where you can execute SQL commands as well as commands supported by sqlite3.\n\n### Run SQL commands\n\nRun a SQL command in the shell by typing SQL and end it by a semicolon, `;`.\n\n```sql\nCREATE TABLE `person` (\n        `uid` INTEGER PRIMARY KEY AUTOINCREMENT,\n        `name` VARCHAR(64) NULL,\n        `lastname` VARCHAR(64) NULL,\n        `created` DATE NULL\n    );\n```\n\n### Exit the shell\n\nAfter you're done, you can exit the shell by typing `.exit`:\n\n```console\n.exit\n```\n\n## Talking to your database via Go\n\nTo talk to your database via Go, there's some steps you need to take in order:\n\n1. **Create a project**. You need to create a project so you can import a Go package containing your sqlite driver. Create a project by running `go mod init`. Below is an example:\n\n   ```console\n   go mod init \"example-project\"\n   ```\n\n1. **Add imports**. Once you have the needed packages you need to refer to them in the import section:\n\n   ```go\n   import (\n     \"database/sql\"\n     _ \"github.com/mattn/go-sqlite3\"\n    )\n   ```\n\n   Above, are the two packages we will use, \"database/sql\" that provides an interface for us to run queries and statements. \"github.com/mattn/go-sqlite3\" contains the driver that will enable us connecting to the database.\n\n1. **Establish connection**. To connect with the database, you call the `Open()` function on the `sql` instance like so:\n\n   ```go\n   db, err := sql.Open(\"sqlite3\", \"./mydb.db\")\n   ```\n\n   In the preceding command, we specify first the type of database and in the second parameter the name of the database and where it's located. We get a database instance back of type `*sql.DB`.\n\n1. **Run queries**. At this point, we are free to run queries. You use `Query()` function and give it a SQL statement like in this example:\n\n   ```go\n   rows, err := db.Query(\"SELECT * FROM person\")   \n   ```\n\n   To iterate over the results, you can use a for-loop like so:\n\n   ```go\n   for rows.Next() {\n      var uid int\n      var name string\n      var lastname string\n      var created time.Time\n      err = rows.Scan(&uid, &name, &lastname, &created)\n   }\n   ```\n\n1. **Run prepared statements**. Prepared statements are SQL statements where we can provide parameter values at a later point. You call the `Prepare()` function with `?` as placeholders where there will be data inserted:\n\n   ```go\n   stmt, err := db.Prepare(\"UPDATE person set lastname=? where uid=?\")\n   ```\n\n   To run the statement against the database, you can call `Exec()`:\n\n   ```go\n   res, err := stmt.Exec(\"smith\", 1)\n   ```\n\n   The `res` instance coming back has a function `RowsAffected()` that returns the number of affected rows:\n\n   ```go\n   affected, _ := res.RowsAffected()\n   ```\n\n   Getting affected rows is a good indicator that you actually changed something.\n\n1. Close the database connection. You should close the database when you're done with it like so:\n\n   ```go\n   db.Close()\n   ```\n\n## Assignment\n\nIn this assignment, we will create a Go program that's able to write and write to the database. We will go all the way from creating the database with the console to writing the Go code needed.\n\n### Create the database and populate it\n\nWe will create our database using the sqlite executable in the console.\n\n1. Run `sqlite` to create the database and initialize the sqlite shell:\n\n    ```console\n    sqlite3 mydb.db\n    sqlite3SQLite version 3.32.3 2020-06-18 14:16:19\n    Enter \".help\" for usage hints.\n    ```\n\n    At this point, you have a database created. Next, we need some tables in there.\n\n1. Run the following SQL command in the sqlite shell:\n\n   ```sql\n   CREATE TABLE `person` (\n            `uid` INTEGER PRIMARY KEY AUTOINCREMENT,\n            `name` VARCHAR(64) NULL,\n            `lastname` VARCHAR(64) NULL,\n            `created` DATE NULL\n        );\n   ```\n\n   You know have the table \"person\" created. Next, we need some data in the table that we will interact with later in our Go code.\n\n1. Run this SQL command to insert data into \"person\" table:\n\n   ```sql\n    insert into person(name,lastname, created) values (\"joe\", \"schmoo\", '2021-01-01');\n    ```\n\n    Great, we now have data in our table. Time to focus on the Go code next.\n\n1. Run `.exit` to exit the database.\n\n### Create a project\n\nNow we will create a Go project and some code able to access our database.\n\n1. Create *db.go* and give it this content:\n\n    ```go\n    package main\n    \n    import (\n     \"database/sql\"\n     \"fmt\"\n     \"log\"\n     _ \"github.com/mattn/go-sqlite3\"\n    )\n    \n    func main() {\n     db, err := sql.Open(\"sqlite3\", \"./mydb.db\")\n     if err != nil {\n      log.Fatal(err)\n     }\n     fmt.Println(\"database open\")\n    \n     fmt.Println(\"bye\")\n    \n     fmt.Println(\"closing db\")\n     db.Close()\n    \n    }\n    ```\n\n    Next, lets initialize our Go project.\n\n1. Run the following commands to create our project:\n\n   ```console\n   go mod init sql-demo\n   ```\n\n1. Run `go mo tidy`, to install the needed packages you specified in the import section of your program (this will download and add \"github.com/mattn/go-sqlite3\" to your project):\n\n   ```console\n   go mod tidy\n   ```\n\n### Read data\n\nNext, we will add a function capable of reading data.\n\n1. Add a function `Read()` like so:\n\n   ```go\n   func Read(db *sql.DB) {\n     rows, err := db.Query(\"SELECT * FROM person\")\n     \n    }\n   ```\n\n   At this point, we have read the response into `rows`. Next, we need iterate on the response.\n\n1. Add the following code, in `Read()` to iterate over the response:\n\n   ```go\n   for rows.Next() {\n      var uid int\n      var name string\n      var lastname string\n      var created time.Time\n      err = rows.Scan(&uid, &name, &lastname, &created)\n      if err != nil {\n       log.Fatal(err)\n      }\n      fmt.Println(uid)\n      fmt.Println(name)\n      fmt.Println(lastname)\n      fmt.Println(created)\n   }\n   ```\n\n   Not the usage of `Scan()` and variables being sent in as references so the response is written to them.\n\n### Create data\n\nNow we will create code that will allow us to create data in our database.\n\n1. Add a function `Read()`:\n\n   ```go\n   func Create(db *sql.DB) {\n     stmt, err := db.Prepare(\"INSERT INTO person(name, lastname, created) values(?,?,?)\")\n     \n   }\n   ```\n\n   At this point, you have created a statement that when executed will attempt to insert row. Note the use of `?`, these are placeholders that you will need to provide values to at the moment of execution.\n\n1. Add the following code to `Create()`:\n\n   ```go\n   if err != nil {\n      log.Fatal(err)\n     }\n     res, err := stmt.Exec(\"Mrs\", \"Smith\", \"2022-01-01\")\n     if err != nil {\n      log.Fatal(err)\n     }\n     affected, _ := res.RowsAffected()\n     log.Printf(\"Affected rows %d\", affected)\n   ```\n\n   Note the call to `Exec()`, here you are providing  data and `?` is being replaced by the values you send in. Also note the last two rows:\n\n   ```go\n   affected, _ := res.RowsAffected()\n   log.Printf(\"Affected rows %d\", affected)\n   ```\n\n   Here for result `res` we are invoking `RowsAffected()` that returns the number of affected rows then we go on to print said value.\n\n### Update and delete data\n\nUpdating and deleting data takes on very similar approach to how to create data. You will use a statement that you prepare and then send in the real values. Below is the code for performing both these actions:\n\n**Update**\n\n```go\nfunc Update(db *sql.DB) {\n stmt, err := db.Prepare(\"UPDATE person set lastname=? where uid=?\")\n if err != nil {\n  log.Fatal(err)\n }\n res, err := stmt.Exec(\"smith\", 1)\n if err != nil {\n  log.Fatal(err)\n }\n affected, _ := res.RowsAffected()\n log.Printf(\"Affected rows %d\", affected)\n}\n```\n\n**Delete**\n\n```go\nfunc Delete(db *sql.DB) {\n stmt, err := db.Prepare(\"delete from person where uid=?\")\n if err != nil {\n  log.Fatal(err)\n }\n res, err := stmt.Exec(1)\n if err != nil {\n  log.Fatal(err)\n }\n affected, _ := res.RowsAffected()\n log.Printf(\"Affected rows %d\", affected)\n}\n```\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"database/sql\"\n \"fmt\"\n \"log\"\n \"time\"\n\n _ \"github.com/mattn/go-sqlite3\"\n)\n\nfunc Read(db *sql.DB) {\n rows, err := db.Query(\"SELECT * FROM person\")\n if err != nil {\n  log.Fatal(err)\n }\n for rows.Next() {\n  var uid int\n  var name string\n  var lastname string\n  var created time.Time\n  err = rows.Scan(&uid, &name, &lastname, &created)\n  if err != nil {\n   log.Fatal(err)\n  }\n  fmt.Println(uid)\n  fmt.Println(name)\n  fmt.Println(lastname)\n  fmt.Println(created)\n }\n}\n\nfunc Update(db *sql.DB) {\n stmt, err := db.Prepare(\"UPDATE person set lastname=? where uid=?\")\n if err != nil {\n  log.Fatal(err)\n }\n res, err := stmt.Exec(\"smith\", 1)\n if err != nil {\n  log.Fatal(err)\n }\n affected, _ := res.RowsAffected()\n log.Printf(\"Affected rows %d\", affected)\n}\n\nfunc Create(db *sql.DB) {\n stmt, err := db.Prepare(\"INSERT INTO person(name, lastname, created) values(?,?,?)\")\n if err != nil {\n  log.Fatal(err)\n }\n res, err := stmt.Exec(\"Mrs\", \"Smith\", \"2022-01-01\")\n if err != nil {\n  log.Fatal(err)\n }\n affected, _ := res.RowsAffected()\n log.Printf(\"Affected rows %d\", affected)\n}\n\nfunc Delete(db *sql.DB) {\n stmt, err := db.Prepare(\"delete from person where uid=?\")\n if err != nil {\n  log.Fatal(err)\n }\n res, err := stmt.Exec(1)\n if err != nil {\n  log.Fatal(err)\n }\n affected, _ := res.RowsAffected()\n log.Printf(\"Affected rows %d\", affected)\n}\n\nfunc main() {\n db, err := sql.Open(\"sqlite3\", \"./mydb.db\")\n if err != nil {\n  log.Fatal(err)\n }\n fmt.Println(\"database open\")\n Create(db)\n Read(db)\n // Update(db)\n\n fmt.Println(\"bye\")\n\n fmt.Println(\"closing db\")\n db.Close()\n\n}\n```\n"
  },
  {
    "path": "05-misc/05-sqlite/go.mod",
    "content": "module db-project\n\ngo 1.16\n\nrequire github.com/mattn/go-sqlite3 v1.14.12\n"
  },
  {
    "path": "05-misc/05-sqlite/go.sum",
    "content": "github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=\ngithub.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=\n"
  },
  {
    "path": "05-misc/05-sqlite/main.go",
    "content": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t_ \"github.com/mattn/go-sqlite3\"\n)\n\nfunc Read(db *sql.DB) {\n\trows, err := db.Query(\"SELECT * FROM person\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfor rows.Next() {\n\t\tvar uid int\n\t\tvar name string\n\t\tvar lastname string\n\t\tvar created time.Time\n\t\terr = rows.Scan(&uid, &name, &lastname, &created)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Println(uid)\n\t\tfmt.Println(name)\n\t\tfmt.Println(lastname)\n\t\tfmt.Println(created)\n\t}\n}\n\nfunc Update(db *sql.DB) {\n\tstmt, err := db.Prepare(\"UPDATE person set lastname=? where uid=?\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tres, err := stmt.Exec(\"smith\", 1)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\taffected, _ := res.RowsAffected()\n\tlog.Printf(\"Affected rows %d\", affected)\n}\n\nfunc Create(db *sql.DB) {\n\tstmt, err := db.Prepare(\"INSERT INTO person(name, lastname, created) values(?,?,?)\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tres, err := stmt.Exec(\"Mrs\", \"Smith\", \"2022-01-01\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\taffected, _ := res.RowsAffected()\n\tlog.Printf(\"Affected rows %d\", affected)\n}\n\nfunc Delete(db *sql.DB) {\n\tstmt, err := db.Prepare(\"delete from person where uid=?\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tres, err := stmt.Exec(1)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\taffected, _ := res.RowsAffected()\n\tlog.Printf(\"Affected rows %d\", affected)\n}\n\nfunc main() {\n\tdb, err := sql.Open(\"sqlite3\", \"./mydb.db\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(\"database open\")\n\tCreate(db)\n\tRead(db)\n\t// Update(db)\n\n\tfmt.Println(\"bye\")\n\n\tfmt.Println(\"closing db\")\n\tdb.Close()\n\n}\n"
  },
  {
    "path": "06-io/01-read-write-files/README.md",
    "content": "# Read and write to files\n\nThere are different types of files, text files, files containing images, videos etc. For that reason you might want to read the content differently, either byte by byte or maybe even the entire file in one go, as text.\n\n## Introduction\n\nIn this chapter you will learn to:\n\n- Read content from text files.\n- Write to text files.\n- Append text at the end of a text file.\n- Analyze a file for its metadata like size, modified date and more.\n\n## Read a text file\n\nOne approach could be using the `ioutil` library and its `ReadFile()` method like so:\n\n```go\n  import (\n    \"io/ioutil\"\n    \"log\"\n  )\n  func main() {\n    filebuffer, err := ioutil.ReadFile(path)\n \n    if err != nil {\n      log.Fatal(err)\n    }\n    var inputdata string = string(filebuffer) \n  }\n```\n\nNote how the result of reading the file ends up in `filebuffer`. To interpret it as a string, you need to convert it via `string(filebuffer)`. Now, you're ready to process the file content, read it line by line or whatever you want to do.\n\n## Write text to a file\n\nIn this scenario, we are looking to do two things:\n\n- Create a file.\n- Write text to our newly created file.\n\nFor this scenario, we can use the `os` library and a combination of the `Create()` method, to create a file and the `WriteString()` method to write a string to the file.\n\n```go\n import (\n  \"os\"\n  \"log\"\n ) \n\n f, err := os.Create(path)\n if err != nil {\n  log.Fatal(err)\n }\n\n n, err := f.WriteString(content + \"\\n\")\n if err != nil {\n  log.Fatal(err)\n }\n fmt.Printf(\"wrote %d bytes\\n\", n)\n f.Sync()\n```\n\nFirst the file is created calling `Create()`. From that, we get a file handle `f`. With `f`, we can call `WriteString()` with a string. Lastly, we call `Sync()` to ensure the string is persisted in the file.\n\n## Append to a file\n\nAppending text, implies you already have an existing file. When you append, you information to the end of the file. Appending is something you are likely to do when you add new entries to a log file or adding a new purchase to a Point of Sale, POS system in a grocery store for example.\n\nTo append to a file you use the `OpenFile()` method in the `os` lib. What you need to do is to pass it some flags that states that you want to append content. You should also have a behavior that says, create if it doesn't already exist. You end up with code looking like so:\n\n```go\nf, err := os.OpenFile(\"text.log\",\n os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\nif err != nil {\n log.Println(err)\n}\ndefer f.Close()\n```\n\nThe 0644, is a 3x3 bit flag. It sets permissing for User (6, Read/Write), Group (4, Read), and Other (4, Read).\n\nTo append a string, you can call `WriteString()` like so:\n\n```go\nf.WriteString(\"my text \\n\")\n```\n\n## Assignment\n\nImagine you have a file *invoices.csv* looking like so:\n\n```text\ncustomer, amount, date\nWood LTD, 100, 2020-01-01\nMetal, 345, 2020-01-29\nSteel, 700, 2020-07-29\n```\n\nOpen up and read the file content, line by line.\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"io/ioutil\"\n \"log\"\n \"strings\"\n)\n\nfunc main() {\n var path = \"invoices.csv\"\n filebuffer, err := ioutil.ReadFile(path)\n\n if err != nil {\n  log.Fatal(err)\n }\n var inputdata string = string(filebuffer)\n\n rows := strings.Split(inputdata, \"\\n\")\n for _, row := range rows {\n  fmt.Println(\"row:\", row)\n }\n}\n\n```\n\n## Challenge\n\nSee if you can split up each row further in columns and summarize how much the orders are worth in total."
  },
  {
    "path": "06-io/01-read-write-files/invoices.csv",
    "content": "customer, amount, date\nWood LTD, 100, 2020-01-01\nMetal, 345, 2020-01-29\nSteel, 700, 2020-07-29"
  },
  {
    "path": "06-io/01-read-write-files/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"strings\"\n)\n\nfunc main() {\n\tvar path = \"invoices.csv\"\n\tfilebuffer, err := ioutil.ReadFile(path)\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tvar inputdata string = string(filebuffer)\n\n\trows := strings.Split(inputdata, \"\\n\")\n\tfor _, row := range rows {\n\t\tfmt.Println(\"row:\", row)\n\t}\n}\n"
  },
  {
    "path": "06-io/02-file-directories/README.md",
    "content": "# Perform operations on files and directories\n\nThings you likely want to do to files and directories are moving them about, removing them, rename them etc. In short, high-level operations that is less about the content of the file but doing something with it.\n\n## Introduction\n\nIn this chapter you will:\n\n- Analyze a file for its metadata like size, modified date and more.\n- Copy files from one location to the next.\n- Rename files.\n- Remove files.\n- Create and read directories.\n\n## File information\n\nYou might want to look at a specific file and find out various details about it. Things that can be interesting are:\n\n- **Name**, maybe youu started from a path looking at a list of file. Getting the filename can be valuable.\n- **Size**. Getting the size of disc can be good to know.\n- **Permission**. To know what permissions you have tells you want you are able to do with the file, like running it, writing to it and so on.\n- **Last modified**. You might have a query looking for newly updated files only. Inspecting the modified date is what you want.\n- **Is a directory**. Files and directories are ultimately just files. There's a flag distinguishing a file from a directory.\n\nTo get file information, use the `Stat()` function like so:\n\n```go\nfileStat, err := os.Stat(path)\nfmt.Println(\"File Name:\", fileStat.Name())        // Base name of the file\nfmt.Println(\"Size:\", fileStat.Size())             // Length in bytes for regular files\nfmt.Println(\"Permissions:\", fileStat.Mode())      // File mode bits\nfmt.Println(\"Last Modified:\", fileStat.ModTime()) // Last modification time\nfmt.Println(\"Is Directory: \", fileStat.IsDir())   // Abbreviation for Mode().IsDir()\n```\n\nAlso when you call `ReadDir()` you get back an array of `FileInfo` objects:\n\n```go\nfiles, err := ioutil.ReadDir(path)\n```\n\n## Copy file\n\nCopying a file is really three operations:\n\n- **open** the file at the destination.\n- **create** a new file at a given destination.\n- **copy**, then transfer the content to that location.\n\nHere's how you can implement a *copy* operation:\n\n```go\n// copies 'test.txt' and its content to 'copy.txt'\nsrc := \"test.txt\"\ndest := \"copy.txt\"\n\nsrcFile, err := os.Open(src)\nif err != nil {\n  log.Fatal(err)\n}\ndefer srcFile.Close()\n\nnewFile, err := os.Create(dest)\nif err != nil {\n  log.Fatal(err)\n}\ndefer newFile.Close()\n\n_, err = io.Copy(newFile, srcFile)\nif err != nil {\n  log.Fatal(err)\n}\n```\n\n## Rename\n\nRename is a bit easier to achieve. The `os` package has a `Rename()` function. Here's how to use it:\n\n```go\nerr := os.Rename(src, dest)\n```\n\n## Remove file\n\nTo remove file, there's a `Remove()` function you can use. Here's how to use it:\n\n```go\nerr := os.Remove(path)\n```\n\n## Create dir\n\nTo create a directory, you can use the `MkdirAll()` function in the `os` library. However, you should check whether the directory exist first. The way to do that is to use the `IsNotExist()` function like so:\n\n```go\n_, err := os.Stat(dirName)\n\n if os.IsNotExist(err) {\n  errDir := os.MkdirAll(dirName, 0755)\n  if errDir != nil {\n   log.Fatal(err)\n  }\n } else if err != nil {\n  log.Fatal(\"error creating dir\")\n } else {\n  log.Fatal(\"directory exist\")\n }\n```\n\nAs you can see on the above code:\n\n1. you first use the `Stat()` function. The `Stat()` returns a `FileInfo` object or an error of type `PathError` if path doesn't exist.\n\n1. `os.IsNotExist(err)`. This returns `true` if `err` is a `PathError`, i.e the path don't exist, which is good, we want to create it.\n\n1. Finally, we call `os.MkdirAll(dirName, 0755)`. The 755 instruction is about permissions on the created directory, which gives the permissions, Read/Write/Execute, Read/Execute, Read/Execute. 755 is a common permission set on web servers. You essentially want to avoid anyone but you to modify the file.\n\n## Read dir\n\nReading a directory is quite straight forward. You can use the `ReadDir()` function on the `io/ioutil` library. Here's how you would read a directory:\n\n```go\nfiles, err := ioutil.ReadDir(path)\n```\n\n`files` is an array of type `FileInfo`.  \n\nTODO, copy, rename, remove, check for existence\n\n## Assignment\n\nCreate the following files and directories like so:\n\n```text\ntmp/\n  a.txt\n  b.xt\n  subdir/\n```\n\nYour program should read the diretory *tmp* and for each entry list, if it's a dir or a file, the size and when last modified.\n\nThe programs output should look something like:\n\n```output\nReading directory tmp:\nName, Type, Size, Modified\na.txt, file, 1kb, 2022-01-01\nb.txt, file, 1kb, 2022-01-01\nsubdir, directory, 1kb, 2022-01-01\n```\n\n## Solution\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"io/ioutil\"\n \"log\"\n)\n\nfunc GetType(isDir bool) string {\n if isDir {\n  return \"directory\"\n }\n return \"file\"\n}\n\nfunc main() {\n var path string = \"tmp\"\n files, err := ioutil.ReadDir(path)\n if err != nil {\n  log.Fatal(err)\n }\n fmt.Println(\"Reading directory \", path)\n fmt.Println(\"Name, Type, Size, Modified\")\n for _, file := range files {\n  if err != nil {\n   log.Fatal(err)\n  }\n  fmt.Printf(\"File Name: %s, \", file.Name())\n  fmt.Printf(\"Type: %s, \", GetType(file.IsDir()))\n  fmt.Printf(\"Size: %d, \", file.Size())             \n  fmt.Printf(\"Last Modified: %s, \", file.ModTime()) \n  fmt.Print(\"\\n\")\n }\n}\n\n```\n"
  },
  {
    "path": "06-io/02-file-directories/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n)\n\nfunc GetType(isDir bool) string {\n\tif isDir {\n\t\treturn \"directory\"\n\t}\n\treturn \"file\"\n}\n\nfunc main() {\n\tvar path string = \"tmp\"\n\tfiles, err := ioutil.ReadDir(path)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(\"Reading directory \", path)\n\tfmt.Println(\"Name, Type, Size, Modified\")\n\tfor _, file := range files {\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"File Name: %s, \", file.Name())\n\t\tfmt.Printf(\"Type: %s, \", GetType(file.IsDir()))\n\t\tfmt.Printf(\"Size: %d, \", file.Size())             // Length in bytes for regular files\n\t\tfmt.Printf(\"Last Modified: %s, \", file.ModTime()) // Last modification time\n\t\tfmt.Print(\"\\n\")\n\t}\n}\n"
  },
  {
    "path": "06-io/02-file-directories/tmp/a.txt",
    "content": ""
  },
  {
    "path": "06-io/02-file-directories/tmp/b.txt",
    "content": ""
  },
  {
    "path": "06-io/03-compress-files/README.md",
    "content": "## Compress files and directories\n\nComing soon\n\n## Assignment\n\n## Solution\n"
  },
  {
    "path": "06-io/fix/README.md",
    "content": "\n\n\n\n## Links\n\n<https://www.golangprograms.com/files-directories-examples.html>\n"
  },
  {
    "path": "06-io/fix/dir/dir.go",
    "content": "package dir\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nvar ErrDirExist = errors.New(\"Dir exist error\")\n\n/*\nDESCRIPTION\n\nReads the content on a directory and returns `FileInfo` array and a possible error, if dir can't be read.\n\nPARAMS\n\npath:string, a string representing the path holding a directory\n\nEXAMPLE\n\n\tfiles, err := dir.ReadDir(\".\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfor _, file := range files {\n\t\tfmt.Println(file.Name())\n\t}\n\n*/\nfunc ReadDir(path string) ([]fs.FileInfo, error) {\n\tfiles, err := ioutil.ReadDir(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn files, nil\n}\n\nfunc CreateDir(dirName string) error {\n\t_, err := os.Stat(dirName)\n\n\tif os.IsNotExist(err) {\n\t\terrDir := os.MkdirAll(dirName, 0755)\n\t\tif errDir != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t} else if err != nil {\n\t\tfmt.Println(\"error creating dir\")\n\t\treturn err // other type of error\n\t} else {\n\t\treturn ErrDirExist\n\t}\n}\n"
  },
  {
    "path": "06-io/fix/file/file.go",
    "content": "package file\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nfunc OpenText(path string) (string, error) {\n\tfilebuffer, err := ioutil.ReadFile(path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvar inputdata string = string(filebuffer)\n\treturn inputdata, nil\n}\n\nfunc GetFileInfo(path string) (fs.FileInfo, error) {\n\tfileStat, err := os.Stat(path)\n\treturn fileStat, err\n}\n\nfunc Append(path string, content string) error {\n\tf, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\tfmt.Fprintf(f, \"%s\\n\", content)\n\treturn nil\n}\n\nfunc WriteText(path string, content string) error {\n\tf, err := os.Create(path)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\tn, err := f.WriteString(content + \"\\n\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tfmt.Printf(\"wrote %d bytes\\n\", n)\n\tf.Sync()\n\treturn nil\n}\n\nfunc CopyFile(src string, dest string) error {\n\tsrcFile, err := os.Open(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer srcFile.Close()\n\n\tnewFile, err := os.Create(dest)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer newFile.Close()\n\n\t_, err = io.Copy(newFile, srcFile)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc RenameFile(src string, dest string) error {\n\terr := os.Rename(src, dest)\n\treturn err\n}\n\nfunc RemoveFile(path string) error {\n\terr := os.Remove(path)\n\treturn err\n}\n"
  },
  {
    "path": "06-io/fix/go.mod",
    "content": "module iohelper\n\ngo 1.16\n\nrequire golang.org/x/tools v0.1.9 // indirect\n"
  },
  {
    "path": "06-io/fix/go.sum",
    "content": "github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=\ngithub.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=\ngolang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=\ngolang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=\ngolang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=\ngolang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\n"
  },
  {
    "path": "06-io/fix/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"iohelper/dir\"\n\t\"iohelper/file\"\n\t\"log\"\n)\n\ntype Products struct {\n\tProducts []Product `json: products`\n}\n\ntype Product struct {\n\tId   int    `json: \"id\"`\n\tName string `json: \"name\"`\n}\n\n// writes JSON to file\n// TODO\n\n// reads JSON from file\nfunc OpenJson() {\n\tfile, _ := ioutil.ReadFile(\"products.json\")\n\n\tdata := Products{}\n\n\t_ = json.Unmarshal([]byte(file), &data)\n\n\tfor i := 0; i < len(data.Products); i++ {\n\t\tfmt.Println(\"Product Id: \", data.Products[i].Id)\n\t\tfmt.Println(\"Name: \", data.Products[i].Name)\n\t}\n}\n\nfunc main() {\n\t// open file\n\tcontent, err := file.OpenText(\"test.txt\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t} else {\n\t\tlog.Println(\"file content\", content)\n\t}\n\n\terr = file.WriteText(\"test2.txt\", \"here's some content\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\terr = file.Append(\"test.txt\", \"append this\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfiles, err := dir.ReadDir(\".\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfor _, file := range files {\n\t\tlog.Println(file.Name())\n\t}\n\n\terr = dir.CreateDir(\"tmp\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(\"dir created\")\n\n\tfile.CopyFile(\"test.txt\", \"copy.txt\")\n\tlog.Println(\"file copied\")\n\n\terr = file.RenameFile(\"test.txt\", \"renamed.txt\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfileStat, err := file.GetFileInfo(\"renamed.txt\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Println(\"File Name:\", fileStat.Name())        // Base name of the file\n\tfmt.Println(\"Size:\", fileStat.Size())             // Length in bytes for regular files\n\tfmt.Println(\"Permissions:\", fileStat.Mode())      // File mode bits\n\tfmt.Println(\"Last Modified:\", fileStat.ModTime()) // Last modification time\n\tfmt.Println(\"Is Directory: \", fileStat.IsDir())   // Abbreviation for Mode().IsDir()\n\n\terr = file.RenameFile(\"copy.txt\", \"test.txt\")\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tlog.Println(\"file renamed\")\n\n\terr = file.RemoveFile(\"renamed.txt\")\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tlog.Println(\"file removed\")\n\n\tOpenJson()\n\n\t/*\n\t\t  CHECK - Append text to file\n\t\t\tCreate empty file\n\t\t\tCHECK - Read dir\n\t\t\tCHECK Create dir\n\t\t\tCHECK Copy file\n\t\t  Move file\n\t\t\tCHECK Get file metadata\n\t\t\tCHECK Delete fil\n\t*/\n}\n"
  },
  {
    "path": "06-io/fix/products.json",
    "content": "{\n  \"products\": [{\n    \"id\": 1,\n    \"name\": \"test\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"test2\"\n  }]\n}"
  },
  {
    "path": "06-io/fix/test.txt",
    "content": "here's a file\nand the second row\n\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\nappend this\n"
  },
  {
    "path": "06-io/fix/test2.txt",
    "content": "here's some content\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "This project welcomes contributions and suggestions.\n\nAny feature suggestion, bugs, tests. Please raise an issue at <https://github.com/softchris/golang-book/issues>.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2022 Chris Noring\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Go from the beginning\n\nWelcome to Go from the beginning, a free book containing 25+ lessons that will take you from \"zero to hero\" in the amazing language Go.\n\n## Read online\n\n> <https://softchris.github.io/golang-book/>\n\n## Read offline/PDF/EPUB\n\n> <https://leanpub.com/go-from-the-beginning> FREE on LeanPub\n\n## Donate\n\nPlease consider donating to the people of Ukraine.\n\n- **Back and Alive** (they are buying what the army requests and do public reports)\n<https://comebackalive.in.ua>\n- **NBU** (National Bank of Ukraine) accounts for the army support <https://t.co/MauRvgu89E>\n- **UNICEF**, <https://www.unicef.org/emergencies/war-ukraine-pose-immediate-threat-children>\n\n## Table of content\n\n| Chapter | Title | Section | What you will learn |  Lesson  \n|--|--|--|--|--|\n| 01 | Hello world | Basics | Why use Go and how to write your first program | [Lesson](/01-basics/01-hello/README.md) |\n| 02 | Using variables | Basics | How to declare variables with different data types and how to initialize and assign values | [Lesson](/01-basics/02-variables/README.md)  |\n| 03 | Boolean logic with If and Else | Basics | How to work with boolean variables and create different execution paths with If, Else and Else If | [Lesson](/01-basics/03-if-and-else/README.md)  |\n| 04 | Converting between strings and numbers | Basics | How to use the `strconv` library to convert between primitives and strings. | [Lesson](/01-basics/04-conversions/README.md)  | \n| 05 | Loop statements | Basics |  How to repeat statements and iterating over list structures and ways to control the loops | [Lesson](/01-basics/05-loops/README.md)  |\n| 06 | User input | Basics | How to read user input from the console | [Lesson](/01-basics/06-user-input/README.md)  |\n| 07 | Functions | Basics | Reuse your code by creating functions. Learn how to deal with parameters and how to deal with returns and return types | [Lesson](/01-basics/07-functions/README.md)  |\n| 08 | Error handling | Basics | How manage errors in your code. This will teach both how to produce errors as well as deal with them | [Lesson](/01-basics/08-error-handling/README.md)  |\n| 09 | Arrays | Composite data types | Here we will learn about arrays, how to construct them, access items and iterate over them | [Lesson](/02-data-types/01-arrays/README.md)  | \n| 10 | Structs | Composite data types | Structs enables us to collect many fields in one grouping, learn how to create and modify structs | [Lesson](/02-data-types/02-structs%20/README.md)  |\n| 11 | Maps | Composite data types | Maps make it easy to lookup items if you know the key. Maps have the notion of keys and values. | [Lesson](/02-data-types/03-maps/README.md)  | \n| 12 | Interfaces | Composite data types | Learn how you can model your data as interfaces and how to implement them | [Lesson](/02-data-types/04-interfaces/README.md)  |\n| 13 | Create your first project  | Projects  | Learn how to create your first project | [Lesson](/03-projects/01-first-project/README.md)  |\n| 14 | Consume external packages | Projects  | Learn how to use external packages | [Lesson](/03-projects/02-consume-external/README.md)  |\n| 15 | Create shared module | Projects | Create a module you can share with others | [Lesson](/03-projects/03-create-shared-module/README.md)  |\n| 16 | Testing | Testing | Learn to test your code | [Lesson](/03-projects/04-testing/README.md)  |  \n| 17 | JSON | Web Dev | Learn to work with the JSON format | [Lesson](/04-webdev/01-json/README.md)  |\n| 18 | Build a Web App | Web Dev | Learn how to build a web app capable of serving many different formats | [Lesson](/04-webdev/02-web-dev/README.md)  |\n| 19 | Logs | Miscellaneous  | Use logging for better management of all kinds of messages in your app | [Lesson](/05-misc/01-logs/README.md)  |\n| 20 | Strings | Miscellaneous | Work with the string library | [Lesson](/05-misc/02-strings/README.md)  |\n| 21 | Regex | Miscellaneous | Work with regular epressions | [Lesson](/05-misc/03-regex/README.md)  |\n| 22 | Goroutines  | Miscellaneous | Work with goroutines and channels | [Lesson](/05-misc/04-goroutines/README.md)  |\n| 23 | Database with Sqlite  | Miscellaneous | Work with databases | [Lesson](/05-misc/05-sqlite/README.md)  |\n| 24 | Read and write to files | IO | Learn to read from and write to files | [Lesson](/06-io/01-read-write-files/README.md)  |\n| 25 | Files and directories  | IO | Learn to perform operations on files and directories | [Lesson](/06-io/02-file-directories/README.md)  |\n\n## How to use this content\n\nEvery chapter consist of a lesson and an exercise. You are encouraged to run the code in the exercise, modify it and understand how it works.\n\n## Contributions\n\nContributions are very welcome. Please raise an issue of you see something or a PR.\n\nI welcome contributions on:\n\n- Suggestions on topics to cover\n- Correctness issues\n- Spelling\n- Suggestions on better formatting\n- I hope I hear from you. :)\n\n\n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-cayman"
  },
  {
    "path": "_layouts/default.html",
    "content": "\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>{{ page.title }}</title>\n    \n    <script type=\"text/javascript\">\n    (function(c,l,a,r,i,t,y){\n        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};\n        t=l.createElement(r);t.async=1;t.src=\"https://www.clarity.ms/tag/\"+i;\n        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);\n    })(window, document, \"clarity\", \"script\", \"rr93jmbel1\");\n    </script>\n  </head>\n  <body>\n    {{ content }}\n  </body>\n</html>\n"
  },
  {
    "path": "_sidebar.md",
    "content": "# Lessons\n\n| Chapter |  Lesson  \n|--|--|\n| 01 | [Hello world](/01-basics/01-hello/README.md) |\n| 02 | [Using variables](/01-basics/02-variables/README.md)  |\n| 03 | [Boolean logic with If and Else ](/01-basics/03-if-and-else/README.md)  |\n| 04 | [Converting between strings and numbers](/01-basics/04-conversions/README.md)  | \n| 05 | [Loop statements](/01-basics/05-loops/README.md)  |\n| 06 | [User input](/01-basics/06-user-input/README.md)  |\n| 07 | [Functions](/01-basics/07-functions/README.md)  |\n| 08 | [Error handling](/01-basics/08-error-handling/README.md)  |\n| 09 | [Arrays](/02-data-types/01-arrays/README.md)  | \n| 10 | [Structs](/02-data-types/02-structs%20/README.md)  |\n| 11 | [Maps](/02-data-types/03-maps/README.md)  | \n| 12 | [Interfaces](/02-data-types/04-interfaces/README.md)  |\n| 13 | [Create your first project](/03-projects/01-first-project/README.md)  |\n| 14 | [Consume external packages](/03-projects/02-consume-external/README.md)  |\n| 15 | [Create shared module](/03-projects/03-create-shared-module/README.md)  |\n| 16 | [Testing](/03-projects/04-testing/README.md)  |  \n| 17 | [JSON](/04-webdev/01-json/README.md)  |\n| 18 | [Build a Web App](/04-webdev/02-web-dev/README.md)  |\n| 19 | [Logs](/05-misc/01-logs/README.md)  |\n| 20 | [Strings](/05-misc/02-strings/README.md)  |\n| 21 | [Regex](/05-misc/03-regex/README.md)  |\n| 22 | [Goroutines](/05-misc/04-goroutines/README.md)  |\n| 23 | [Database with Sqlite](/05-misc/05-sqlite/README.md)  |\n| 24 | [Read and write to files](/06-io/01-read-write-files/README.md)  |\n| 25 | [Files and directories](/06-io/02-file-directories/README.md)  |\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Golang book</title>\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n  <meta name=\"description\" content=\"Description\">\n  <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0\">\n  <link rel=\"icon\" type=\"image/png\" href=\"images/favicon.png\">\n  <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css\">\n  <link rel=\"stylesheet\" href=\"index.css\">\n  </head>\n<body>\n  <div id=\"app\"></div>\n  <script type=\"text/javascript\">\n\n    (function(c,l,a,r,i,t,y){\n        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};\n        t=l.createElement(r);t.async=1;t.src=\"https://www.clarity.ms/tag/\"+i;\n        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);\n    })(window, document, \"clarity\", \"script\", \"rr93jmbel1\");\n\n    window.$docsify = {\n      loadSidebar: true,\n      name: 'Golang book',\n      repo: 'https://github.com/softchris/golang-book',\n      relativePath: true,\n      auto2top: false,\n      notFoundPage: true,\n      alias: {\n        '/.*/_sidebar.md': '/_sidebar.md',\n        '/(README.(.*))': '/translations/$1',\n        '#/((?!README).*)/README.(.*)': '$1/translations/README.$2',\n        '/((?!README).*)/((?!README).*)/README.(.*)': '$1/$2/translations/README.$3',\n\n        // handle English, since English files isn't in translation folders\n        '/(README$)': '/$1',\n        '#/((?!README).*)/(README$)': '$1/$2',\n        '/((?!README).*)/((?!README).*)/(README$)': '$1/$2/$3'\n      }\n    }\n  </script>\n  <script src=\"//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js\"></script>\n\n</body>\n</html>\n"
  }
]