~kotrunga/a-tour-of-go

0e1e307d7c9d5613d4ab2fc5e4e7c50b29a883b6 — kotrunga 7 months ago 372aab1
completion of the tour
37 files changed, 1338 insertions(+), 1 deletions(-)

A .DS_Store
M README.md
A concurrency/3.10_exercise-web-crawler.go
A concurrency/3.1_goroutines.go
A concurrency/3.2_channels.go
A concurrency/3.3_buffered-channels.go
A concurrency/3.4_range-and-close.go
A concurrency/3.5_select.go
A concurrency/3.6_default-selection.go
A concurrency/3.8_exercise-equivalent-binary-trees.go
A concurrency/3.9_mutex-counter.go
A methods-and-interfaces/2.10_interfaces-are-satisfied-implicitly.go
A methods-and-interfaces/2.11_interface-values.go
A methods-and-interfaces/2.12_interface-values-with-nil.go
A methods-and-interfaces/2.13_nil-interface-values.go
A methods-and-interfaces/2.14_empty-interface.go
A methods-and-interfaces/2.15_type-assertions.go
A methods-and-interfaces/2.16_type-switches.go
A methods-and-interfaces/2.17_stringer.go
A methods-and-interfaces/2.18_exercise-stringer.go
A methods-and-interfaces/2.19_errors.go
A methods-and-interfaces/2.1_methods.go
A methods-and-interfaces/2.20_exercise-errors.go
A methods-and-interfaces/2.21_reader.go
A methods-and-interfaces/2.22_exercise-readers.go
A methods-and-interfaces/2.23_exercise-rot-reader.go
A methods-and-interfaces/2.24_images.go
A methods-and-interfaces/2.25_exercise-images.go
A methods-and-interfaces/2.2_methods-funcs.go
A methods-and-interfaces/2.3_methods-continued.go
A methods-and-interfaces/2.4_methods-pointers.go
A methods-and-interfaces/2.5_methods-pointers-explained.go
A methods-and-interfaces/2.6_indirection.go
A methods-and-interfaces/2.7_indirection-values.go
A methods-and-interfaces/2.8_methods-with-pointer-receivers.go
A methods-and-interfaces/2.9_interfaces.go
D methods-and-interfaces/basic-types.go
A .DS_Store => .DS_Store +0 -0

M README.md => README.md +1 -1
@@ 2,4 2,4 @@

This repository contains code & comments from the official [A Tour of Go](https://tour.golang.org).

As long as you have the Go environment set up on your machine, you can build/run each file as so: `go build filename.go`. The files are just arranged individually, so if you import the repo into your GOPATH src/ folder, linters may complain that you have more than one `main()` func. Just ignore it and compile the file individually.
\ No newline at end of file
As long as you have the Go environment set up on your machine, you can run each file as so: `go run filename.go`. The files are just arranged individually, so if you import the repo into your GOPATH src/ folder, linters may complain that you have more than one `main()` func. Just ignore it and compile the file individually.

A concurrency/3.10_exercise-web-crawler.go => concurrency/3.10_exercise-web-crawler.go +142 -0
@@ 0,0 1,142 @@
/*
	Notes 3.10

	Exercise: https://tour.golang.org/concurrency/10

	For now... the Go author's solution.
*/

// Copyright 2012 The Go Authors.  All rights reserved.
// From: https://code.google.com/p/go-tour/source/browse/solutions/webcrawler.go

package main

import (
	"errors"
	"fmt"
	"sync"
)

type Fetcher interface {
	// Fetch returns the body of URL and
	// a slice of URLs found on that page.
	Fetch(url string) (body string, urls []string, err error)
}

// fetched tracks URLs that have been (or are being) fetched.
// The lock must be held while reading from or writing to the map.
// See http://golang.org/ref/spec#Struct_types section on embedded types.
var fetched = struct {
	m map[string]error
	sync.Mutex
}{m: make(map[string]error)}

var loading = errors.New("url load in progress") // sentinel value

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
	if depth <= 0 {
		fmt.Printf("<- Done with %v, depth 0.\n", url)
		return
	}

	fetched.Lock()
	if _, ok := fetched.m[url]; ok {
		fetched.Unlock()
		fmt.Printf("<- Done with %v, already fetched.\n", url)
		return
	}
	// We mark the url to be loading to avoid others reloading it at the same time.
	fetched.m[url] = loading
	fetched.Unlock()

	// We load it concurrently.
	body, urls, err := fetcher.Fetch(url)

	// And update the status in a synced zone.
	fetched.Lock()
	fetched.m[url] = err
	fetched.Unlock()

	if err != nil {
		fmt.Printf("<- Error on %v: %v\n", url, err)
		return
	}
	fmt.Printf("Found: %s %q\n", url, body)
	done := make(chan bool)
	for i, u := range urls {
		fmt.Printf("-> Crawling child %v/%v of %v : %v.\n", i, len(urls), url, u)
		go func(url string) {
			Crawl(url, depth-1, fetcher)
			done <- true
		}(u)
	}
	for i := range urls {
		fmt.Printf("<- [%v] %v/%v Waiting for child %v.\n", url, i, len(urls))
		<-done
	}
	fmt.Printf("<- Done with %v\n", url)
}

