Skip to content

Commit

Permalink
iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
quii committed Mar 4, 2018
1 parent f81afbb commit 72846ca
Show file tree
Hide file tree
Showing 14 changed files with 226 additions and 1 deletion.
112 changes: 112 additions & 0 deletions for/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# for

To do stuff repeatedly in Go, you'll need `for`. In go there are no `while`, `do`, `until` kewords, you can only use `for`. Which is a good thing!

## Repeat a character

Let's write a test for a function that repeats a character 5 times.

There's nothing new so far, so try and write it yourself for practice.

```go
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}
```

_Keep the discipline!_ You will dont need to know anything new right now

- Run the test
- Listen to the compiler
- Make it compile

```go
package main

func Repeat(character string) (repeated string) {
return
}
```

Isn't it nice to know you already know enough Go to write tests for some basic problems? This means you can now play with the production code as much as you like and know it's behaving as you'd hope.

The `for` syntax is very unremarkable and follows most C-like languages.

```go
func Repeat(character string) (repeated string) {
for i := 0; i < 5; i++ {
repeated = repeated + character
}
return
}
```

Run the test and it should pass.

Now it's time to refactor and introduce another construct `+=`

```go
const repeatCount = 5

func Repeat(character string) (repeated string) {
for i := 0; i < repeatCount; i++ {
repeated += character
}
return
}
```

`+=` adds a value to another. It works other types like integers.

## next iteration

todo: Think of a way to include `continue` in exercise.

## Benchmarking

Writing benchmarks in Go is another first-class feature of the language and it is very similar to writing tests.

```go
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat("a")
}
}
```

I am using gogland so when I type `Test` or `Bench` in a file it generates most of the code for me.

You'll see the code is very similar to a test.

The `testing.B` gives you access to the cryptically named `b.N`.

When the benchmark is run the code is ran `b.N` times, and measure how long it takes.

That amount shouldn't matter to you, the framework will determine what is a "good" value for that to let you have some decent results.

To run the benchmarks do `go test -bench=.`

```
goos: darwin
goarch: amd64
pkg: github.com/quii/learn-go-with-tests/for/v4
10000000 136 ns/op
PASS
```

What that means is our function takes 136 nanoseconds to run. Which is pretty ok!

### Practice exercises

- Change the test so a caller can specify how many times the character is repeated and then fix the code
- Write `ExampleRepeat` to document your function
- Have a look through the [the strings package](https://golang.org/pkg/strings) package. Find functions you think could be useful and experiment with them by writing tests like we have here. Investing time learning the standard library will really pay off over time.
5 changes: 5 additions & 0 deletions for/v1/repeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package main

func Repeat(character string) (repeated string) {
return
}
12 changes: 12 additions & 0 deletions for/v1/repeat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}
8 changes: 8 additions & 0 deletions for/v2/repeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

func Repeat(character string) (repeated string) {
for i := 0; i < 5; i++ {
repeated = repeated + character
}
return
}
12 changes: 12 additions & 0 deletions for/v2/repeat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}
10 changes: 10 additions & 0 deletions for/v3/repeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

const repeatCount = 5

func Repeat(character string) (repeated string) {
for i := 0; i < repeatCount; i++ {
repeated += character
}
return
}
12 changes: 12 additions & 0 deletions for/v3/repeat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}
10 changes: 10 additions & 0 deletions for/v4/repeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

const repeatCount = 5

func Repeat(character string) (repeated string) {
for i := 0; i < repeatCount; i++ {
repeated += character
}
return
}
12 changes: 12 additions & 0 deletions for/v4/repeat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aAaAa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}
10 changes: 10 additions & 0 deletions for/vx/repeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

const repeatCount = 5

func Repeat(character string) (repeated string) {
for i := 0; i < repeatCount; i++ {
repeated += character
}
return
}
18 changes: 18 additions & 0 deletions for/vx/repeat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import "testing"

func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"

if repeated != expected {
t.Errorf("expected '%s' but got '%s'", expected, repeated)
}
}

func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat("a")
}
}
File renamed without changes.
1 change: 1 addition & 0 deletions integers/v1/adder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import "testing"


func TestAdder(t *testing.T) {
sum := Add(2, 2)
expected := 4
Expand Down
5 changes: 4 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Learn go with tests

I hope that after reading this you'll have a good grasp of the Go language in terms of its syntax, tooling and idioms - and be confident you will be able to start writing great systems in Go.

I have some experience introducing Go to development teams and have tried different approaches as to how to grow a team from some people curious about Go into highly effective writers of Go systems.

## What didnt work

### Read a book
### Read _the_ book

An approach we tried was to take [the blue book](https://www.amazon.co.uk/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440) and every week discuss the next chapter along with the exercises.

Expand Down Expand Up @@ -53,6 +55,7 @@ Taking my experience of learning with a group and my own personal way I am going

1. [Hello, world](/hello-world) - Declaring variables, constants, if statements, write your first go program and write your first test.
2. [Integers](/integers) - Further Explore function declaration syntax and learn new ways to improve the documentation of your code.
3. [Iteration](/for) - Learn about `for` and benchmarking

Property based tests (todo)

Expand Down

0 comments on commit 72846ca

Please sign in to comment.