talks: Go for C++ programmers.

Change-Id: I63fcf13468eeaa174714dcd9e58a99d973ddae40
Reviewed-on: https://go-review.googlesource.com/7995
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/2015/go4cpp.slide b/2015/go4cpp.slide
new file mode 100644
index 0000000..0742025
--- /dev/null
+++ b/2015/go4cpp.slide
@@ -0,0 +1,712 @@
+Go for C++ developers
+
+Francesc Campoy
+Developer, Advocate, and Gopher at Google
+@francesc
+campoy@golang.org
+
+#go4cpp
+
+* Go for C++ developers
+
+Agenda:
+
+- let's talk about Go
+
+- how do I do X in Go?
+
+- concurrency, because it's awesome
+
+- Q & A: but feel free to interrupt anytime
+
+- We might not go through all the slides
+
+* About me
+
+*2011*  Joined Google as a Software Engineer
+
+- writing mostly in C++ and Python
+- used to think _smart_code_ was better than boring code
+
+*2012* Joined the Go team as a Developer Programs Engineer
+
+*2014*to*today* Developer Advocate for the Google Cloud Platform
+
+* Let's talk about Go
+
+* Go is
+
+Go is
+
+- open source
+
+- statically typed
+
+- object oriented (if you ask me)
+
+- compiled
+
+- memory safe
+
+- type safe
+
+* Why Go?
+
+Go was created for:
+
+- scalability
+
+- concurrency
+
+- simplicity
+
+* Who uses Go?
+
+Google:
+
+- YouTube
+- dl.google.com
+
+Others:
+
+- Docker
+- SoundCloud
+- Canonical
+- CloudFlare
+- Mozilla
+- ...
+
+[[http://golang.org/wiki/GoUsers][golang.org/wiki/GoUsers]]
+
+* Who uses Go?
+
+.image go4cpp/trends.png _ 800
+
+.caption Google Trends for [[http://www.google.com/trends/explore#q=golang][golang]]
+
+* Some Go features
+
+* Go types
+
+- primitive types
+
+	int, uint, int8, uint8, ...
+	bool, string
+	float32, float64
+	complex64, complex128
+
+- structs
+
+	struct {
+		Name string
+		Age  int
+	}
+
+- slices and arrays
+
+	[]int, [3]string, []struct{ Name string }
+
+- maps
+
+	map[string]int
+
+* Kinds of types (continued)
+
+- pointers
+
+	*int, *Person
+
+- functions
+
+	func(int, int) int
+
+- channels
+
+	chan bool
+
+- interfaces
+
+	interface {
+		Start()
+		Stop()
+	}
+
+* Type declarations
+
+	type [name] [specification]
+
+`Person` is a `struct` type.
+
+	type Person struct {
+		name string
+		age  int
+	}
+
+`Celsius` is a `float64` type.
+
+	type Celsius float64
+
+* Function declarations
+
+	func [name] ([params]) [return value]
+	func [name] ([params]) ([return values])
+
+A sum function:
+
+	func sum(a int, b int) int {
+		return a + b
+	}
+
+A function with multiple return values:
+
+	func divMod(a, b int) (int, int) {
+		return a / b, a % b
+	}
+
+Made clearer by naming the return values:
+
+	func divMod(den, div int) (quo, rem int) {
+		return den / div, den % div
+	}
+
+* Method declarations
+
+	func ([receiver]) [name] ([params]) ([return values])
+
+A method on a struct:
+
+	func (p Person) IsMinor() bool {
+		return p.age < 18
+	}
+
+But also a method on a `float64`:
+
+	func (c Celsius) Freezing() bool {
+		return c <= 0
+	}
+
+_Constraint:_ Methods can be defined *only* on types declared in the same package.
+
+	// This won't compile
+	func (s string) Length() int { return len(s) }
+
+* Declaring variables
+
+Normal declaration:
+
+    var text string = "hello"
+
+You can omit types:
+
+    var text = "hello"
+
+And inside of functions:
+
+    text := "hello"
+
+Other types
+
+    a := 0                             // int
+    b := true                          // boolean
+    f := 1.0                           // float64
+    p := Person{"Francesc", "Campoy"}  // Person
+
+* No implicit numeric conversion
+
+Given types:
+
+    type Celsius float64
+
+    type Fahrenheit float64
+
+And the variables:
+
+    var freezing Fahrenheit = 32
+    var boiling Celsius = 100
+
+This code won't compile:
+
+    sauna := (freezing + boiling) / 2
+
+There's no implicit numeric conversion in Go.
+
+* Pointers and memory allocation
+
+* Pointers
+
+Go has pointers:
+
+    var p *int
+    p = new(int)
+
+But no pointer arithmetics:
+
+    var p *int = &a[0]
+    var q = p+2            // invalid
+
+There's `new` but there's no `delete`.
+
+Memory is garbaged collected after it's no longer accessible.
+
+* Memory allocation
+
+The compiler decides where to allocate based on escape analysis.
+
+Using `new` doesn't imply using the heap:
+
+`stack.go`:
+
+    func get() int {
+        n := new(int)
+        return *n
+    }
+
+And not all values in the heap are created with `new`:
+
+`heap.go`:
+
+    func get() *int {
+        n := 4
+        return &n
+    }
+
+* Choosing what allocation you want
+
+You can *not* decide where a value is allocated.
+
+But you can see what kind of allocation is used:
+
+    $ go tool 6g -m stack.go
+
+    stack.go:3: can inline get
+    stack.go:4: get new(int) does not escape
+
+Compare to:
+
+    $ go tool 6g -m heap.go
+
+    heap.go:3: can inline get
+    heap.go:4: moved to heap: n
+    heap.go:5: &n escapes to heap
+
+* RAII
+
+_Resource_Acquisition_Is_Initialization_
+
+Provides:
+
+- encapsulation of acquisition and disposition of resources
+
+- exception safe
+
+An example:
+
+    void write_to_file (const std::string & message) {
+        // mutex to protect file access
+        static std::mutex mutex;
+     
+        // lock mutex before accessing file
+        // at the end of the scope unlock mutex
+        std::lock_guard<std::mutex> lock(mutex);
+
+        // mutual exclusion access section
+        ...
+    }
+
+* RAII in Go: defer
+
+The `defer` statement:
+
+- schedules a function call at the end of the current function
+
+- stacks all deferred calls - first in first out
+
+    var m sync.Mutex
+
+    func writeToFile(msg string) error {
+        m.Lock()
+        defer m.Unlock()
+
+        // mutual exclusion access section
+    }
+
+* Garbage collection
+
+Go is a garbage collected language
+
+But it's easy to limit heap allocations
+
+- many values are allocated on the stack
+
+- object pools: [[sync.Pool][http://golang.org/pkg/sync/#Pool]]
+
+- contiguous area of memory
+
+.play go4cpp/sizes.go /type/,
+
+* More about garbage collection
+
+Trusted in production.
+
+Brad Fitzpatrick's talk on migrating dl.google.com from C++ to Go:
+
+- [[https://talks.golang.org/2013/oscon-dl.slide#1][dl.google.com: Powered by Go]]
+
+Current state and road plan:
+
+- [[http://golang.org/s/go14gc][golang.org/s/go14gc]]
+
+* Inheritance vs Composition
+
+* Inheritance vs Composition
+
+- Inheritance breaks encapsulation
+
+- Composition causes boilerplate to proxy all methods
+
+Example:
+
+    type Engine struct{}
+
+    func (e Engine) Start() { ... }
+    func (e Engine) Stop()  { ... }
+
+We want `Car` to be able to `Start` and `Stop` too.
+
+More detail in my talk [[http://talks.golang.org/2014/go4java.slide#32][Go for Javaneros]]
+
+* Struct embedding
+
+Composition + Proxy of selectors
+
+.play go4cpp/embedding.go /type/,
+
+* Struct embedding and the diamond problem
+
+What if two embedded fields have the same type?
+
+.play go4cpp/diamond.go /type/,
+
+* Struct embedding
+
+It looks like inheritance but _it_is_not_inheritance_.
+
+It is composition.
+
+Used to share implementations between different types.
+
+What if want to share behavior instead?
+
+* Interfaces
+
+* Interfaces
+
+An interface is a set of methods.
+
+In Java (C++ doesn't have interfaces)
+
+    interface Switch {
+        void open();
+        void close();
+    }
+
+In Go:
+
+	type OpenCloser interface {
+		Open()
+		Close()
+	}
+
+* It's all about satisfaction
+
+Java interfaces are satisfied *explicitly*.
+
+C++ abstract classes need to be extended *explicitly*
+
+Go interfaces are satisfied *implicitly*.
+
+.image //upload.wikimedia.org/wikipedia/commons/thumb/2/29/Rolling_Stones_09.jpg/512px-Rolling_Stones_09.jpg _ 512
+
+.caption Picture by Gorupdebesanez [[http://creativecommons.org/licenses/by-sa/3.0][CC-BY-SA-3.0]], via [[http://commons.wikimedia.org/wiki/File%3ARolling_Stones_09.jpg][Wikimedia Commons]]
+
+* Go: implicit satisfaction
+
+_If_a_type_defines_all_the_methods_of_an_interface,_the_type_satisfies_that_interface._
+
+Benefits:
+
+- fewer dependencies
+- no type hierarchy
+- organic composition
+
+* Structural subtyping
+
+Better than duck typing. Verified at compile time.
+
+.image go4cpp/duck.jpg 500 500
+
+* FuncDraw: an example on interfaces
+
+.image go4cpp/funcdraw.png 500 700
+
+* FuncDraw: package parser
+
+Package `parse` provides a parser of strings into functions.
+
+	func Parse(text string) (*Func, error) { ... }
+
+`Func` is a struct type, with an `Eval` method.
+
+	type Func struct { ... }
+
+	func (p *Func) Eval(x float64) float64 { ... }
+
+* FuncDraw: package draw
+
+Package draw generates images given a function.
+
+	func Draw(f *parser.Func) image.Image {
+		for x := start; x < end; x += inc {
+			y := f.Eval(x)
+			...
+		}
+	}
+
+`draw` depends on `parser`, which makes testing hard.
+
+* Breaking dependencies
+
+Let's use an interface instead
+
+	type Evaluable interface {
+		Eval(float64) float64
+	}
+
+	func Draw(f Evaluable) image.Image image.Image {
+		for x := start; x < end; x += inc {
+			y := f.Eval(x)
+			...
+		}
+	}
+
+* Advanced interfaces and composition
+
+* Struct embedding of interfaces
+
+Embedding an interface:
+
+- more types can be used
+- limits what is added to the embedding type
+
+Given:
+
+    type Person struct {
+        First string
+        Last  string
+        Age   int
+    }
+
+`Employee` exposes the `Age` of `Person`
+
+    type Employee struct {
+        Person
+    }
+
+    e := Employee{Person{"John", "Doe", 49}}
+
+* Choosing what to proxy
+
+But we could hide it by choosing an interface:
+
+    type Employee struct {
+        Namer
+    }
+
+    type Namer interface {
+        Name() string
+    }
+
+And we need to make `Person` satisfy `Namer`
+
+    func (e Person) Name() string { return e.First + e.Last }
+
+And the rest of the code still works:
+
+    e := Employee{Person{"John", "Doe", 49}}
+
+* Easy mocking of interfaces
+
+Given this function:
+
+.code go4cpp/mock.go /func/,/^}/
+
+How would you test it?
+
+* Easy mocking of interfaces
+
+`net.Conn` is an interface defined in the `net` package of the standard library.
+
+    type Conn interface {
+        Read(b []byte) (n int, err error)
+        Write(b []byte) (n int, err error)
+        Close() error
+        LocalAddr() Addr
+        RemoteAddr() Addr
+        SetDeadline(t time.Time) error
+        SetReadDeadline(t time.Time) error
+        SetWriteDeadline(t time.Time) error
+    }
+
+We need a fake `net.Conn`!
+
+* One solution
+
+We could define a new type that satisfies `net.Conn`
+
+    type fakeConn struct {}
+
+    func (c fakeConn) Read(b []byte) (n int, err error) {...}
+    func (c fakeConn) Write(b []byte) (n int, err error) {...}
+    func (c fakeConn) Close() error {...}
+    ...
+
+But, is there a better way?
+
+* The better way
+
+.code go4cpp/mock.go /type fakeConn/,/end_fake/
+
+And our test can look like:
+
+.play go4cpp/mock.go /func main/,
+
+* Concurrency
+
+* Concurrency
+
+It is part of the language, not a library.
+
+Based on three concepts:
+
+- goroutines: lightweight threads
+- channels: typed pipes used to communicate and synchronize between goroutines
+- select: control structure to coordinate concurrent operations
+
+.image go4cpp/funnelin.jpg 300 700
+
+* Sleep and talk
+
+.code go4cpp/conc1.go /sleepAndTalk/,/^}/
+
+We want a message per second.
+
+.play go4cpp/conc1.go /func main/,/^}/
+
+What if we started all the `sleepAndTalk` concurrently?
+
+Just add `go`!
+
+* Concurrent sleep and talk
+
+.play go4cpp/conc2.go /func main/,/^}/
+
+That was fast ...
+
+When the `main` goroutine ends, the program ends.
+
+* Concurrent sleep and talk with more sleeping
+
+.play go4cpp/conc3.go /func main/,/^}/
+
+But synchronizing with `Sleep` is a bad idea.
+
+* Communicating through channels
+
+`sleepAndTalk` sends the string into the channel instead of printing it.
+
+.code go4cpp/chan.go /sleepAndTalk/,/^}/
+
+We create the channel and pass it to `sleepAndTalk`, then wait for the values to be sent.
+
+.play go4cpp/chan.go /func main/,/^}/
+
+* Aside: a web server
+
+A production ready web server.
+
+.play go4cpp/webserver.go
+
+* Let's count on the web
+
+Why is this wrong?
+
+.play go4cpp/badcounter.go /nextID/,
+
+* Let's count on the web correctly
+
+We receive the next id from a channel.
+
+.code go4cpp/goodcounter.go /nextID/,/^}/
+
+We need to send ids into the channel.
+
+.code go4cpp/goodcounter.go /counter/,/^}/
+
+* Let's count on the web correctly
+
+And we need to do both at the same time.
+
+.play go4cpp/goodcounter.go /func main/,/^}/
+
+* Let's fight!
+
+`select` allows us to choose among multiple channel operations.
+
+.play go4cpp/battle.go /battle/,/^}/
+
+Go - [[http://localhost:8080/fight?usr=go]]
+C++ - [[http://localhost:8080/fight?usr=cpp]]
+
+* Chain of gophers
+
+.image go4cpp/chain.jpg
+
+Ok, I'm just bragging here
+
+* Chain of gophers
+
+.play go4cpp/goroutines.go /func f/,
+
+* Concurrency is very powerful
+
+And there's lots to learn!
+
+- [[http://talks.golang.org/2012/concurrency.slide#1][Go Concurrency Patterns]], by Rob Pike
+- [[http://talks.golang.org/2013/advconc.slide#1][Advanced Concurrency Patterns]], by Sameer Ajmani
+- [[http://talks.golang.org/2012/waza.slide#1][Concurrency is not Parellelism]], by Rob Pike
+
+.image go4cpp/busy.jpg
+
+* In conclusion
+
+- Go is simple, consistent, readable, and fun.
+
+- All types are equal: methods on any type.
+
+- Implicit satisfaction of interfaces makes code easier to reuse.
+
+- Use composition instead of inheritance.
+
+- Struct embedding is a powerful tool.
+
+- Concurrency is awesome, and you should check it out.
+
+* What to do next?
+
+Learn Go on your browser with [[http://tour.golang.org][tour.golang.org]]
+
+Find more about Go on [[http://golang.org][golang.org]]
+
+Join the community at [[https://groups.google.com/forum/#!forum/Golang-nuts][golang-nuts]]
+
+Link to the slides [[http://talks.golang.org/2015/go4cpp.slide]]
diff --git a/2015/go4cpp/badcounter.go b/2015/go4cpp/badcounter.go
new file mode 100644
index 0000000..92b8eb7
--- /dev/null
+++ b/2015/go4cpp/badcounter.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+)
+
+var nextID int
+
+func handler(w http.ResponseWriter, q *http.Request) {
+	fmt.Fprintf(w, "<h1>You got %v<h1>", nextID)
+	nextID++
+}
+
+func main() {
+	http.HandleFunc("/", handler)
+	log.Fatal(http.ListenAndServe("localhost:8080", nil))
+}
diff --git a/2015/go4cpp/battle.go b/2015/go4cpp/battle.go
new file mode 100644
index 0000000..8fc9505
--- /dev/null
+++ b/2015/go4cpp/battle.go
@@ -0,0 +1,24 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"net/http"
+)
+
+var battle = make(chan string)
+
+func handler(w http.ResponseWriter, q *http.Request) {
+	select {
+	case battle <- q.FormValue("usr"):
+		fmt.Fprintf(w, "You won!")
+	case won := <-battle:
+		fmt.Fprintf(w, "You lost, %v is better than you", won)
+	}
+}
+
+func main() {
+	http.HandleFunc("/fight", handler)
+	http.ListenAndServe("localhost:8080", nil)
+}
diff --git a/2015/go4cpp/busy.jpg b/2015/go4cpp/busy.jpg
new file mode 100644
index 0000000..35ce9f4
--- /dev/null
+++ b/2015/go4cpp/busy.jpg
Binary files differ
diff --git a/2015/go4cpp/chain.jpg b/2015/go4cpp/chain.jpg
new file mode 100644
index 0000000..87f8571
--- /dev/null
+++ b/2015/go4cpp/chain.jpg
Binary files differ
diff --git a/2015/go4cpp/chan.go b/2015/go4cpp/chan.go
new file mode 100644
index 0000000..c9ea793
--- /dev/null
+++ b/2015/go4cpp/chan.go
@@ -0,0 +1,26 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func sleepAndTalk(secs time.Duration, msg string, c chan string) {
+	time.Sleep(secs * time.Second)
+	c <- msg
+}
+
+func main() {
+	c := make(chan string)
+
+	go sleepAndTalk(0, "Hello", c)
+	go sleepAndTalk(1, "Gophers!", c)
+	go sleepAndTalk(2, "What's", c)
+	go sleepAndTalk(3, "up?", c)
+
+	for i := 0; i < 4; i++ {
+		fmt.Printf("%v ", <-c)
+	}
+}
diff --git a/2015/go4cpp/conc.jpg b/2015/go4cpp/conc.jpg
new file mode 100644
index 0000000..5813956
--- /dev/null
+++ b/2015/go4cpp/conc.jpg
Binary files differ
diff --git a/2015/go4cpp/conc1.go b/2015/go4cpp/conc1.go
new file mode 100644
index 0000000..9d114bc
--- /dev/null
+++ b/2015/go4cpp/conc1.go
@@ -0,0 +1,20 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func sleepAndTalk(t time.Duration, msg string) {
+	time.Sleep(t)
+	fmt.Printf("%v ", msg)
+}
+
+func main() {
+	sleepAndTalk(0*time.Second, "Hello")
+	sleepAndTalk(1*time.Second, "Gophers!")
+	sleepAndTalk(2*time.Second, "What's")
+	sleepAndTalk(3*time.Second, "up?")
+}
diff --git a/2015/go4cpp/conc2.go b/2015/go4cpp/conc2.go
new file mode 100644
index 0000000..9fc8aa3
--- /dev/null
+++ b/2015/go4cpp/conc2.go
@@ -0,0 +1,20 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func sleepAndTalk(t time.Duration, msg string) {
+	time.Sleep(t)
+	fmt.Printf("%v ", msg)
+}
+
+func main() {
+	go sleepAndTalk(0*time.Second, "Hello")
+	go sleepAndTalk(1*time.Second, "Gophers!")
+	go sleepAndTalk(2*time.Second, "What's")
+	go sleepAndTalk(3*time.Second, "up?")
+}
diff --git a/2015/go4cpp/conc3.go b/2015/go4cpp/conc3.go
new file mode 100644
index 0000000..ada59d1
--- /dev/null
+++ b/2015/go4cpp/conc3.go
@@ -0,0 +1,21 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func sleepAndTalk(t time.Duration, msg string) {
+	time.Sleep(t)
+	fmt.Printf("%v ", msg)
+}
+
+func main() {
+	go sleepAndTalk(0*time.Second, "Hello")
+	go sleepAndTalk(1*time.Second, "Gophers!")
+	go sleepAndTalk(2*time.Second, "What's")
+	go sleepAndTalk(3*time.Second, "up?")
+	time.Sleep(4 * time.Second)
+}
diff --git a/2015/go4cpp/defer.go b/2015/go4cpp/defer.go
new file mode 100644
index 0000000..05f7cc6
--- /dev/null
+++ b/2015/go4cpp/defer.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"os"
+)
+
+func dumpURL(u, path string) error {
+	net.Dial()
+	res, err := http.Get(u)
+	if err != nil {
+		return fmt.Errorf("get %v: %v", u, err)
+	}
+	defer res.Body.Close()
+
+	f, err := os.Create(path)
+	if err != nil {
+		return fmt.Errorf("create %v: %v", path, err)
+	}
+	defer f.Close()
+
+	_, err := io.Copy(f, res.Body)
+}
diff --git a/2015/go4cpp/diamond.go b/2015/go4cpp/diamond.go
new file mode 100644
index 0000000..1d1b96f
--- /dev/null
+++ b/2015/go4cpp/diamond.go
@@ -0,0 +1,24 @@
+package main
+
+import "fmt"
+
+type Engine struct{}
+
+func (e Engine) Start() { fmt.Println("Engine started") }
+func (e Engine) Stop()  { fmt.Println("Engine stopped") }
+
+type Radio struct{}
+
+func (r Radio) Start() { fmt.Println("Radio started") }
+func (r Radio) Stop()  { fmt.Println("Radio stopped") }
+
+type Car struct {
+	Engine
+	Radio
+}
+
+func main() {
+	var c Car
+	c.Radio.Start()  // HL
+	c.Engine.Start() // HL
+}
diff --git a/2015/go4cpp/duck.jpg b/2015/go4cpp/duck.jpg
new file mode 100644
index 0000000..344b31e
--- /dev/null
+++ b/2015/go4cpp/duck.jpg
Binary files differ
diff --git a/2015/go4cpp/embedding.go b/2015/go4cpp/embedding.go
new file mode 100644
index 0000000..6bf08ef
--- /dev/null
+++ b/2015/go4cpp/embedding.go
@@ -0,0 +1,24 @@
+package main
+
+import "fmt"
+
+type Engine struct{}
+
+func (e Engine) Start() {
+	fmt.Println("Engine started")
+}
+
+func (e Engine) Stop() {
+	fmt.Println("Engine stopped")
+}
+
+type Car struct {
+	Engine // Notice the lack of name // HL
+}
+
+func main() {
+	var c Car
+
+	c.Start()
+	c.Stop()
+}
diff --git a/2015/go4cpp/funcdraw.png b/2015/go4cpp/funcdraw.png
new file mode 100644
index 0000000..374ea2e
--- /dev/null
+++ b/2015/go4cpp/funcdraw.png
Binary files differ
diff --git a/2015/go4cpp/funnelin.jpg b/2015/go4cpp/funnelin.jpg
new file mode 100644
index 0000000..2bf6873
--- /dev/null
+++ b/2015/go4cpp/funnelin.jpg
Binary files differ
diff --git a/2015/go4cpp/goodcounter.go b/2015/go4cpp/goodcounter.go
new file mode 100644
index 0000000..7ba8b7c
--- /dev/null
+++ b/2015/go4cpp/goodcounter.go
@@ -0,0 +1,27 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+)
+
+var nextID = make(chan int)
+
+func handler(w http.ResponseWriter, q *http.Request) {
+	fmt.Fprintf(w, "<h1>You got %v<h1>", <-nextID)
+}
+
+func counter() {
+	for i := 0; ; i++ {
+		nextID <- i
+	}
+}
+
+func main() {
+	http.HandleFunc("/", handler)
+	go counter()
+	log.Fatal(http.ListenAndServe("localhost:8080", nil))
+}
diff --git a/2015/go4cpp/goroutines.go b/2015/go4cpp/goroutines.go
new file mode 100644
index 0000000..d137b3a
--- /dev/null
+++ b/2015/go4cpp/goroutines.go
@@ -0,0 +1,30 @@
+// +build OMIT
+
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func f(left, right chan int) {
+	left <- 1 + <-right
+}
+
+func main() {
+	start := time.Now()
+	const n = 1000
+	leftmost := make(chan int)
+
+	right := leftmost
+	left := leftmost
+	for i := 0; i < n; i++ {
+		right = make(chan int)
+		go f(left, right)
+		left = right
+	}
+
+	go func(c chan int) { c <- 0 }(right)
+
+	fmt.Println(<-leftmost, time.Since(start))
+}
diff --git a/2015/go4cpp/mock.go b/2015/go4cpp/mock.go
new file mode 100644
index 0000000..86ddb85
--- /dev/null
+++ b/2015/go4cpp/mock.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"strings"
+)
+
+func CheckPassword(c net.Conn) error {
+	// read a password from the connection
+	buf := make([]byte, 256)
+	n, err := c.Read(buf)
+	if err != nil {
+		return fmt.Errorf("read: %v", err)
+	}
+
+	// check it's correct
+	got := string(buf[:n])
+	if got != "password" {
+		return fmt.Errorf("wrong password")
+	}
+	return nil
+}
+
+type fakeConn struct {
+	net.Conn
+	r io.Reader
+}
+
+func (c fakeConn) Read(b []byte) (int, error) {
+	return c.r.Read(b)
+}
+
+// end_fake OMIT
+
+func main() {
+	c := fakeConn{
+		r: strings.NewReader("foo"),
+	}
+	err := CheckPassword(c)
+	if err == nil {
+		log.Println("expected error using wrong password")
+	} else {
+		log.Println("OK")
+	}
+}
diff --git a/2015/go4cpp/sizes.go b/2015/go4cpp/sizes.go
new file mode 100644
index 0000000..98fe2d5
--- /dev/null
+++ b/2015/go4cpp/sizes.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+	"fmt"
+	"unsafe"
+)
+
+type Date struct {
+	Day   int
+	Month int
+	Year  int
+}
+
+func main() {
+	fmt.Printf("size of %T: %v\n", 0, unsafe.Sizeof(0))
+	fmt.Printf("size of %T: %v\n", Date{}, unsafe.Sizeof(Date{}))
+	fmt.Printf("size of %T: %v\n", [100]Date{}, unsafe.Sizeof([100]Date{}))
+}
diff --git a/2015/go4cpp/trends.png b/2015/go4cpp/trends.png
new file mode 100644
index 0000000..2abc0f0
--- /dev/null
+++ b/2015/go4cpp/trends.png
Binary files differ
diff --git a/2015/go4cpp/webserver.go b/2015/go4cpp/webserver.go
new file mode 100644
index 0000000..bcd9075
--- /dev/null
+++ b/2015/go4cpp/webserver.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) { // HL
+	fmt.Fprintln(w, "hello")
+}
+
+func main() {
+	http.HandleFunc("/", handler) // HL
+	err := http.ListenAndServe("localhost:1234", nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+}