func main() {
	Crawl("http://golang.org/", 4, fetcher)

	fmt.Println("Fetching stats\n--------------")
	for url, err := range fetched.m {
		if err != nil {
			fmt.Printf("%v failed: %v\n", url, err)
		} else {
			fmt.Printf("%v was fetched\n", url)
		}
	}
}

// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult

type fakeResult struct {
	body string
	urls []string
}

func (f *fakeFetcher) Fetch(url string) (string, []string, error) {
	if res, ok := (*f)[url]; ok {
		return res.body, res.urls, nil
	}
	return "", nil, fmt.Errorf("not found: %s", url)
}

// fetcher is a populated fakeFetcher.
var fetcher = &fakeFetcher{
	"http://golang.org/": &fakeResult{
		"The Go Programming Language",
		[]string{
			"http://golang.org/pkg/",
			"http://golang.org/cmd/",
		},
	},
	"http://golang.org/pkg/": &fakeResult{
		"Packages",
		[]string{
			"http://golang.org/",
			"http://golang.org/cmd/",
			"http://golang.org/pkg/fmt/",
			"http://golang.org/pkg/os/",
		},
	},
	"http://golang.org/pkg/fmt/": &fakeResult{
		"Package fmt",
		[]string{
			"http://golang.org/",
			"http://golang.org/pkg/",
		},
	},
	"http://golang.org/pkg/os/": &fakeResult{
		"Package os",
		[]string{
			"http://golang.org/",
			"http://golang.org/pkg/",
		},
	},
}
\ No newline at end of file

A concurrency/3.1_goroutines.go => concurrency/3.1_goroutines.go +27 -0
@@ 0,0 1,27 @@
/*
	Notes 3.1

	A 'goroutine' is a "lightweight thread managed by the Go runtime".

	If you run go f(x, y, z), it evaluates f, x, y, and z on the current goroutine, and
	the execution of f happens in the new goroutine.
*/

package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}
\ No newline at end of file

A concurrency/3.2_channels.go => concurrency/3.2_channels.go +34 -0
@@ 0,0 1,34 @@
/*
	Notes 3.2

	You can use channels to send and receive values with the channel operator, <-

	'chan'

	In the example below, we sum the numbers in the slice s. The work is
	distributed through two go routines (lines 29 and 30). When both goroutines
	complete their jobs, the final result is calculated.
*/

package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // send sum to c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c // receive from c

	fmt.Println(x, y, x+y)
}
\ No newline at end of file

A concurrency/3.3_buffered-channels.go => concurrency/3.3_buffered-channels.go +22 -0
@@ 0,0 1,22 @@
/*
	Notes 3.3

	Channels can be buffered- provide the length during channel creation with make().

	"Sends to a buffered channel block only when the buffer is full. Receives block
	when the buffer is empty."

	If you overfill the buffer, you'll get an error.
*/

package main

import "fmt"

func main() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}
\ No newline at end of file

A concurrency/3.4_range-and-close.go => concurrency/3.4_range-and-close.go +43 -0
@@ 0,0 1,43 @@
/*
	Notes 3.4

	A sender can close channels to indicate no more values will be sent.
	Receivers can test if channels are closed by testing the ok value:

	v, ok := <-ch

	ok is false if the channel is closed and there are no more values to receive.

	i := range c

	This loop receives values from the channel until it's closed.

	PS:
	- Only the sender should close a channel, never the receiver (sending on a closed channel)
	will cause a panic
	- Channels aren't like files; you don't *usually* need to close them. You only need to close them
	when the receiver must be told there are no more values coming (like when terminating a range loop).
*/

package main

import (
	"fmt"
)

func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c)
}

func main() {
	c := make(chan int, 10)	// buffered channel with a size of 10
	go fibonacci(cap(c), c)
	for v := range c {
		fmt.Println(v)
	}
}
\ No newline at end of file

A concurrency/3.5_select.go => concurrency/3.5_select.go +36 -0
@@ 0,0 1,36 @@
/*
	Notes 3.5

	"The select statement lets a goroutine wait on multiple communication operations.
	A select blocks until one of its cases can run, then it executes that case.
	It chooses one at random if multiple are ready."
*/

package main

import "fmt"

func fibonacci(c, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <- quit:
			fmt.Println("quit")
			return
		}
	}
}

func main() {
	c := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		quit <- 0
	}()
	fibonacci(c, quit)
}
\ No newline at end of file

A concurrency/3.6_default-selection.go => concurrency/3.6_default-selection.go +37 -0
@@ 0,0 1,37 @@
/*
	Notes 3.6

	You can add a default case to your select which
	will run if no other case is ready.

	select {
	case i := <-c:
		// use i
	default:
		// receiving from c would block
	}
*/

package main

import (
	"fmt"
	"time"
)

func main() {
	tick := time.Tick(100 * time.Millisecond)
	boom := time.After(500 * time.Millisecond)
	for {
		select {
		case <- tick:
			fmt.Println("tick.")
		case <- boom:
			fmt.Println("BOOM!")
			return
		default:
			fmt.Println("    .")
			time.Sleep(50 * time.Millisecond)
		}
	}
}
\ No newline at end of file

A concurrency/3.8_exercise-equivalent-binary-trees.go => concurrency/3.8_exercise-equivalent-binary-trees.go +81 -0
@@ 0,0 1,81 @@
/*
	Notes 3.8

	Exercise:
	https://tour.golang.org/concurrency/7
	https://tour.golang.org/concurrency/8

	Solution from: https://play.golang.org/p/He5vnWCiyQD
*/

package main

import (
	"fmt"

	"golang.org/x/tour/tree"
)

func main() {
	fmt.Println("Tour of Go Solution - Equivalent Binary Trees\n")

	t1 := tree.New(5)
	t2 := tree.New(5)
	fmt.Println("Tree 1:", t1)
	fmt.Println("Tree 2:", t2)
	fmt.Println("Are they same? - ", Same(t1, t2))
	fmt.Println("------")

	t3 := tree.New(2)
	t4 := tree.New(3)
	fmt.Println("Tree 3:", t3)
	fmt.Println("Tree 4:", t4)
	fmt.Println("Are they same? - ", Same(t3, t4))
	fmt.Println("")
}

func Walker(t *tree.Tree, ch chan int) {
	Walk(t, ch)
	//close the channel to avoid panic
	close(ch)
}

func Walk(t *tree.Tree, ch chan int) {
	if t == nil {
		return
	} else if t.Left == nil {
		ch <- t.Value
		if t.Right != nil {
			Walk(t.Right, ch)
		}
		return
	} else {
		Walk(t.Left, ch)
	}
	ch <- t.Value
	if t.Right != nil {
		Walk(t.Right, ch)
	}
}

func Same(t1, t2 *tree.Tree) bool {
	var br bool
	done := make(chan bool)
	c1 := make(chan int)
	c2 := make(chan int)
	go Walker(t1, c1)
	go Walker(t2, c2)
	go func() {
		for i := range c1 {
			if i == <-c2 {
				br = true
			} else {
				br = false
				break
			}
		}
		done <- true
	}()
	<-done
	return br
}
\ No newline at end of file

A concurrency/3.9_mutex-counter.go => concurrency/3.9_mutex-counter.go +53 -0
@@ 0,0 1,53 @@
/*
	Notes 3.9

	'mutual exclusion'- allowing goroutines to only access a variable one at a time
	to prevent conflicts. Uses the data structure called a 'mutex'

	Go's standard lib provides mutual exclusion via sync.Mutex (has methods Lock and Unlock).

	We can execute a block of code in mutual exclusion by surrounding it with Lock and Unlock
	(see the Inc method).

	You can also use the defer method to ensure the mutex is unlocked (see the Value method).
*/

package main

import (
	"fmt"
	"sync"
	"time"
)

// SafeCounter is safe to use concurrently.
type SafeCounter struct {
	v   map[string]int
	mux sync.Mutex
}

// Inc increments the counter for the given key.
func (c *SafeCounter) Inc(key string) {
	c.mux.Lock()
	// Lock so only one goroutine at a time can access the map c.v.
	c.v[key]++
	c.mux.Unlock()
}

// Value returns the current value of the counter for the given key.
func (c *SafeCounter) Value(key string) int {
	c.mux.Lock()
	// Lock so only one goroutine at a time can access the map c.v.
	defer c.mux.Unlock()
	return c.v[key]
}

func main() {
	c := SafeCounter{v: make(map[string]int)}
	for i := 0; i < 1000; i++ {
		go c.Inc("somekey")
	}

	time.Sleep(time.Second)
	fmt.Println(c.Value("somekey"))
}
\ No newline at end of file

A methods-and-interfaces/2.10_interfaces-are-satisfied-implicitly.go => methods-and-interfaces/2.10_interfaces-are-satisfied-implicitly.go +28 -0
@@ 0,0 1,28 @@
/*
	Notes 2.10

	You don't need to be explicity about a type that implements an interface.
*/

package main

import "fmt"

type I interface {
	M()
}

type T struct {
	S string
}

// This method means type T implements the interface I,
// but we don't need to explicitly declare that it does so.
func (t T) M() {
	fmt.Println(t.S)
}

func main() {
	var i I = T{"hello"}
	i.M()
}
\ No newline at end of file

A methods-and-interfaces/2.11_interface-values.go => methods-and-interfaces/2.11_interface-values.go +53 -0
@@ 0,0 1,53 @@
/*
	Notes 2.11

	"Interface values can be thought of as a tuple of a value and a concrete type. (value, type)
	An interface value holds a value of a specific underlying concrete type.
	Calling a method on an interface value executes the method of the same name on its underlying type."


	fmt.Printf verbs:
		%v = the value in a default format
		%T = a Go-syntax representation of the type of the value
*/

package main

import (
	"fmt"
	"math"
)

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M() {
	fmt.Println(t.S)
}

type F float64

func (f F) M() {
	fmt.Println(f)
}

func main() {
	var i I

	i = &T{"hello"}
	describe(i)
	i.M()

	i = F(math.Pi)
	describe(i)
	i.M()
}

func describe(i I) {
	fmt.Printf("(%v, %T)\n", i, i)
}
\ No newline at end of file

A methods-and-interfaces/2.12_interface-values-with-nil.go => methods-and-interfaces/2.12_interface-values-with-nil.go +46 -0
@@ 0,0 1,46 @@
/*
	Notes 2.12

	"If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.
	In some languages this would trigger a null pointer exception, but in Go it is common to write methods that gracefully handle being called with a nil receiver (as with the method M in this example.)
	Note that an interface value that holds a nil concrete value is itself non-nil."

	If you comment out lines 24-27, then you will get a runtime error.
*/

package main

import "fmt"

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M() {
	if t == nil {
		fmt.Println("<nil>")
		return
	}
	fmt.Println(t.S)
}

func main() {
	var i I

	var t *T
	i = t
	describe(i)
	i.M()

	i = &T{"hello"}
	describe(i)
	i.M()
}

func describe(i I) {
	fmt.Printf("(%v, %T)\n", i, i)
}

A methods-and-interfaces/2.13_nil-interface-values.go => methods-and-interfaces/2.13_nil-interface-values.go +28 -0
@@ 0,0 1,28 @@
/*
	Notes 2.13

	A nil interface value holds neither a value nor a concrete type.
	Calling a method on a nil interface causes a runtime error, b/c
	there's no type in the interface tuple to indicate which concrete
	method to call.

	A comment also was written about this in Notes 2.12.
*/

package main

import "fmt"

type I interface {
	M()
}

func main() {
	var i I
	describe(i)
	i.M()
}

func describe(i I) {
	fmt.Printf("(%v, %T)\n", i, i)
}
\ No newline at end of file

A methods-and-interfaces/2.14_empty-interface.go => methods-and-interfaces/2.14_empty-interface.go +29 -0
@@ 0,0 1,29 @@
/*
	Notes 2.14

	empty interface- the interface type that specifies zero methods

	Typed as: interface{}

	Empty interfaces can hold values of any type- each type implements at least zero methods.
	Empty interfaces are used by code that handles values of unkown type.
*/

package main

import "fmt"

func main() {
	var i interface{}
	describe(i)

	i = 42
	describe(i)

	i = "hello"
	describe(i)
}

func describe(i interface{}) {
	fmt.Printf("(%v, %T)\n", i, i)
}
\ No newline at end of file

A methods-and-interfaces/2.15_type-assertions.go => methods-and-interfaces/2.15_type-assertions.go +38 -0
@@ 0,0 1,38 @@
/*
	Notes 2.15

	A type assertion provides access to an interface
	value's underlying concrete value.

	t := i.(T)
	
	The statement above will return the underlying T value to the variabel t,
	provided the interface value i holds the concrete type T. If it doesn't hold
	the concrete type T, a panic occurs.

	t, ok := i.(T)

	For this line, it's the same as above it; except 'ok' is a boolean.
	'ok' holds if the underlying concrete type is type T. If it doesn't hold
	the concrete type T, a panic will not occur, as 'ok' will just be false.
*/

package main

import "fmt"

func main() {
	var i interface{} = "hello"

	s := i.(string)
	fmt.Println(s)

	s, ok := i.(string)
	fmt.Println(s, ok)

	f, ok := i.(float64)
	fmt.Println(f, ok)

	f = i.(float64) // panic
	fmt.Println(f)
}
\ No newline at end of file

A methods-and-interfaces/2.16_type-switches.go => methods-and-interfaces/2.16_type-switches.go +26 -0
@@ 0,0 1,26 @@
/*
	Notes 2.16

	"A type switch is a construct that permits several type assertions in series."
*/

package main

import "fmt"

func do(i interface{}) {
	switch v:= i.(type) {
	case int:
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know about type %T!\n", v)
	}
}

func main() {
	do(21)
	do("hello")
	do(true)
}
\ No newline at end of file

A methods-and-interfaces/2.17_stringer.go => methods-and-interfaces/2.17_stringer.go +27 -0
@@ 0,0 1,27 @@
/*
	Notes 2.17

	The fmt package provides the interface "Stringer", which is a type
	that can describe itself as a string.

	%v = the value in a default format
*/

package main

import "fmt"

type Person struct {
	Name string
	Age int
}

func (p Person) String() string {
	return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
	a := Person{"Arthur Dent", 42}
	z := Person{"Zaphod Beeblebrox", 9001}
	fmt.Println(a, z)
}
\ No newline at end of file

A methods-and-interfaces/2.18_exercise-stringer.go => methods-and-interfaces/2.18_exercise-stringer.go +25 -0
@@ 0,0 1,25 @@
/*
	Notes 2.18

	The exercise: "Make the IPAddr type implement fmt.Stringer to print the address as a dotted quad."
*/

package main

import "fmt"

type IPAddr [4]byte

func (ip IPAddr) String() string {
	return fmt.Sprintf("%v.%v.%v.%v", ip[0], ip[1], ip[2], ip[3])
}

func main() {
	hosts := map[string]IPAddr{
		"loopback":  {127, 0, 0, 1},
		"googleDNS": {8, 8, 8, 8},
	}
	for name, ip := range hosts {
		fmt.Printf("%v: %v\n", name, ip)
	}
}
\ No newline at end of file

A methods-and-interfaces/2.19_errors.go => methods-and-interfaces/2.19_errors.go +39 -0
@@ 0,0 1,39 @@
/*
	Notes 2.19

	"Go programs express error state with error values."
	"The error type is a built-in interface":

	type error interface {
    	Error() string
	}
*/

package main

import (
	"fmt"
	"time"
)

type MyError struct {
	When time.Time
	What string
}

func (e *MyError) Error() string {
	return fmt.Sprintf("at %v, %s", e.When, e.What)
}

func run() error {
	return &MyError {
		time.Now(),
		"it didn't work",
	}
}

func main() {
	if err := run(); err != nil {
		fmt.Println(err)
	}
}
\ No newline at end of file

A methods-and-interfaces/2.1_methods.go => methods-and-interfaces/2.1_methods.go +29 -0
@@ 0,0 1,29 @@
/*
	Notes 2.1

	- Go doesn't have classes
	- You define methods on types
	- A method is a function with a special receiver argument
	- The receiver appears in its own argument list between func and the method name
	- The Abs() method has a receiver of type Vertex named v
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}
\ No newline at end of file

A methods-and-interfaces/2.20_exercise-errors.go => methods-and-interfaces/2.20_exercise-errors.go +33 -0
@@ 0,0 1,33 @@
/*
	Notes 2.20

	Exercise: https://tour.golang.org/methods/20
*/

package main

import (
	"fmt"
)

func Sqrt(x float64) (float64, error) {
	if x < 0 {
		return 0, ErrNegativeSqrt(x)
	}
	var z float64 = 1
	for i := 0; i < 10; i++ {
		z -= (z*z - x) / (2 * z)
	}
	return z, nil
}

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
	return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println(Sqrt(-2))
}
\ No newline at end of file

A methods-and-interfaces/2.21_reader.go => methods-and-interfaces/2.21_reader.go +30 -0
@@ 0,0 1,30 @@
/*
	Notes 2.21

	The io package provides the io.Reader interface.

	"Read populates the given byte slice with data and
	 returns the number of bytes populated and an error value. It returns an io.EOF error when the stream ends."
*/

package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	r := strings.NewReader("Hello, Reader!")

	b := make([]byte, 8)
	for {
		n, err := r.Read(b)
		fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
		fmt.Printf("b[:n] = %q\n", b[:n])
		if err == io.EOF {
			break;
		}
	}
}
\ No newline at end of file

A methods-and-interfaces/2.22_exercise-readers.go => methods-and-interfaces/2.22_exercise-readers.go +26 -0
@@ 0,0 1,26 @@
/*
	Notes 2.22

	Exercise: https://tour.golang.org/methods/22

	"Implement a Reader type that emits an infinite stream of the ASCII character 'A'."
*/

package main

import "golang.org/x/tour/reader"

type MyReader struct{}

// TODO: Add a Read([]byte) (int, error) method to MyReader.

func (r MyReader) Read(b []byte) (int, error) {
	for i := range b {
		b[i] = 65
	}
	return len(b), nil
}

func main() {
	reader.Validate(MyReader{})
}
\ No newline at end of file

A methods-and-interfaces/2.23_exercise-rot-reader.go => methods-and-interfaces/2.23_exercise-rot-reader.go +48 -0
@@ 0,0 1,48 @@
/*
	Notes 2.23

	Exercise: https://tour.golang.org/methods/23
	
	I had to get help with this one:
	https://play.golang.org/p/sb1vtLP1Dx
	https://stackoverflow.com/questions/31669266/a-tour-of-golang-exercise-rot13reader
*/

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func rot13(x byte) byte {
	capital := x >= 'A' && x <= 'Z'
	if !capital && (x < 'a' || x > 'z') {
		return x // Not a letter
	}

	x += 13
	if capital && x > 'Z' || !capital && x > 'z' {
		x -= 26
	}
	return x
}

func (r13 *rot13Reader) Read(b []byte) (int, error) {
	n, err := r13.r.Read(b)
	for i := 0; i <= n; i++ {
		b[i] = rot13(b[i])
	}
	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}
\ No newline at end of file

A methods-and-interfaces/2.24_images.go => methods-and-interfaces/2.24_images.go +18 -0
@@ 0,0 1,18 @@
/*
	Notes 2.24

	Package "image" has the Image interface.
*/

package main

import (
	"fmt"
	"image"
)

func main() {
	m := image.NewRGBA(image.Rect(0,0, 100, 100))
	fmt.Println(m.Bounds())
	fmt.Println(m.At(0, 0).RGBA())
}
\ No newline at end of file

A methods-and-interfaces/2.25_exercise-images.go => methods-and-interfaces/2.25_exercise-images.go +37 -0
@@ 0,0 1,37 @@
/*
	Notes 2.25

	Exercise: https://tour.golang.org/methods/25

	Got help from: https://gist.github.com/flc/6437570
*/

package main

import (
	"golang.org/x/tour/pic"
	"image"
	"image/color"
)

type Image struct {
	width, height int
	colorB, colorA uint8
}

func (i Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, i.width, i.height)
}

func (i Image) At(x, y int) color.Color {
	return color.RGBA{uint8(x), uint8(y), i.colorB, i.colorA}
}

func main() {
	m := Image{111, 111, 255, 255}
	pic.ShowImage(m)
}
\ No newline at end of file

A methods-and-interfaces/2.2_methods-funcs.go => methods-and-interfaces/2.2_methods-funcs.go +26 -0
@@ 0,0 1,26 @@
/*
	Notes 2.2

	- A method is just a function with a receiver argument
	- Below- Abs() written as a regular function with no change in funcionality
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func Abs(v Vertex) float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(Abs(v))
}
\ No newline at end of file

A methods-and-interfaces/2.3_methods-continued.go => methods-and-interfaces/2.3_methods-continued.go +34 -0
@@ 0,0 1,34 @@
/*
	Notes 2.3

	- You can declare a method on non-struct types also.
	- You can only declare a method with a receiver whose type is defined
	  in the same package as the method. So, because MyFloat is defined in
	  the 'main' package, we can make a method with a MyFloat as a receiver.
	  However, we can't make a method on a built in type like int, as it's
	  defined in a different package.

	Below, we create a numeric type MyFloat & give it an Abs() method.
*/

package main

import (
	"fmt"
	"math"
)

type MyFloat float64

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func main() {
	f := MyFloat(-math.Sqrt2)	// math.Sqrt2 is a constant in the math package
	fmt.Println(f)				// before Abs()
	fmt.Println(f.Abs())		// after Abs()
}
\ No newline at end of file

A methods-and-interfaces/2.4_methods-pointers.go => methods-and-interfaces/2.4_methods-pointers.go +36 -0
@@ 0,0 1,36 @@
/*
	Notes 2.4

	You can declare methods with pointer receivers.
	This allows you to change the value of the receiver passed by reference.

	Without the pointer, it's only passed by value, and any operations done
	are operating on a copy of the original, so after the method ends, the changes
	aren't saved.
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func main() {
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Abs())
}
\ No newline at end of file

A methods-and-interfaces/2.5_methods-pointers-explained.go => methods-and-interfaces/2.5_methods-pointers-explained.go +32 -0
@@ 0,0 1,32 @@
/*
	Notes 2.5

	Rewriting methods from 2.4 as functions... notice, with pointers,
	we can acheive similar (or, the same) functionality.
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func Abs(v Vertex) float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func Scale(v *Vertex, f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func main() {
	v := Vertex{3, 4}
	Scale(&v, 10)
	fmt.Println(Abs(v))
}
\ No newline at end of file

A methods-and-interfaces/2.6_indirection.go => methods-and-interfaces/2.6_indirection.go +43 -0
@@ 0,0 1,43 @@
/*
	Notes 2.6

	Functions with a pointer argument take a pointer...
	Methods with pointer receivers take either a value or a pointer
	as the receiver when they are called.

	v.Scale(2), at the bottom, uses pointer indirection. Even though
	v is a value and not a pointer, the method with a pointer receiver is called automatically.

	So, v.Scale(2) is really (&v).Scale(2), since the Scale method has a pointer receiver.
*/

package main

import "fmt"

type Vertex struct {
	X, Y float64
}

// a method with 
func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func ScaleFunc(v *Vertex, f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func main() {
	v := Vertex{3, 4}
	v.Scale(2)
	ScaleFunc(&v, 10)

	p := &Vertex{4, 3}
	p.Scale(3)
	ScaleFunc(p, 8)

	fmt.Println(v, p)
}
\ No newline at end of file

A methods-and-interfaces/2.7_indirection-values.go => methods-and-interfaces/2.7_indirection-values.go +40 -0
@@ 0,0 1,40 @@
/*
	Notes 2.7

	Pointer indirection also happens in the opposite direction
	as seen in the example 2.6.

	If you call a pointer receiver function on the pointer of a
	value that has that receiver, it is still used correctly.

	In this case, the method call p.Abs() is interpreted as (*p).Abs()
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func AbsFunc(v Vertex) float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
	fmt.Println(AbsFunc(v))

	p := &Vertex{4, 3}
	fmt.Println(p.Abs())
	fmt.Println(AbsFunc(*p))
}
\ No newline at end of file

A methods-and-interfaces/2.8_methods-with-pointer-receivers.go => methods-and-interfaces/2.8_methods-with-pointer-receivers.go +41 -0
@@ 0,0 1,41 @@
/*
	Notes 2.8

	Two reasons to use a pointer receiver
	1) so the method can modify the value the receiver points to
	2) to avoid copying the value on each method call

	Notice, in the Abs() method, it doesn't modify the receiver.
	However, b/c it's a pointer receiver method, we don't have to copy
	the value on each method call. (Could acheive the same with just passing a pointer.)

	"In general, all methods on a given type should have either value or pointer receivers,
	but not a mixture of both."
*/

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := &Vertex{3, 4}
	fmt.Printf("Before caling: %+v, Abs: %v\n", v, v.Abs())
	v.Scale(5)
	fmt.Printf("After scaling: %+v, Abs: %v\n", v, v.Abs())
}
\ No newline at end of file

A methods-and-interfaces/2.9_interfaces.go => methods-and-interfaces/2.9_interfaces.go +50 -0
@@ 0,0 1,50 @@
/*
	Notes 2.9

	An interface type is defined as a set of method signatures.

	A value of interface type can hold any value that implements those methods.
*/

package main

import (
	"fmt"
	"math"
)

type MyFloat float64

type Abser interface {
	Abs() float64
}

type Vertex struct {
	X, Y float64
}

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	var a Abser
	f := MyFloat(-math.Sqrt2)
	v := Vertex{3, 4}

	a = f	// a MyFloat implements Abser
	a = &v	// a *Vertex implements Abser

	// In the following line, v is a Vertex (not *Vertex)
	// and does NOT implement Abser.
	a = v	// error on this line

	fmt.Println(a.Abs())
}
\ No newline at end of file

D methods-and-interfaces/basic-types.go => methods-and-interfaces/basic-types.go +0 -0