talks: remove nearly everything

Everything in this repo moved to golang.org/x/website
in CL 365135 (x/website commit e219555f).

Leave a README behind.

Change-Id: I35d72a64f3f350967842fb3285737aa065729732
Reviewed-on: https://go-review.googlesource.com/c/talks/+/366177
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/.gcloudignore b/.gcloudignore
deleted file mode 100644
index 199e6d9..0000000
--- a/.gcloudignore
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file specifies files that are *not* uploaded to Google Cloud Platform
-# using gcloud. It follows the same syntax as .gitignore, with the addition of
-# "#!include" directives (which insert the entries of the given .gitignore-style
-# file at that point).
-#
-# For more information, run:
-#   $ gcloud topic gcloudignore
-#
-.gcloudignore
-# If you would like to upload your .git directory, .gitignore file or files
-# from your .gitignore file, remove the corresponding line
-# below:
-.git
-.gitignore
-
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-# Test binary, build with `go test -c`
-*.test
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index be5533b..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,21 +0,0 @@
-# Treat all files in this repo as binary, with no git magic updating
-# line endings. Windows users contributing to Go will need to use a
-# modern version of git and editors capable of LF line endings.
-#
-# We'll prevent accidental CRLF line endings from entering the repo
-# via the git-review gofmt checks.
-#
-# See golang.org/issue/9281
-
-* -text
-
-# The builders assume the git archive *.tar.gz of the tree is under
-# 25 MB but this repo is 31+ MB with all the images.
-# So exclude those.
-# See https://golang.org/issue/11199
-
-*.jpg export-ignore
-*.jpeg export-ignore
-*.png export-ignore
-*.gif export-ignore
-*.pdf export-ignore
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 15167cd..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code refers to The Go Authors for copyright purposes.
-# The master list of authors is in the main Go distribution,
-# visible at http://tip.golang.org/AUTHORS.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index d0485e8..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Contributing to Go
-
-Go is an open source project.
-
-It is the work of hundreds of contributors. We appreciate your help!
-
-## Filing issues
-
-When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
-
-1.  What version of Go are you using (`go version`)?
-2.  What operating system and processor architecture are you using?
-3.  What did you do?
-4.  What did you expect to see?
-5.  What did you see instead?
-
-General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
-The gophers there will answer or ask you to file an issue if you've tripped over a bug.
-
-## Contributing code
-
-Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
-before sending patches.
-
-Unless otherwise noted, the Go source files are distributed under
-the BSD-style license found in the LICENSE file.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
deleted file mode 100644
index 1c4577e..0000000
--- a/CONTRIBUTORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code was written by the Go contributors.
-# The master list of contributors is in the main Go distribution,
-# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 6a66aea..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/PATENTS b/PATENTS
deleted file mode 100644
index 7330990..0000000
--- a/PATENTS
+++ /dev/null
@@ -1,22 +0,0 @@
-Additional IP Rights Grant (Patents)
-
-"This implementation" means the copyrightable works distributed by
-Google as part of the Go project.
-
-Google hereby grants to You a perpetual, worldwide, non-exclusive,
-no-charge, royalty-free, irrevocable (except as stated in this section)
-patent license to make, have made, use, offer to sell, sell, import,
-transfer and otherwise run, modify and propagate the contents of this
-implementation of Go, where such license applies only to those patent
-claims, both currently owned or controlled by Google and acquired in
-the future, licensable by Google that are necessarily infringed by this
-implementation of Go.  This grant does not include claims that would be
-infringed only as a consequence of further modification of this
-implementation.  If you or your agent or exclusive licensee institute or
-order or agree to the institution of patent litigation against any
-entity (including a cross-claim or counterclaim in a lawsuit) alleging
-that this implementation of Go or any code incorporated within this
-implementation of Go constitutes direct or contributory patent
-infringement, or inducement of patent infringement, then any patent
-rights granted to you under this License for this implementation of Go
-shall terminate as of the date such litigation is filed.
diff --git a/README.md b/README.md
index 135d5ee..e5e7f43 100644
--- a/README.md
+++ b/README.md
@@ -1,61 +1,3 @@
-# Go Talks
+# Go Talks (obsolete)
 
-[![Go Reference](https://pkg.go.dev/badge/golang.org/x/talks.svg)](https://pkg.go.dev/golang.org/x/talks)
-
-This repository holds various Go talks that may be viewed with the present tool.
-
-## Viewing Locally
-
-To install the present tool, use `go get`:
-
-```
-go get golang.org/x/tools/cmd/present
-```
-
-To view talks, run `present` in the `content` directory and then
-visit [http://127.0.0.1:3999](http://127.0.0.1:3999) in your browser.
-
-## Report Issues / Send Patches
-
-This repository uses Gerrit for code changes. To learn how to submit changes to
-this repository, see https://golang.org/doc/contribute.html.
-
-The main issue tracker for the talks repository is located at
-https://github.com/golang/go/issues. Prefix your issue with "x/talks:" in the
-subject line, so it is easy to find.
-
-## Deploying
-
-To deploy these talks to talks.golang.org hosted on App Engine:
-
-1.	Add a version of `golang.org/x/tools/cmd/present` that you intend to
-	use in this deploy as a dependency of this module:
-
-	```
-	go get -d golang.org/x/tools/cmd/present@latest
-	```
-
-2.	Copy the contents of `golang.org/x/tools/cmd/present` to the root of
-	this repository:
-
-	```
-	rsync -r $(go list -f '{{.Dir}}' golang.org/x/tools/cmd/present)/ .
-	```
-
-3.	Run the deploy:
-
-	```
-	GO111MODULE=on gcloud --project=golang-org app deploy --no-promote app.yaml
-	```
-
-	This will create a new version, which can be viewed within the
-	[golang-org GCP project](https://console.cloud.google.com/appengine/versions?project=golang-org&serviceId=talks).
-
-4.	Check that the deployed version looks OK (click the version link in GCP).
-
-5.	If all is well, click "Migrate Traffic" to move 100% of the talks.golang.org
-	traffic to the new version.
-
-6.	Clean up the local file modifications that steps 1 and 2 caused.
-
-7.	You're done.
+The content of this repository has moved to [golang.org/x/website/_content/talks/](https://cs.opensource.google/go/x/website/+/master:_content/talks/).
diff --git a/app.yaml b/app.yaml
deleted file mode 100644
index ed889e7..0000000
--- a/app.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-service: talks
-runtime: go111
-
-env_variables:
-  GOLANGORG_CHECK_COUNTRY: true
-
-handlers:
-- url: /favicon.ico
-  static_files: static/favicon.ico
-  upload: static/favicon.ico
-  secure: always
-- url: /static
-  static_dir: static
-  secure: always
-- url: /.*
-  script: auto
-  secure: always
-
-nobuild_files: content/
diff --git a/codereview.cfg b/codereview.cfg
deleted file mode 100644
index 3f8b14b..0000000
--- a/codereview.cfg
+++ /dev/null
@@ -1 +0,0 @@
-issuerepo: golang/go
diff --git a/content/2009/go_talk-20091030.pdf b/content/2009/go_talk-20091030.pdf
deleted file mode 100644
index 5139ff2..0000000
--- a/content/2009/go_talk-20091030.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2010/ExpressivenessOfGo-2010.pdf b/content/2010/ExpressivenessOfGo-2010.pdf
deleted file mode 100644
index f1931d0..0000000
--- a/content/2010/ExpressivenessOfGo-2010.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2010/go_talk-20100112.html b/content/2010/go_talk-20100112.html
deleted file mode 100644
index e119dbb..0000000
--- a/content/2010/go_talk-20100112.html
+++ /dev/null
@@ -1,410 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go (January 12, 2010)</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="support/slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="support/slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0;  ">
-<img src="support/bumper480x270.png" style="margin: -135px 0 0 0;"/>
-</div>
-<br/>
-<img src="support/go-logo-white.png">
-<br/>
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<h2>Russ Cox</h2>
-<!-- <h3><i>rsc@google.com</i></h3> -->
-<br/>
-<h3>Stanford University<br/><br/>January 12, 2010</h3>
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage-collected</h2>
-	<h2>Systems</h2>
-	<h2>Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>History</h1>
-	
-	<h2>Design started in late 2007.</h2>
-	<h2>Implementation starting to work mid-2008.</h2>
-	<h2>Released as an open source project in November 2009.</h2>
-	<h2>Work continues.<h2>
-	<h2>Robert&nbsp;Griesemer, Ken&nbsp;Thompson, Rob&nbsp;Pike, Ian&nbsp;Lance&nbsp;Taylor, Russ&nbsp;Cox, many others</h2>
-</div>
-
-<div class="slide">
-	<h1>Why?</h1>
-	
-	<h2>Go fast!</h2>
-	<h2>Make programming fun again.</h2>
-</div>
-
-<div class="slide">
-	<h1>Why isn't programming fun?</h1>
-	
-	<div class="incremental">
-	<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
-	
-	<ul>
-		<li>verbose, lots of repetition</li>
-		<li>too much focus on type hierarchy</li>
-		<li>types get in the way as much as they help</li>
-		<li>compiles take far too long</li>
-	</ul>
-	</div>
-	
-	<div class="incremental">
-	<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
-	
-	<ul>
-		<li>errors at run time that should be caught statically</li>
-		<li>no compilation means slow code</li>
-	</ul>
-	</div>
-	
-	<h2 class="incremental">Can we combine the best of both?</h2>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-	
-	<h2>Make the language fast.</h2>
-	<h2>Make the tools fast.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Static Types</h1>
-	
-	<h2>Static types, but declarations can infer type from expression:</h2>
-	
-<pre>
-var one, hi = 1, "hello"
-
-var double = func(x int) int { return x*2 }
-</pre>
-
-	<h2>Not full Hindley-Milner type inference.</h2>
-</div>
-
-
-<div class="slide">
-	<h1>Go Approach: Methods</h1>
-	
-	<h2>Methods can be defined on any type.</h2>
-
-<pre>
-type Point struct {
-	X, Y float64
-}
-
-func (p Point) Abs() float64 {
-	return math.Sqrt(p.X*p.X + p.Y*p.Y)
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Methods</h1>
-	
-	<h2>Methods can be defined on any type.</h2>
-
-<pre>
-type MyFloat float64
-
-func (f MyFloat) Abs() float64 {
-	v := float64(f)
-	if v < 0 {
-		v = -v
-	}
-	return v
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Abstract Types</h1>
-	
-	<h2>An interface type lists a set of methods. Any value with those methods satisfies the interface.</h2>
-
-<pre>
-type Abser interface {
-	Abs() float64
-}
-
-func AbsPrinter(a Abser)
-</pre>
-
-	<h2>Can use Point or MyFloat (or ...):</h2>
-
-<pre>
-p := Point{3, 4}
-AbsPrinter(p)
-
-f := MyFloat(-10)
-AbsPrinter(f)
-</pre>
-
-	<h2>Notice that Point never declared that it implements Abser. It just does.  Same with MyFloat.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Packages</h1>
-
-	<h2>A Go program comprises one or more packages.</h2>
-	<h2>Each package is one or more source files compiled and imported as a unit.</h2>
-<pre>
-package draw
-
-type Point struct {
-	X, Y int
-}
-</pre>
-
-<pre>
-package main
-
-import "draw"
-
-var p draw.Point
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Visibility</h1>
-	
-	<h2>Inside a package, all locally defined names are visible in all source files.</h2>
-	
-	<h2>When imported, only the upper case names are visible.</h2>
-
-<pre>
-package draw
-
-type <span style="color: black;">Point</span> struct {
-	<span style="color: black;">X</span>, <span style="color: black;">Y</span> int
-	dist float64
-}
-
-type cache map[Point] float64
-</pre>
-
-<h2>Clients that <code>import "draw"</code> can use the black names only.</h2>
-
-<h2>&ldquo;Shift is the new <code>public</code>.&rdquo;</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Concurrency</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Two expensive computations in parallel.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Synchronization</h1>
-	
-	<h2>Use explicit messages to communicate and synchronize.</h2>
-	
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch <- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := <-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-	<h2>Notice communication of result in addition to synchronization.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Fast: Language</h1>
-	
-	<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
-	
-	<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
-	
-	<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
-	
-	<h2 class="incremental">Visibility: inferred from case of name.</h2>
-	
-	<h2 class="incremental">Concurrency: lightweight way to start new thread of control.</h2>
-	
-	<h2 class="incremental">Synchronization: explicit, easy message passing.</h2>
-
-	<br/>
-	
-	<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compile fast</h1>
-
-	<div class="incremental">
-	<h2>Observation: much of the compile time for a source file is spent processing
-	other, often unrelated files.</h2>
-
-	<h2>In C: <code>a.c</code> includes <code>b.h</code>, which includes <code>c.h</code>, which includes <code>d.h</code>.
-	</h2>
-	
-	<h2>Except that it's more often a tree instead of a chain.</h2>
-	
-	<h2>On my Mac (OS X 10.5.8, gcc 4.0.1):</h2>
-	<ul>
-	<li>C: <code>#include &lt;stdio.h&gt;</code> reads 360 lines from 9 files.
-	<li>C++: <code>#include &lt;iostream&gt;</code> reads 25,326 lines from 131 files.
-	<li>Objective C: <code>#include &lt;Carbon/Carbon.h&gt;</code> reads 124,730 lines from 689 files.
-	</ul>
-	
-	<h2>And we haven't done any real work yet!</h2>
-	
-	<h2>Same story in Java, Python, but reading binaries instead of source files.</h2>
-	</div>
-</div>
-
-<div class="slide">
-	<h1>Implementation: Summarize Dependencies</h1>
-	
-<pre>
-package gui
-
-import "draw"
-
-type Mouse struct {
-	Loc draw.Point
-	Buttons uint
-}
-</pre>
-	<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).</h2>
-
-</div>
-
-<div class="slide">
-	<h1>Implementation: Summarize Dependencies</h1>
-
-	<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).  Pseudo-object:</h2>
-
-<pre>
-package gui
-type draw.Point struct {
-	X, Y int
-}
-type gui.Mouse struct {
-	Loc draw.Point
-	Buttons uint
-}
-</pre>
-
-	<h2>A file that imports <code>gui</code> compiles without consulting <code>draw</code> or its dependencies.</h2>
-	
-	<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing types from 7 packages.</h2>
-
-	<h2>Tiny effect in this program but can be exponential in large programs.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compilation Demo</h1>
-	
-	<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<div class="incremental">
-	<div>
-	<h2>Open source:</h2>
-	<ul>
-	<li>released on November 10, 2009
-	<li>regular releases (~ weekly)
-	<li>all development done in public Mercurial repository
-	<li>outside contributions welcome
-	</ul>
-	</div>
-	
-	<div>
-	<h2>Portable:</h2>
-	<ul>
-	<li>FreeBSD, Linux, OS X (x86, x86-64)
-	<li>(in progress) Linux arm, Native Client x86, Windows x86.
-	</ul>
-	</div>
-	
-	<div>
-	<h2>Still in progress, experimental.  Yet to come:</h2>
-	<ul>
-	<li>mature garbage collector
-	<li>generics?
-	<li>exceptions?
-	<li>unions or sum types?
-	</ul>
-	</div>
-	</div>
-
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="support/bumper640x360.png">
-	</center>
-	<br><br>
-	<div style="color: #ffcc00;">
-	<!-- <h3><i>rsc@google.com</i></h3> -->
-	</div>
-</div>
-
-</body></html>
diff --git a/content/2010/go_talk-20100121.html b/content/2010/go_talk-20100121.html
deleted file mode 100644
index 4c88a1b..0000000
--- a/content/2010/go_talk-20100121.html
+++ /dev/null
@@ -1,452 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go, Networked (January 21, 2010)</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="support/slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="support/slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0;  ">
-<img src="support/gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
-</div>
-<br/>
-<img src="support/go-logo-white.png">
-<br/>
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<h2>Russ Cox</h2>
-<!-- <h3><i>rsc@google.com</i></h3> -->
-<br/>
-<h3>CNS Winter Research Review<br/><br/>January 21, 2010</h3>
-<br/>
-<br/>
-<!--
-<h4><i>click to start; then left/right arrow to change slides</i></h4> -->
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage-collected</h2>
-	<h2>Systems</h2>
-	<h2>Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>History</h1>
-	
-	<h2>Design started in late 2007.</h2>
-	<h2>Implementation starting to work mid-2008.</h2>
-	<h2>Released as an open source project in November 2009.</h2>
-	<h2>Work continues.</h2>
-	<h2>Robert&nbsp;Griesemer, Ken&nbsp;Thompson, Rob&nbsp;Pike, Ian&nbsp;Lance&nbsp;Taylor, Russ&nbsp;Cox, many others</h2>
-</div>
-
-<div class="slide">
-	<h1>Goals and Motivation</h1>
-	
-	<h2>Go fast!</h2>
-	<h2>Make programming fun again.</h2>
-	<h2>Targeted at systems software, broadly.</h2>
-</div>
-
-<div class="slide">
-	<h1>Why isn't programming fun?</h1>
-	
-	<div class="incremental">
-	<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
-	
-	<ul>
-		<li>verbose, lots of repetition</li>
-		<li>too much focus on type hierarchy</li>
-		<li>types get in the way as much as they help</li>
-		<li>compiles take far too long</li>
-	</ul>
-	</div>
-	
-	<div class="incremental">
-	<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
-	
-	<ul>
-		<li>errors at run time that should be caught statically</li>
-		<li>no compilation means slow code</li>
-	</ul>
-	</div>
-	
-	<h2 class="incremental">Can we combine the best of both?</h2>
-</div>
-
-<div class="slide">
-	<h1>Why a new language?</h1>
-	
-	<div class="incremental">
-	<h2>No new systems language in 10+ years.</h2>
-	<h2>Current languages designed before ...</h2>
-	<h3>... rise of large-scale, networked and multicore computing</h3>
-	<h3>... rise of Internet-scale distributed development (many libraries)</h3>
-	</div>
-</div>
-	
-<div class="slide">
-	<h1>Go</h1>
-	
-	<h2>Make the language fast.</h2>
-	<h2>Make the tools fast.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compilation Demo</h1>
-	
-	<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go in one slide</h1>
-	
-	<h2 class="incremental">Lightweight syntax.</h2>
-	
-	<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
-	
-	<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
-	
-	<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
-	
-	<h2 class="incremental">Visibility: inferred from case of name.</h2>
-
-	<h2 class="incremental">First-class functions.</h2>
-	
-	<h2 class="incremental">Garbage collection.</h2>
-
-	<br/>
-	
-	<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, concurrently</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Two expensive computations in parallel.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, concurrently</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-	for {
-		rw := l.Accept()
-		conn := newConn(rw, handler)
-		go conn.serve()
-	}
-</pre>
-
-	<h2>Concurrent web server.</h2>
-	<h2>Network connections multiplexed onto epoll.</h2>
-		<ul>
-		<li>many blocked Read calls != many blocked OS threads</li>
-		</ul>
-
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>Use explicit messages to communicate and synchronize.</h2>
-	
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch <- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := <-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-	<h2>Notice communication of result in addition to synchronization.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client</h2>
-
-<pre>
-func (client *Client) Call(method string, args, reply interface{}) os.Error {
-    // Send RPC message.
-    call := client.Go(method, args, reply, nil)
-	
-    // Read reply from Done channel.
-    <-call.Done
-
-    return call.Error
-}
-</pre>	
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		<font style="color: black;">resp := client.readResponse()</font>
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Read response from network.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		<font style="color: black;">client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()</font>
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Look up request by sequence number.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		<font style="color: black;">if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)</font>
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Decode response fields from payload.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		<font style="color: black;">c.Done <- c</font>
-	}
-}
-</pre>
-<h2>Tell client that it finished.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-
-<h2>Can create multiple Calls with same Done channel
-and distinguish which finished by inspecting value sent on channel.
-</h2>
-
-</div>
-
-<div class="slide">
-	<h1>Goroutine demo</h1>
-	
-	<h2>Chain together 100,000 goroutines connected by 100,001 channels.</h2>
-	
-	<h2>Send a value to one end of the chain.</h2>
-	
-	<h2>Each passes it along, increments.</h2>
-	
-	<h2>Receive value out the other end of the chain.</h2>
-</div>
-	
-
-<div class="slide">
-	<h1>Go Status</h1>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source:</h2>
-	<ul>
-	<li>released on November 10, 2009
-	<li>regular releases (~ weekly)
-	<li>all development done in public Mercurial repository
-	<li>outside contributions welcome
-	<li>two independent compiler implementations
-	<li>XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ...
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source</h2>
-
-	<h2>Portable:</h2>
-	<ul>
-	<li>FreeBSD, Linux, OS X (x86, x86-64)
-	<li>(in progress) Linux arm, Native Client x86, Windows x86.
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source</h2>
-	<h2>Portable</h2>
-
-	<h2>Still in progress, experimental.  Yet to come:</h2>
-	<ul>
-	<li>production garbage collector
-	<li>generics?
-	<li>exceptions?
-	<li>unions or sum types?
-	</ul>
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="support/bumper640x360.png">
-	</center>
-	<br><br>
-	<div style="color: #ffcc00;">
-	<!-- <h3><i>rsc@google.com</i></h3> -->
-	</div>
-</div>
-
-</body></html>
diff --git a/content/2010/go_talk-20100323.html b/content/2010/go_talk-20100323.html
deleted file mode 100644
index 277546d..0000000
--- a/content/2010/go_talk-20100323.html
+++ /dev/null
@@ -1,395 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go Tech Talk</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="support/slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="support/slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<br/>
-<br/>
-<img src="support/go-logo-white.png" width="588px" height="217px">
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<br/>
-<h3>Sydney University<br/><br/>March 23, 2010</h3>
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage Collected</h2>
-	<h2>Systems Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Hello, world 2.0</h1>
-
-	<h2>Serving <a href="http://localhost:8080/world">http://localhost:8080/world</a></h2>
-<pre>
-package main
-
-import (
-	"fmt"
-	"http"
-)
-
-func handler(c *http.Conn, r *http.Request) { 
-	fmt.Fprintf(c, "Hello, %s.", r.URL.Path[1:]) 
-}
-
-func main() {
-	http.ListenAndServe(":8080",
-			http.HandlerFunc(handler))
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-	
-	<h2>It's about two years old:</h2>
-	<ul>
-		<li>Design started in late 2007</li>
-		<li>Implementation starting to work mid-2008</li>
-		<li>Released as an open source project in November 2009</li>
-		<li>Development continues with an active community</li>
-	</ul>
-
-	<h2>Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:</h2>
-	<ul>
-		<li>Large scale, networked computing, such as Google web search</li>
-		<li>Multi-core hardware</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-	
-	<h2>Older languages are also frustrating on a day-to-day basis</h2>
-	<h2>Statically-typed languages (C, C++, Java) have issues:</h2>
-	<ul>
-		<li>Edit-Compile-Run cycle takes far too long</li>
-		<li>Type hierarchy can hurt as much as it helps</li>
-	</ul>
-<div style="text-align:center">
-<img src="support/java-typing.png" width="800px" height="90px"><br>
-</div>
-	
-	<h2>Dynamic languages (Python, JavaScript) fix some issues but introduce others:</h2>
-	<ul>
-		<li>No compilation means slow code</li>
-		<li>Runtime errors that should be caught statically</li>
-	</ul>
-
-	<h2>Go has the lighter feel of a scripting language but is compiled</h2>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-
-	<h2>Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:</h2>
-	<ul>
-		<li>XKCD's #1 Programmer Excuse for Legitimately Slacking Off: &quot;<a href="http://xkcd.com/303/">My Code's Compiling</a>&quot;</li>
-	</ul>
-
-	<h2>On a Mac (OS X 10.5.8, gcc 4.0.1):</h2>
-	<ul>
-		<li>C: <code>#include &lt;stdio.h&gt;</code> reads 360 lines from 9 files</li>
-		<li>C++: <code>#include &lt;iostream&gt;</code> reads 25,326 lines from 131 files</li>
-		<li>Objective-C: <code>#include &lt;Carbon/Carbon.h&gt;</code> reads 124,730 lines from 689 files</li>
-		<li>We haven't done any real work yet!</li>
-	</ul>
-				
-	<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing 7 packages</h2>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-
-	<h2>Compilation demo</h2>
-</div>
-
-<div class="slide">
-	<h1>Experimental</h1>
-	
-	<h2>Go is still unproven</h2>
-	<h2>Language is still evolving</h2>
-	<h2>Package library is incomplete</h2>
-	<h2>Concurrent garbage collection is an active research problem</h2>
-	<h2>Reviving forgotten concepts:</h2>
-	<ul>
-		<li>Go's concurrency is strongly influenced by <i>Communicating Sequential Processes</i> (Hoare, 1978)</li>
-		<li>Go has types and interfaces, but no inheritance. It is arguably more object-oriented than previously mentioned languages, being closer to the original Smalltalk meaning (1970s)</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Unix philosophy: write <i>programs</i> that do one thing and do it well</h2>
-	<h2>Connect them with <i>pipes</i>:</h2>
-	<ul>
-		<li>How many lines of test code are there in the Go standard library?</li>
-		<li><code>find ~/go/src/pkg | grep _test.go$ | xargs wc -l</code></li>
-	</ul>
-
-	<h2>Unlike other languages, Go makes it easy to:</h2>
-	<ul>
-		<li>Launch <i>goroutines</i></li>
-		<li>Connect them with <i>channels</i></li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Start a new flow of control with the <code>go</code> keyword</h2>
-	<h2>Parallel computation is easy:</h2>
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Roughly speaking, a goroutine is like a thread, but lighter weight:</h2>
-	<ul>
-		<li>Goroutines have segmented stacks, and typically smaller stacks</li>
-		<li>This requires compiler support. Goroutines can't just be a C++ library on top of a thread library</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Consider web servers ("the C10k problem"):</h2>
-	<ul>
-		<li>"Thread per connection" approach is conceptually neat, but doesn't scale well in practice</li>
-		<li>What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug</li>
-		<li>We think "goroutine per connection" can scale well, and is conceptually neat</li>
-	</ul>
-<pre>
-	for {
-		rw := socket.Accept()
-		conn := newConn(rw, handler)
-		go conn.serve()
-	}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Let's look again at our simple parallel computation:</h2>
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>This story is incomplete:</h2>
-	<ul>
-		<li>How do we know when the two computations are done?</li>
-		<li>What are their values?</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Goroutines communicate with other goroutines via channels</h2>
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch &lt;- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := &lt;-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>In traditional concurrent programs, you <i>communicate by sharing memory</i>. In Go, you <i>share memory by communicating</i>:</h2>
-	<ul>
-		<li>Communication (the <code>&lt;-</code> operator) is sharing and synchronization</li>
-	</ul>
-
-	<h2>Threads and locks are concurrency primitives; CSP is a concurrency model:</h2>
-	<ul>
-		<li>Analogy: &quot;Go To Statement Considered Harmful&quot; (Dijsktra, 1968)</li>
-		<li><code>goto</code> is a control flow primitive; structured programming (<code>if</code> statements, <code>for</code> loops, function calls) is a control flow model</li>
-	</ul>
-
-	<h2>Learning CSP changes the way you think about concurrent programming:</h2>
-	<ul>
-		<li>Every language has its grain. If your Go program uses mutexes, you're probably working against the grain</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Garbage Collected</h1>
-	
-	<h2>Automatic memory management makes writing (and maintaining) programs easier</h2>
-	<h2>Especially in a concurrent world:</h2>
-	<ul>
-		<li>Who &quot;owns&quot; a shared piece of memory, and is responsible for destroying it?</li>
-	</ul>
-
-	<h2>Large C++ programs usually end up with semi-automatic memory management anyway, via &quot;smart pointers&quot;</h2>
-	<h2>Mixing the two models can be problematic:</h2>
-	<ul>
-		<li>Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Garbage Collected</h1>
-
-	<h2>Go is also a safer language:</h2>
-	<ul>
-		<li>Pointers but no pointer arithmetic</li>
-		<li>No dangling pointers</li>
-		<li>Variables are zero-initialized</li>
-		<li>Array access is bounds-checked</li>
-	</ul>
-
-	<h2>No buffer overflow exploits</h2>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-
-	<h2>This just means you could write decently large programs in Go:</h2>
-	<ul>
-		<li>Web servers</li>
-		<li>Web browsers</li>
-		<li>Web crawlers</li>
-		<li>Search indexers</li>
-		<li>Databases</li>
-		<li>Word processors</li>
-		<li>Integrated Development Environments (IDEs)</li>
-		<li>Operating systems</li>
-		<li>...</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-
-	<h2>Garbage collection has a reputation for being &quot;slower&quot;</h2>
-	<h2>We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:</h2>
-	<ul>
-		<li>Fast and buggy is worse than almost-as-fast and correct</li>
-		<li>It is easier to optimize a correct program than to correct an optimized program</li>
-		<li>Fundamentally, it's simply a trade-off we're willing to make</li>
-	</ul>
-
-	<h2>Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:</h2>
-<pre>
-type Point struct { X, Y int }
-type Rect struct { P0, P1 Point }
-
-// or ...
-
-type Rect struct { X0, Y0, X1, Y1 int }
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-	
-	<h2>Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html</h2>
-
-<h2>
-&quot;[Git] is known to be very fast. It is written in C. A Java version
-JGit was made. It was considerably slower. Handling of memory and lack
-of unsigned types was some of the important reasons.
-</h2>
-
-<h2>Shawn O. Pearce wrote on the git mailinglist:</h2>
-<ul><li>&quot;JGit struggles with not
-having an efficient way to represent a SHA-1. C can just say &quot;unsigned
-char[20]&quot; and have it inline into the container's memory allocation. A
-byte[20] in Java will cost an *additional* 16 bytes of memory, and be
-slower to access because the bytes themselves are in a different area
-of memory from the container object. We try to work around it by
-converting from a byte[20] to 5 ints, but that costs us machine
-instructions&quot;
-</li></ul>
-
-<h2>
-Like C, Go does allow unsigned types and defining data structures
-containing other data structures as continuous blocks of memory.&quot;
-</h2>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage Collected</h2>
-	<h2>Systems Language</h2>
-
-	<h2>And more:</h2>
-	<ul>
-		<li>I haven't talked about the type system, interfaces, slices, closures, selects, ...</li>
-		<li>Documentation, mailing list, source code all online</li>
-	</ul>
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="support/bumper640x360.png" width="640px" height="360px">
-	</center>
-</div>
-
-</body></html>
diff --git a/content/2010/gofrontend-gcc-summit-2010.pdf b/content/2010/gofrontend-gcc-summit-2010.pdf
deleted file mode 100644
index 157fd76..0000000
--- a/content/2010/gofrontend-gcc-summit-2010.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2010/io/balance.go b/content/2010/io/balance.go
deleted file mode 100644
index 0214750..0000000
--- a/content/2010/io/balance.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"container/heap"
-	"flag"
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-const nRequester = 100
-const nWorker = 10
-
-var roundRobin = flag.Bool("r", false, "use round-robin scheduling")
-
-// Simulation of some work: just sleep for a while and report how long.
-func op() int {
-	n := rand.Int63n(1e9)
-	time.Sleep(time.Duration(nWorker * n))
-	return int(n)
-}
-
-type Request struct {
-	fn func() int
-	c  chan int
-}
-
-func requester(work chan Request) {
-	c := make(chan int)
-	for {
-		time.Sleep(time.Duration(rand.Int63n(nWorker * 2e9)))
-		work <- Request{op, c}
-		<-c
-	}
-}
-
-type Worker struct {
-	i        int
-	requests chan Request
-	pending  int
-}
-
-func (w *Worker) work(done chan *Worker) {
-	for {
-		req := <-w.requests
-		req.c <- req.fn()
-		done <- w
-	}
-}
-
-type Pool []*Worker
-
-func (p Pool) Len() int { return len(p) }
-
-func (p Pool) Less(i, j int) bool {
-	return p[i].pending < p[j].pending
-}
-
-func (p *Pool) Swap(i, j int) {
-	a := *p
-	a[i], a[j] = a[j], a[i]
-	a[i].i = i
-	a[j].i = j
-}
-
-func (p *Pool) Push(x interface{}) {
-	a := *p
-	n := len(a)
-	a = a[0 : n+1]
-	w := x.(*Worker)
-	a[n] = w
-	w.i = n
-	*p = a
-}
-
-func (p *Pool) Pop() interface{} {
-	a := *p
-	*p = a[0 : len(a)-1]
-	w := a[len(a)-1]
-	w.i = -1 // for safety
-	return w
-}
-
-type Balancer struct {
-	pool Pool
-	done chan *Worker
-	i    int
-}
-
-func NewBalancer() *Balancer {
-	done := make(chan *Worker, nWorker)
-	b := &Balancer{make(Pool, 0, nWorker), done, 0}
-	for i := 0; i < nWorker; i++ {
-		w := &Worker{requests: make(chan Request, nRequester)}
-		heap.Push(&b.pool, w)
-		go w.work(b.done)
-	}
-	return b
-}
-
-func (b *Balancer) balance(work chan Request) {
-	for {
-		select {
-		case req := <-work:
-			b.dispatch(req)
-		case w := <-b.done:
-			b.completed(w)
-		}
-		b.print()
-	}
-}
-
-func (b *Balancer) print() {
-	sum := 0
-	sumsq := 0
-	for _, w := range b.pool {
-		fmt.Printf("%d ", w.pending)
-		sum += w.pending
-		sumsq += w.pending * w.pending
-	}
-	avg := float64(sum) / float64(len(b.pool))
-	variance := float64(sumsq)/float64(len(b.pool)) - avg*avg
-	fmt.Printf(" %.2f %.2f\n", avg, variance)
-}
-
-func (b *Balancer) dispatch(req Request) {
-	if *roundRobin {
-		w := b.pool[b.i]
-		w.requests <- req
-		w.pending++
-		b.i++
-		if b.i >= len(b.pool) {
-			b.i = 0
-		}
-		return
-	}
-
-	w := heap.Pop(&b.pool).(*Worker)
-	w.requests <- req
-	w.pending++
-	//	fmt.Printf("started %p; now %d\n", w, w.pending)
-	heap.Push(&b.pool, w)
-}
-
-func (b *Balancer) completed(w *Worker) {
-	if *roundRobin {
-		w.pending--
-		return
-	}
-
-	w.pending--
-	//	fmt.Printf("finished %p; now %d\n", w, w.pending)
-	heap.Remove(&b.pool, w.i)
-	heap.Push(&b.pool, w)
-}
-
-func main() {
-	flag.Parse()
-	work := make(chan Request)
-	for i := 0; i < nRequester; i++ {
-		go requester(work)
-	}
-	NewBalancer().balance(work)
-}
diff --git a/content/2010/io/decrypt.go b/content/2010/io/decrypt.go
deleted file mode 100644
index 5c30fe2..0000000
--- a/content/2010/io/decrypt.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-// This code differs from the slides in that it handles errors.
-
-package main
-
-import (
-	"compress/gzip"
-	"crypto/aes"
-	"crypto/cipher"
-	"io"
-	"log"
-	"os"
-)
-
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
-	r, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	var w io.Writer
-	w, err = os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	w = cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}
-	w2, err := gzip.NewWriter(w)
-	if err != nil {
-		return err
-	}
-	defer w2.Close()
-	_, err = io.Copy(w2, r)
-	return err
-}
-
-func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) error {
-	f, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	r := cipher.StreamReader{S: cipher.NewOFB(c, iv), R: f}
-	r2, err := gzip.NewReader(r)
-	if err != nil {
-		return err
-	}
-	w, err := os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	_, err = io.Copy(w, r2)
-	return err
-}
-
-func main() {
-	err := EncryptAndGzip(
-		"/tmp/passwd.gz",
-		"/etc/passwd",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-	err = DecryptAndGunzip(
-		"/dev/stdout",
-		"/tmp/passwd.gz",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/content/2010/io/encrypt.go b/content/2010/io/encrypt.go
deleted file mode 100644
index c942fe5..0000000
--- a/content/2010/io/encrypt.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-// This code differs from the slides in that it handles errors.
-
-package main
-
-import (
-	"compress/gzip"
-	"crypto/aes"
-	"crypto/cipher"
-	"io"
-	"log"
-	"os"
-)
-
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
-	r, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	var w io.WriteCloser
-	w, err = os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	w, err = gzip.NewWriter(w)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	_, err = io.Copy(cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}, r)
-	return err
-}
-
-func main() {
-	err := EncryptAndGzip(
-		"/tmp/passwd.gz",
-		"/etc/passwd",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/content/2010/io/eval1.go b/content/2010/io/eval1.go
deleted file mode 100644
index eef7741..0000000
--- a/content/2010/io/eval1.go
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// Generic expression parser/evaluator
-
-type Value interface {
-	String() string
-	BinaryOp(op string, y Value) Value
-}
-
-type Parser struct {
-	precTab map[string]int
-	newVal  func(string) Value
-	src     string
-	pos     int
-	tok     string
-}
-
-const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-func (p *Parser) stop(c uint8) bool {
-	switch {
-	case p.pos >= len(p.src):
-		return true
-	case c == '"':
-		if p.src[p.pos] == '"' {
-			p.pos++
-			return true
-		}
-		return false
-	case strings.IndexRune(alphanum, int(c)) >= 0:
-		return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
-	}
-	return true
-}
-
-func (p *Parser) next() {
-	// skip blanks
-	for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
-	}
-	if p.pos >= len(p.src) {
-		p.tok = ""
-		return
-	}
-	start := p.pos
-	c := p.src[p.pos]
-	for p.pos < len(p.src) {
-		p.pos++
-		if p.stop(c) {
-			break
-		}
-	}
-	p.tok = p.src[start:p.pos]
-}
-
-func (p *Parser) binaryExpr(prec1 int) Value {
-	x := p.newVal(p.tok)
-	p.next()
-	for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
-		for p.precTab[p.tok] == prec {
-			op := p.tok
-			p.next()
-			y := p.binaryExpr(prec + 1)
-			x = x.BinaryOp(op, y)
-		}
-	}
-	return x
-}
-
-func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
-	var p Parser
-	p.precTab = precTab
-	p.newVal = newVal
-	p.src = src
-	p.next()
-	return p.binaryExpr(1)
-}
-
-// Command-line expression evaluator
-
-func main() {
-	r := bufio.NewReader(os.Stdin)
-	for {
-		fmt.Printf("> ")
-		line, err := r.ReadString('\n')
-		if err != nil {
-			break
-		}
-		fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
-	}
-}
-
-// Custom grammar and values
-
-var precTab = map[string]int{
-	"&&": 1,
-	"||": 2,
-	"==": 3,
-	"!=": 3,
-	"<":  3,
-	"<=": 3,
-	">":  3,
-	">=": 3,
-	"+":  4,
-	"-":  4,
-	"*":  5,
-	"/":  5,
-	"%":  5,
-}
-
-func newVal(lit string) Value {
-	x, err := strconv.Atoi(lit)
-	if err == nil {
-		return Int(x)
-	}
-	b, err := strconv.ParseBool(lit)
-	if err == nil {
-		return Bool(b)
-	}
-	return Error(fmt.Sprintf("illegal literal '%s'", lit))
-}
-
-type Error string
-
-func (e Error) String() string                    { return string(e) }
-func (e Error) BinaryOp(op string, y Value) Value { return e }
-
-type Int int
-
-func (x Int) String() string { return strconv.Itoa(int(x)) }
-func (x Int) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Int:
-		switch op {
-		case "+":
-			return x + y
-		case "-":
-			return x - y
-		case "*":
-			return x * y
-		case "/":
-			return x / y
-		case "%":
-			return x % y
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		case "<":
-			return Bool(x < y)
-		case "<=":
-			return Bool(x <= y)
-		case ">":
-			return Bool(x > y)
-		case ">=":
-			return Bool(x >= y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type Bool bool
-
-func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
-func (x Bool) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Bool:
-		switch op {
-		case "&&":
-			return Bool(x && y)
-		case "||":
-			return Bool(x || y)
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-func trace(newVal func(string) Value) func(string) Value {
-	return func(s string) Value {
-		v := newVal(s)
-		fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
-		return &traceValue{v}
-	}
-}
-
-type traceValue struct {
-	Value
-}
-
-func (x *traceValue) BinaryOp(op string, y Value) Value {
-	z := x.Value.BinaryOp(op, y.(*traceValue).Value)
-	fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
-	return &traceValue{z}
-}
-
-func (x *traceValue) String() string {
-	s := x.Value.String()
-	fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
-	return s
-}
-
-func fmtv(v Value) string {
-	t := fmt.Sprintf("%T", v)
-	if i := strings.LastIndex(t, "."); i >= 0 { // strip package
-		t = t[i+1:]
-	}
-	return fmt.Sprintf("%s(%#v)", t, v)
-}
diff --git a/content/2010/io/eval2.go b/content/2010/io/eval2.go
deleted file mode 100644
index d138a51..0000000
--- a/content/2010/io/eval2.go
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// Generic expression parser/evaluator
-
-type Value interface {
-	String() string
-	BinaryOp(op string, y Value) Value
-}
-
-type Parser struct {
-	precTab map[string]int
-	newVal  func(string) Value
-	src     string
-	pos     int
-	tok     string
-}
-
-const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-func (p *Parser) stop(c uint8) bool {
-	switch {
-	case p.pos >= len(p.src):
-		return true
-	case c == '"':
-		if p.src[p.pos] == '"' {
-			p.pos++
-			return true
-		}
-		return false
-	case strings.IndexRune(alphanum, int(c)) >= 0:
-		return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
-	}
-	return true
-}
-
-func (p *Parser) next() {
-	// skip blanks
-	for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
-	}
-	if p.pos >= len(p.src) {
-		p.tok = ""
-		return
-	}
-	start := p.pos
-	c := p.src[p.pos]
-	for p.pos < len(p.src) {
-		p.pos++
-		if p.stop(c) {
-			break
-		}
-	}
-	p.tok = p.src[start:p.pos]
-}
-
-func (p *Parser) binaryExpr(prec1 int) Value {
-	x := p.newVal(p.tok)
-	p.next()
-	for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
-		for p.precTab[p.tok] == prec {
-			op := p.tok
-			p.next()
-			y := p.binaryExpr(prec + 1)
-			x = x.BinaryOp(op, y)
-		}
-	}
-	return x
-}
-
-func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
-	var p Parser
-	p.precTab = precTab
-	p.newVal = newVal
-	p.src = src
-	p.next()
-	return p.binaryExpr(1)
-}
-
-// Command-line expression evaluator
-
-func main() {
-	r := bufio.NewReader(os.Stdin)
-	for {
-		fmt.Printf("> ")
-		line, err := r.ReadString('\n')
-		if err != nil {
-			break
-		}
-		fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
-	}
-}
-
-// Custom grammar and values
-
-var precTab = map[string]int{
-	"&&": 1,
-	"||": 2,
-	"==": 3,
-	"!=": 3,
-	"<":  3,
-	"<=": 3,
-	">":  3,
-	">=": 3,
-	"+":  4,
-	"-":  4,
-	"*":  5,
-	"/":  5,
-	"%":  5,
-}
-
-func newVal(lit string) Value {
-	x, err := strconv.Atoi(lit)
-	if err == nil {
-		return Int(x)
-	}
-	b, err := strconv.ParseBool(lit)
-	if err == nil {
-		return Bool(b)
-	}
-	s, err := strconv.Unquote(lit)
-	if err == nil {
-		return String(s)
-	}
-	return Error(fmt.Sprintf("illegal literal '%s'", lit))
-}
-
-type Error string
-
-func (e Error) String() string                    { return string(e) }
-func (e Error) BinaryOp(op string, y Value) Value { return e }
-
-type Int int
-
-func (x Int) String() string { return strconv.Itoa(int(x)) }
-func (x Int) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case String:
-		switch op {
-		case "*":
-			return String(strings.Repeat(string(y), int(x)))
-		}
-	case Int:
-		switch op {
-		case "+":
-			return x + y
-		case "-":
-			return x - y
-		case "*":
-			return x * y
-		case "/":
-			return x / y
-		case "%":
-			return x % y
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		case "<":
-			return Bool(x < y)
-		case "<=":
-			return Bool(x <= y)
-		case ">":
-			return Bool(x > y)
-		case ">=":
-			return Bool(x >= y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type Bool bool
-
-func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
-func (x Bool) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Bool:
-		switch op {
-		case "&&":
-			return Bool(x && y)
-		case "||":
-			return Bool(x || y)
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type String string
-
-func (x String) String() string { return strconv.Quote(string(x)) }
-func (x String) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Int:
-		switch op {
-		case "*":
-			return String(strings.Repeat(string(x), int(y)))
-		}
-	case String:
-		switch op {
-		case "+":
-			return x + y
-		case "<":
-			return Bool(x < y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-func trace(newVal func(string) Value) func(string) Value {
-	return func(s string) Value {
-		v := newVal(s)
-		fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
-		return &traceValue{v}
-	}
-}
-
-type traceValue struct {
-	Value
-}
-
-func (x *traceValue) BinaryOp(op string, y Value) Value {
-	z := x.Value.BinaryOp(op, y.(*traceValue).Value)
-	fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
-	return &traceValue{z}
-}
-
-func (x *traceValue) String() string {
-	s := x.Value.String()
-	fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
-	return s
-}
-
-func fmtv(v Value) string {
-	t := fmt.Sprintf("%T", v)
-	if i := strings.LastIndex(t, "."); i >= 0 { // strip package
-		t = t[i+1:]
-	}
-	return fmt.Sprintf("%s(%#v)", t, v)
-}
diff --git a/content/2010/io/talk.pdf b/content/2010/io/talk.pdf
deleted file mode 100644
index aff42c2..0000000
--- a/content/2010/io/talk.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2010/support/bumper480x270.png b/content/2010/support/bumper480x270.png
deleted file mode 100644
index cf18715..0000000
--- a/content/2010/support/bumper480x270.png
+++ /dev/null
Binary files differ
diff --git a/content/2010/support/bumper640x360.png b/content/2010/support/bumper640x360.png
deleted file mode 100644
index a5073e0..0000000
--- a/content/2010/support/bumper640x360.png
+++ /dev/null
Binary files differ
diff --git a/content/2010/support/go-logo-white.png b/content/2010/support/go-logo-white.png
deleted file mode 100644
index fa29169..0000000
--- a/content/2010/support/go-logo-white.png
+++ /dev/null
Binary files differ
diff --git a/content/2010/support/java-typing.png b/content/2010/support/java-typing.png
deleted file mode 100644
index 54abf01..0000000
--- a/content/2010/support/java-typing.png
+++ /dev/null
Binary files differ
diff --git a/content/2010/support/slidy.css b/content/2010/support/slidy.css
deleted file mode 100644
index e9ff532..0000000
--- a/content/2010/support/slidy.css
+++ /dev/null
@@ -1,277 +0,0 @@
-/* http://www.w3.org/Talks/Tools/Slidy/slidy.css
-
-   Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
-   W3C liability, trademark, document use and software licensing
-   rules apply, see:
-
-   http://www.w3.org/Consortium/Legal/copyright-documents
-   http://www.w3.org/Consortium/Legal/copyright-software
-*/
-body
-{
-  margin: 0 0 0 0;
-  padding: 0 0 0 0;
-  width: 100%;
-  height: 100%;
-  color: black;
-  background-color: white;
-  font-family: "Lucida Sans", "Lucida Grande", Lucida, sans-serif;
-  font-size: 14pt;
-}
-
-.hidden { display: none; visibility: hidden }
-
-div.toolbar {
-  position: fixed; z-index: 200;
-  top: auto; bottom: 0; left: 0; right: 0;
-  height: 1.2em; text-align: right;
-  padding-left: 1em;
-  padding-right: 1em; 
-  font-size: 60%;
-  color: red; background: rgb(240,240,240);
-}
-
-div.background {
-  display: none;
-}
-
-div.handout {
-  margin-left: 20px;
-  margin-right: 20px;
-}
-
-div.slide.titlepage {
-  color: white;
-  background: black;
-  text-align: center;
-}
-
-div.slide {
-  z-index: 20;
-  margin: 0 0 0 0;
-  padding-top: 0;
-  padding-bottom: 0;
-  padding-left: 20px;
-  padding-right: 20px;
-  border-width: 0;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  line-height: 120%;
-  background-color: transparent;
-}
-
-/* this rule is hidden from IE 6 and below which don't support + selector */
-div.slide + div[class].slide { page-break-before: always;}
-
-div.slide h1 {
-  padding-left: 20px;
-  padding-right: 20px;
-  padding-top: 10px;
-  padding-bottom: 10px;
-  margin-top: 0;
-  margin-left: 0;
-  margin-right: 0;
-  margin-bottom: 0.5em;
-  border-bottom: 4px solid #36c;
-  display: block; 
-  font-size: 160%;
-  line-height: 1.2em;
-}
-
-div.slide h2 {
-  font-size:120%;
-  line-height: 1.2em;
-}
-
-div.toc {
-  position: absolute;
-  top: auto;
-  bottom: 4em;
-  left: 4em;
-  right: auto;
-  width: 60%;
-  max-width: 30em;
-  height: 30em;
-  border: solid thin black;
-  padding: 1em;
-  background: rgb(240,240,240);
-  color: black;
-  z-index: 300;
-  overflow: auto;
-  display: block;
-  visibility: visible;
-}
-
-div.toc-heading {
-  width: 100%;
-  border-bottom: solid 1px rgb(180,180,180);
-  margin-bottom: 1em;
-  text-align: center;
-}
-
-pre {
- font-size: 120%;
- font-weight: bold;
- line-height: 140%;
- padding-top: 0.2em;
- padding-bottom: 0.2em;
- padding-left: 1em;
- padding-right: 1em;
-/*
- border-style: solid;
- border-left-width: 1em;
- border-top-width: thin;
- border-right-width: thin;
- border-bottom-width: thin;
- border-color: #95ABD0;
-*/
- color: #0F398D;
- background-color: #fff8f8;
-}
-
-@media print {
-  div.slide {
-     display: block;
-     visibility: visible;
-     position: relative;
-     border-top-style: solid;
-     border-top-width: thin;
-     border-top-color: black;
-  }
-  div.slide pre { font-size: 60%; padding-left: 0.5em; }
-  div.handout { display: block; visibility: visible; }
-}
-
-blockquote { font-style: italic }
-
-img { background-color: transparent }
-
-p.copyright { font-size: smaller }
-
-.center { text-align: center }
-.footnote { font-size: smaller; margin-left: 2em; }
-
-a img { border-width: 0; border-style: none }
-
-a:visited { color: navy }
-a:link { color: navy }
-a:hover { color: red; text-decoration: underline }
-a:active { color: red; text-decoration: underline }
-
-a {text-decoration: none}
-.navbar a:link {color: white}
-.navbar a:visited {color: yellow}
-.navbar a:active {color: red}
-.navbar a:hover {color: red}
-
-ul { list-style-type: square; }
-ul ul { list-style-type: disc; }
-ul ul ul { list-style-type: circle; }
-ul ul ul ul { list-style-type: disc; }
-li { margin-left: 2em; margin-top: 0.5em; }
-li li { font-size: 85%; font-style: italic }
-li li li { font-size: 85%; font-style: normal }
-
-div dt
-{
-  margin-left: 0;
-  margin-top: 1em;
-  margin-bottom: 0.5em;
-  font-weight: bold;
-}
-div dd
-{
-  margin-left: 2em;
-  margin-bottom: 0.5em;
-}
-
-
-p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
-  margin-left: 1em;
-  margin-right: 1em;
-}
-
-p.subhead { font-weight: bold; margin-top: 2em; }
-
-p.smaller { font-size: smaller }
-
-td,th { padding: 0.2em }
-
-ul {
-  margin: 0.5em 1.5em 0.5em 1.5em;
-  padding: 0;
-}
-
-ol {
-  margin: 0.5em 1.5em 0.5em 1.5em;
-  padding: 0;
-}
-
-ul { list-style-type: square; }
-ul ul { list-style-type: disc; }
-ul ul ul { list-style-type: circle; }
-ul ul ul ul { list-style-type: disc; }
-
-ul li { 
-  list-style: square;
-  //margin: 0.1em 0em 0.6em 0;
-  padding: 0 0 0 0;
-  line-height: 140%;
-}
-
-ol li { 
-  margin: 0.1em 0em 0.6em 1.5em;
-  padding: 0 0 0 0px;
-  line-height: 140%;
-  list-style-type: decimal;
-}
-
-li ul li { 
-  font-size: 85%; 
-  font-style: italic;
-  list-style-type: disc;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-li li ul li { 
-  font-size: 85%; 
-  font-style: normal;
-  list-style-type: circle;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-li li li ul li {
-  list-style-type: disc;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-
-li ol li {
-  list-style-type: decimal;
-}
-
-
-li li ol li {
-  list-style-type: decimal;
-}
-
-/*
- setting class="outline on ol or ul makes it behave as an
- ouline list where blocklevel content in li elements is
- hidden by default and can be expanded or collapsed with
- mouse click. Set class="expand" on li to override default
-*/
-
-ol.outline li:hover { cursor: pointer }
-ol.outline li.nofold:hover { cursor: default }
-
-ul.outline li:hover { cursor: pointer }
-ul.outline li.nofold:hover { cursor: default }
-
-ol.outline { list-style:decimal; }
-ol.outline ol { list-style-type:lower-alpha }
-
-/* for slides with class "title" in table of contents */
-a.titleslide { font-weight: bold; font-style: italic }
diff --git a/content/2010/support/slidy.js b/content/2010/support/slidy.js
deleted file mode 100644
index 6a5561a..0000000
--- a/content/2010/support/slidy.js
+++ /dev/null
@@ -1,2772 +0,0 @@
-/* http://www.w3.org/Talks/Tools/Slidy/slidy.js
-
-   Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
-   W3C liability, trademark, document use and software licensing
-   rules apply, see:
-
-   http://www.w3.org/Consortium/Legal/copyright-documents
-   http://www.w3.org/Consortium/Legal/copyright-software
-*/
-
-var ns_pos = (typeof window.pageYOffset!='undefined');
-var khtml = ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false);
-var opera = ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false);
-var ie7 = (!ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1);
-
-window.onload = startup; // equivalent to onload on body element
-
-// IE only event handlers to ensure all slides are printed
-// I don't yet know how to emulate these for other browsers
-window.onbeforeprint = beforePrint;
-window.onafterprint = afterPrint;
-
-// hack to hide slides while loading
-setTimeout(hideAll, 50);
-
-function hideAll()
-{
-  if (document.body)
-    document.body.style.visibility = "hidden";
-  else
-    setTimeout(hideAll, 50);
-}
-
-var slidenum = 0;     // integer slide count: 0, 1, 2, ...
-var slides;           // set to array of slide div's
-var slideNumElement;  // element containing slide number
-var notes;            // set to array of handout div's
-var backgrounds;      // set to array of background div's
-var toolbar;          // element containing toolbar
-var title;            // document title
-var lastShown = null; // last incrementally shown item
-var eos = null;       // span element for end of slide indicator
-var toc = null;       // table of contents
-var outline = null;   // outline element with the focus
-var selectedTextLen;  // length of drag selection on document
-
-var viewAll = 0;      // 1 to view all slides + handouts
-var wantToolbar = 1;   // 0 if toolbar isn't wanted
-var mouseClickEnabled = true;  // enables left click for next slide
-var scrollhack = 0;   // IE work around for position: fixed
-
-var helpAnchor;  // used for keyboard focus hack in showToolbar()
-var helpPage = "http://www.w3.org/Talks/Tools/Slidy/help.html";
-var helpText = "Navigate with mouse click, space bar, Cursor Left/Right, " +
-               "or Pg Up and Pg Dn. Use S and B to change font size.";
-
-var sizeIndex = 0;
-var sizeAdjustment = 0;
-var sizes = new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
-                      "22pt", "24pt", "26pt", "28pt", "30pt", "32pt");
-
-var okayForIncremental = incrementalElementList();
-
-// needed for efficient resizing
-var lastWidth = 0;
-var lastHeight = 0;
-
-// Needed for cross browser support for relative width/height on
-// object elements. The work around is to save width/height attributes
-// and then to recompute absolute width/height dimensions on resizing
-var objects;
-
-// updated to language specified by html file
-var lang = "en";
-
-//var localize = {};
-
-// for each language there is an associative array
-var strings_es = {
-  "slide":"pág.",
-  "help?":"Ayuda",
-  "contents?":"Índice",
-  "table of contents":"tabla de contenidos",
-  "Table of Contents":"Tabla de Contenidos",
-  "restart presentation":"Reiniciar presentación",
-  "restart?":"Inicio"
-   };
-
-strings_es[helpText] =
-    "Utilice el ratón, barra espaciadora, teclas Izda/Dhca, " +
-    "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.";
-
-var strings_nl = {
-  "slide":"pagina",
-  "help?":"Help?",
-  "contents?":"Inhoud?",
-  "table of contents":"inhoudsopgave",
-  "Table of Contents":"Inhoudsopgave",
-  "restart presentation":"herstart presentatie",
-  "restart?":"Herstart?"
-   };
-
-strings_nl[helpText] =
-    "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
-    "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.";
-
-var strings_de = {
-  "slide":"Seite",
-  "help?":"Hilfe",
-  "contents?":"Übersicht",
-  "table of contents":"Inhaltsverzeichnis",
-  "Table of Contents":"Inhaltsverzeichnis",
-  "restart presentation":"Präsentation neu starten",
-  "restart?":"Neustart"
-   };
-
-strings_de[helpText] =
-    "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts" +
-    "oder Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.";
-
-var strings_pl = {
-  "slide":"slajd",
-  "help?":"pomoc?",
-  "contents?":"spis treści?",
-  "table of contents":"spis treści",
-  "Table of Contents":"Spis Treści",
-  "restart presentation":"Restartuj prezentację",
-  "restart?":"restart?"
-   };
-
-strings_pl[helpText] =
-    "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
-    "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.";
-
-var strings_fr = {
-  "slide":"page",
-  "help?":"Aide",
-  "contents?":"Index",
-  "table of contents":"table des matières",
-  "Table of Contents":"Table des matières",
-  "restart presentation":"Recommencer l'exposé",
-  "restart?":"Début"
-  };
-
-strings_fr[helpText] =
-    "Naviguez avec la souris, la barre d'espace, les flèches" +
-    "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
-    "les touches S et B pour modifier la taille de la police.";
-
-var strings_hu = {
-  "slide":"oldal",
-  "help?":"segítség",
-  "contents?":"tartalom",
-  "table of contents":"tartalomjegyzék",
-  "Table of Contents":"Tartalomjegyzék",
-  "restart presentation":"bemutató újraindítása",
-  "restart?":"újraindítás"
-   };
-
-strings_hu[helpText] =
-    "Az oldalak közti lépkedéshez kattintson az egérrel, vagy használja a szóköz, a bal, vagy a jobb nyíl, " +
-    "illetve a Page Down, Page Up billentyűket. Az S és a B billentyűkkel változtathatja a szöveg méretét.";
-
-var strings_it = {
-  "slide":"pag.",
-  "help?":"Aiuto",
-  "contents?":"Indice",
-  "table of contents":"indice",
-  "Table of Contents":"Indice",
-  "restart presentation":"Ricominciare la presentazione",
-  "restart?":"Inizio"
-   };
-
-strings_it[helpText] =
-    "Navigare con mouse, barra spazio, frecce sinistra/destra o " +
-    "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.";
-
-var strings_el = {
-  "slide":"σελίδα",
-  "help?":"βοήθεια;",
-  "contents?":"περιεχόμενα;",
-  "table of contents":"πίνακας περιεχομένων",
-  "Table of Contents":"Πίνακας Περιεχομένων",
-  "restart presentation":"επανεκκίνηση παρουσίασης",
-  "restart?":"επανεκκίνηση;"
-   };
-
-strings_el[helpText] =
-  "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
-  "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
-  "το μέγεθος της γραμματοσειράς.";
-
-var strings_ja = {
-  "slide":"スライド",
-  "help?":"ヘルプ",
-  "contents?":"目次",
-  "table of contents":"目次を表示",
-  "Table of Contents":"目次",
-  "restart presentation":"最初から再生",
-  "restart?":"最初から"
-};
-
-strings_ja[helpText] =
-    "マウス左クリック ・ スペース ・ 左右キー " +
-    "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更";
-
-
-// each such language array is declared in the localize array
-// used indirectly as in help.innerHTML = "help".localize();
-var localize = {
-     "es":strings_es,
-     "nl":strings_nl,
-     "de":strings_de,
-     "pl":strings_pl,
-     "fr":strings_fr,
-     "hu":strings_hu,
-     "it":strings_it,
-     "el":strings_el,
-     "jp":strings_ja
-   };
-
-/* general initialization */
-function startup()
-{
-   // find human language from html element
-   // for use in localizing strings
-   lang = document.body.parentNode.getAttribute("lang");
-
-   if (!lang)
-     lang = document.body.parentNode.getAttribute("xml:lang");
-
-   if (!lang)
-     lang = "en";
-
-   document.body.style.visibility = "visible";
-   title = document.title;
-   toolbar = addToolbar();
-   wrapImplicitSlides();
-   slides = collectSlides();
-   notes = collectNotes();
-   objects = document.body.getElementsByTagName("object");
-   backgrounds = collectBackgrounds();
-   patchAnchors();
-
-   slidenum = findSlideNumber(location.href);
-   window.offscreenbuffering = true;
-   sizeAdjustment = findSizeAdjust();
-   hideImageToolbar();  // suppress IE image toolbar popup
-   initOutliner();  // activate fold/unfold support
-
-   if (slides.length > 0)
-   {
-      var slide = slides[slidenum];
-      slide.style.position = "absolute";
-   
-      if (slidenum > 0)
-      {
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-         setEosStatus(true);
-      }
-      else
-      {
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         setEosStatus(!nextIncrementalItem(lastShown));
-      }
-
-      setLocation();
-   }
-
-   toc = tableOfContents();
-   hideTableOfContents();
-
-   // bind event handlers
-   document.onclick = mouseButtonClick;
-   document.onmouseup = mouseButtonUp;
-   document.onkeydown = keyDown;
-   window.onresize  = resized;
-   window.onscroll = scrolled;
-   singleSlideView();
-
-   setLocation();
-   resized();
-
-   if (ie7)
-     setTimeout("ieHack()", 100);
-
-   showToolbar();
-}
-
-// add localize method to all strings for use
-// as in help.innerHTML = "help".localize();
-String.prototype.localize = function()
-{
-  if (this == "")
-    return this;
-
-  // try full language code, e.g. en-US
-  var s, lookup = localize[lang];
-
-  if (lookup)
-  {
-    s = lookup[this];
-
-    if (s)
-      return s;
-  }
-
-  // try en if undefined for en-US
-  var lg = lang.split("-");
-
-  if (lg.length > 1)
-  {
-    lookup = localize[lg[0]];
-
-    if (lookup)
-    {
-      s = lookup[this];
-
-      if (s)
-        return s;
-    }
-  }
-
-  // otherwise string as is
-  return this;
-}
-
-// suppress IE's image toolbar pop up
-function hideImageToolbar()
-{
-  if (!ns_pos)
-  {
-    var images = document.getElementsByTagName("IMG");
-
-    for (var i = 0; i < images.length; ++i)
-      images[i].setAttribute("galleryimg", "no");
-  }
-}
-
-// hack to persuade IE to compute correct document height
-// as needed for simulating fixed positioning of toolbar
-function ieHack()
-{
-   window.resizeBy(0,-1);
-   window.resizeBy(0, 1);
-}
-
-// Firefox reload SVG bug work around
-function reload(e)
-{
-   if (!e)
-      var e = window.event;
-
-   hideBackgrounds();
-   setTimeout("document.reload();", 100);
-
-   stopPropagation(e);
-   e.cancel = true;
-   e.returnValue = false;
-
-   return false;
-}
-
-// Safari and Konqueror don't yet support getComputedStyle()
-// and they always reload page when location.href is updated
-function isKHTML()
-{
-   var agent = navigator.userAgent;
-   return (agent.indexOf("KHTML") >= 0 ? true : false);
-}
-
-function resized()
-{
-   var width = 0;
-
-   if ( typeof( window.innerWidth ) == 'number' )
-      width = window.innerWidth;  // Non IE browser
-   else if (document.documentElement && document.documentElement.clientWidth)
-      width = document.documentElement.clientWidth;  // IE6
-   else if (document.body && document.body.clientWidth)
-      width = document.body.clientWidth; // IE4
-
-   var height = 0;
-
-   if ( typeof( window.innerHeight ) == 'number' )
-      height = window.innerHeight;  // Non IE browser
-   else if (document.documentElement && document.documentElement.clientHeight)
-      height = document.documentElement.clientHeight;  // IE6
-   else if (document.body && document.body.clientHeight)
-      height = document.body.clientHeight; // IE4
-
-   if (height && (width/height > 1.05*1024/768))
-   {
-     width = height * 1024.0/768;
-   }
-
-   // IE fires onresize even when only font size is changed!
-   // so we do a check to avoid blocking < and > actions
-   if (width != lastWidth || height != lastHeight)
-   {
-      if (width >= 1100)
-         sizeIndex = 5;    // 4
-      else if (width >= 1000)
-         sizeIndex = 4;    // 3
-      else if (width >= 800)
-         sizeIndex = 3;    // 2
-      else if (width >= 600)
-         sizeIndex = 2;    // 1
-      else if (width)
-         sizeIndex = 0;
-
-      // add in font size adjustment from meta element e.g.
-      // <meta name="font-size-adjustment" content="-2" />
-      // useful when slides have too much content ;-)
-
-      if (0 <= sizeIndex + sizeAdjustment &&
-             sizeIndex + sizeAdjustment < sizes.length)
-        sizeIndex = sizeIndex + sizeAdjustment;
-
-      // enables cross browser use of relative width/height
-      // on object elements for use with SVG and Flash media
-      adjustObjectDimensions(width, height);
-
-      document.body.style.fontSize = sizes[sizeIndex];
-
-      lastWidth = width;
-      lastHeight = height;
-
-      // force reflow to work around Mozilla bug
-      //if (ns_pos)
-      {
-         var slide = slides[slidenum];
-         hideSlide(slide);
-         showSlide(slide);
-      }
-
-      // force correct positioning of toolbar
-      refreshToolbar(200);
-   }
-}
-
-function scrolled()
-{
-   if (toolbar && !ns_pos && !ie7)
-   {
-      hackoffset = scrollXOffset();
-      // hide toolbar
-      toolbar.style.display = "none";
-
-      // make it reappear later
-      if (scrollhack == 0 && !viewAll)
-      {
-         setTimeout(showToolbar, 1000);
-         scrollhack = 1;
-      }
-   }
-}
-
-// used to ensure IE refreshes toolbar in correct position
-function refreshToolbar(interval)
-{
-   if (!ns_pos && !ie7)
-   {
-     hideToolbar();
-     setTimeout(showToolbar, interval);
-   }
-}
-
-// restores toolbar after short delay
-function showToolbar()
-{
-   if (wantToolbar)
-   {
-      if (!ns_pos)
-      {
-         // adjust position to allow for scrolling
-         var xoffset = scrollXOffset();
-         toolbar.style.left = xoffset;
-         toolbar.style.right = xoffset;
-
-         // determine vertical scroll offset
-         //var yoffset = scrollYOffset();
-
-         // bottom is doc height - window height - scroll offset
-         //var bottom = documentHeight() - lastHeight - yoffset
-
-         //if (yoffset > 0 || documentHeight() > lastHeight)
-         //   bottom += 16;  // allow for height of scrollbar
-
-         toolbar.style.bottom = 0; //bottom;
-      }
-
-      toolbar.style.display = "block";
-      toolbar.style.visibility = "visible";
-   }
-
-   scrollhack = 0;
-
-
-   // set the keyboard focus to the help link on the
-   // toolbar to ensure that document has the focus
-   // IE doesn't always work with window.focus()
-   // and this hack has benefit of Enter for help
-
-   try
-   {
-     if (!opera)
-       helpAnchor.focus();
-   }
-   catch (e)
-   {
-   }
-}
-
-function test()
-{
-   var s = "docH: " + documentHeight() +
-       " winH: " + lastHeight +
-       " yoffset: " + scrollYOffset() +
-       " toolbot: " + (documentHeight() - lastHeight - scrollYOffset());
-
-   //alert(s);
-
-   var slide = slides[slidenum];
-   // IE getAttribute requires "class" to be "className"
-   var name = ns_pos ? "class" : "className";
-   var style = (slide.currentStyle ? slide.currentStyle["backgroundColor"] :
-       document.defaultView.getComputedStyle(slide, '').getPropertyValue("background-color"));
-   alert("class='" + slide.getAttribute(name) + "' backgroundColor: " + style);
-}
-
-function hideToolbar()
-{
-   toolbar.style.display = "none";
-   toolbar.style.visibility = "hidden";
-   window.focus();
-}
-
-// invoked via F key
-function toggleToolbar()
-{
-   if (!viewAll)
-   {
-      if (toolbar.style.display == "none")
-      {
-         toolbar.style.display = "block";
-         toolbar.style.visibility = "visible";
-         wantToolbar = 1;
-      }
-      else
-      {
-         toolbar.style.display = "none";
-         toolbar.style.visibility = "hidden";
-         wantToolbar = 0;
-      }
-   }
-}
-
-function scrollXOffset()
-{
-   if (window.pageXOffset)
-      return self.pageXOffset;
-
-   if (document.documentElement && 
-             document.documentElement.scrollLeft)
-      return document.documentElement.scrollLeft;
-
-   if (document.body)
-      return document.body.scrollLeft;
-
-    return 0;
-}
-
-
-function scrollYOffset()
-{
-   if (window.pageYOffset)
-      return self.pageYOffset;
-
-   if (document.documentElement && 
-             document.documentElement.scrollTop)
-      return document.documentElement.scrollTop;
-
-   if (document.body)
-      return document.body.scrollTop;
-
-    return 0;
-}
-
-// looking for a way to determine height of slide content
-// the slide itself is set to the height of the window
-function optimizeFontSize()
-{
-   var slide = slides[slidenum];
-
-   //var dh = documentHeight(); //getDocHeight(document);
-   var dh = slide.scrollHeight;
-   var wh = getWindowHeight();
-   var u = 100 * dh / wh;
-
-   alert("window utilization = " + u + "% (doc "
-      + dh + " win " + wh + ")");
-}
-
-function getDocHeight(doc) // from document object
-{
-  if (!doc)
-    doc = document;
-
-  if (doc && doc.body && doc.body.offsetHeight)
-    return doc.body.offsetHeight;  // ns/gecko syntax
-
-  if (doc && doc.body && doc.body.scrollHeight)
-    return doc.body.scrollHeight;
-
-  alert("couldn't determine document height");
-}
-
-function getWindowHeight()
-{
-  if ( typeof( window.innerHeight ) == 'number' )
-    return window.innerHeight;  // Non IE browser
-
-  if (document.documentElement && document.documentElement.clientHeight)
-    return document.documentElement.clientHeight;  // IE6
-
-  if (document.body && document.body.clientHeight)
-    return document.body.clientHeight; // IE4
-}
-
-
-
-function documentHeight()
-{
-   var sh, oh;
-
-   sh = document.body.scrollHeight;
-   oh = document.body.offsetHeight;
-
-   if (sh && oh)
-   {
-      return (sh > oh ? sh : oh);
-   }
-
-   // no idea!
-   return 0;
-}
-
-function smaller()
-{
-   if (sizeIndex > 0)
-   {
-      --sizeIndex;
-   }
-
-   toolbar.style.display = "none";
-   document.body.style.fontSize = sizes[sizeIndex];
-   var slide = slides[slidenum];
-   hideSlide(slide);
-   showSlide(slide);
-   setTimeout(showToolbar, 300);
-}
-
-function bigger()
-{
-   if (sizeIndex < sizes.length - 1)
-   {
-      ++sizeIndex;
-   }
-
-   toolbar.style.display = "none";
-   document.body.style.fontSize = sizes[sizeIndex];
-   var slide = slides[slidenum];
-   hideSlide(slide);
-   showSlide(slide);
-   setTimeout(showToolbar, 300);
-}
-
-// enables cross browser use of relative width/height
-// on object elements for use with SVG and Flash media
-// with thanks to Ivan Herman for the suggestion
-function adjustObjectDimensions(width, height)
-{
-   for( var i = 0; i < objects.length; i++ )
-   {
-      var obj = objects[i];
-      var mimeType = obj.getAttribute("type");
-
-      if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
-      {
-         if ( !obj.initialWidth ) 
-            obj.initialWidth = obj.getAttribute("width");
-
-         if ( !obj.initialHeight ) 
-            obj.initialHeight = obj.getAttribute("height");
-
-         if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
-         {
-            var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
-            var newW = width * (w/100.0);
-            obj.setAttribute("width",newW);
-         }
-
-         if ( obj.initialHeight && obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
-         {
-            var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
-            var newH = height * (h/100.0);
-            obj.setAttribute("height", newH);
-         }
-      }
-   }
-}
-
-function cancel(event)
-{
-  if (event)
-  {
-     event.cancel = true;
-     event.returnValue = false;
-
-    if (event.preventDefault)
-      event.preventDefault();
-  }
-
-  return false;
-}
-
-//  See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
-function keyDown(event)
-{
-    var key;
-
-    if (!event)
-      var event = window.event;
-
-    // kludge around NS/IE differences 
-    if (window.event)
-       key = window.event.keyCode;
-    else if (event.which)
-       key = event.which;
-    else
-       return true; // Yikes! unknown browser
-
-    // ignore event if key value is zero
-    // as for alt on Opera and Konqueror
-    if (!key)
-       return true;
-
-    // check for concurrent control/command/alt key
-    // but are these only present on mouse events?
-
-    if (event.ctrlKey || event.altKey || event.metaKey)
-       return true;
-
-    // dismiss table of contents if visible
-    if (isShownToc() && key != 9 && key != 16 && key != 38 && key != 40)
-    {
-      hideTableOfContents();
-
-      if (key == 27 || key == 84 || key == 67)
-        return cancel(event);
-    }
-
-    if (key == 34) // Page Down
-    {
-       nextSlide(false);
-       return cancel(event);
-    }
-    else if (key == 33) // Page Up
-    {
-       previousSlide(false);
-       return cancel(event);
-    }
-    else if (key == 32) // space bar
-    {
-       nextSlide(true);
-       return cancel(event);
-    }
-    else if (key == 37 || key == 38) // Left arrow || Up arrow
-    {
-       previousSlide(!event.shiftKey);
-       return cancel(event);
-    }
-    else if (key == 36) // Home
-    {
-       firstSlide();
-       return cancel(event);
-    }
-    else if (key == 35) // End
-    {
-       lastSlide();
-       return cancel(event);
-    }
-    else if (key == 39 || key == 40) // Right arrow || Down arrow
-    {
-       nextSlide(!event.shiftKey);
-       return cancel(event);
-    }
-    else if (key == 13) // Enter
-    {
-       if (outline)
-       {
-          if (outline.visible)
-            fold(outline);
-          else
-            unfold(outline);
-          
-         return cancel(event);
-       }
-    }
-    else if (key == 188)  // < for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 190)  // > for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 189 || key == 109)  // - for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 187 || key == 191 || key == 107)  // = +  for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 83)  // S for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 66)  // B for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 90)  // Z for last slide
-    {
-       lastSlide();
-       return cancel(event);
-    }
-    else if (key == 70)  // F for toggle toolbar
-    {
-       toggleToolbar();
-       return cancel(event);
-    }
-    else if (key == 65)  // A for toggle view single/all slides
-    {
-       toggleView();
-       return cancel(event);
-    }
-    else if (key == 75)  // toggle action of left click for next page
-    {
-       mouseClickEnabled = !mouseClickEnabled;
-       alert((mouseClickEnabled ? "enabled" : "disabled") +  " mouse click advance");
-       return cancel(event);
-    }
-    else if (key == 84 || key == 67)  // T or C for table of contents
-    {
-       if (toc)
-         showTableOfContents();
-
-       return cancel(event);
-    }
-    else if (key == 72) // H for help
-    {
-       window.location = helpPage;
-       return cancel(event);
-    }
-
-    //else if (key == 93) // Windows menu key
-      //alert("lastShown is " + lastShown);
-    //else alert("key code is "+ key);
-
-
-    return true;
-}
-
-// make note of length of selected text
-// as this evaluates to zero in click event
-function mouseButtonUp(e)
-{
-  selectedTextLen = getSelectedText().length;
-}
-
-// right mouse button click is reserved for context menus
-// it is more reliable to detect rightclick than leftclick
-function mouseButtonClick(e)
-{
-   var rightclick = false;
-   var leftclick = false;
-   var middleclick = false;
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   if (e.which) // all browsers except IE
-   {
-      leftclick = (e.which == 1);
-      middleclick = (e.which == 2);
-      rightclick = (e.which == 3);
-   }
-   else if (e.button)
-   {
-      // Konqueror gives 1 for left, 4 for middle
-      // IE6 gives 0 for left and not 1 as I expected
-
-      if (e.button == 4)
-        middleclick = true;
-
-      // all browsers agree on 2 for right button
-      rightclick = (e.button == 2);
-   }
-   else leftclick = true;
-
-   // dismiss table of contents
-   hideTableOfContents();
-
-   if (selectedTextLen > 0)
-   {
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-      return false;
-   }
-
-   // check if target is something that probably want's clicks
-   // e.g. embed, object, input, textarea, select, option
-
-   if (mouseClickEnabled && leftclick &&
-        target.nodeName != "EMBED" &&
-        target.nodeName != "OBJECT" &&
-        target.nodeName != "INPUT" &&
-        target.nodeName != "TEXTAREA" &&
-        target.nodeName != "SELECT" &&
-        target.nodeName != "OPTION")
-   {
-      nextSlide(true);
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-   }
-}
-
-function previousSlide(incremental)
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      if ((incremental || slidenum == 0) && lastShown != null)
-      {
-         lastShown = hidePreviousItem(lastShown);
-         setEosStatus(false);
-      }
-      else if (slidenum > 0)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = slidenum - 1;
-         slide = slides[slidenum];
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-         setEosStatus(true);
-         showSlide(slide);
-      }
-
-      setLocation();
-
-      if (!ns_pos)
-         refreshToolbar(200);
-   }
-}
-
-function nextSlide(incremental)
-{
-   if (!viewAll)
-   {
-      var slide, last = lastShown;
-
-      if (incremental || slidenum == slides.length - 1)
-         lastShown = revealNextItem(lastShown);
-
-      if ((!incremental || lastShown == null) && slidenum < slides.length - 1)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = slidenum + 1;
-         slide = slides[slidenum];
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         showSlide(slide);
-      }
-      else if (!lastShown)
-      {
-         if (last && incremental)
-           lastShown = last;
-      }
-
-      setLocation();
-
-      setEosStatus(!nextIncrementalItem(lastShown));
-
-      if (!ns_pos)
-         refreshToolbar(200);
-   }
-}
-
-// to first slide with nothing revealed
-// i.e. state at start of presentation
-function firstSlide()
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      if (slidenum != 0)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = 0;
-         slide = slides[slidenum];
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         showSlide(slide);
-      }
-
-      setEosStatus(!nextIncrementalItem(lastShown));
-      setLocation();
-   }
-}
-
-
-// to last slide with everything revealed
-// i.e. state at end of presentation
-function lastSlide()
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      lastShown = null; //revealNextItem(lastShown);
-
-      if (lastShown == null && slidenum < slides.length - 1)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-         slidenum = slides.length - 1;
-         slide = slides[slidenum];
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-
-         showSlide(slide);
-      }
-      else
-      {
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-      }
-
-      setEosStatus(true);
-      setLocation();
-   }
-}
-
-function setEosStatus(state)
-{
-   if (eos)
-      eos.style.color = (state ? "rgb(240,240,240)" : "red");
-}
-
-function showSlide(slide)
-{
-   syncBackground(slide);
-   window.scrollTo(0,0);
-   slide.style.visibility = "visible";
-   slide.style.display = "block";
-}
-
-function hideSlide(slide)
-{
-   slide.style.visibility = "hidden";
-   slide.style.display = "none";
-}
-
-function beforePrint()
-{
-   showAllSlides();
-   hideToolbar();
-}
-
-function afterPrint()
-{
-   if (!viewAll)
-   {
-      singleSlideView();
-      showToolbar();
-   }
-}
-
-function printSlides()
-{
-  beforePrint();
-  window.print();
-  afterPrint();
-}
-
-function toggleView()
-{
-   if (viewAll)
-   {
-      singleSlideView();
-      showToolbar();
-      viewAll = 0;
-   }
-   else
-   {
-      showAllSlides();
-      hideToolbar();
-      viewAll = 1;
-   }
-}
-
-// prepare for printing
-function showAllSlides()
-{
-   var slide;
-
-   for (var i = 0; i < slides.length; ++i)
-   {
-      slide = slides[i];
-
-      slide.style.position = "relative";
-      slide.style.borderTopStyle = "solid";
-      slide.style.borderTopWidth = "thin";
-      slide.style.borderTopColor = "black";
-
-      try {
-        if (i == 0)
-          slide.style.pageBreakBefore = "avoid";
-        else
-          slide.style.pageBreakBefore = "always";
-      }
-      catch (e)
-      {
-        //do nothing
-      }
-
-      setVisibilityAllIncremental("visible");
-      showSlide(slide);
-   }
-
-   var note;
-
-   for (var i = 0; i < notes.length; ++i)
-   {
-      showSlide(notes[i]);
-   }
-
-   // no easy way to render background under each slide
-   // without duplicating the background divs for each slide
-   // therefore hide backgrounds to avoid messing up slides
-   hideBackgrounds();
-}
-
-// restore after printing
-function singleSlideView()
-{
-   var slide;
-
-   for (var i = 0; i < slides.length; ++i)
-   {
-      slide = slides[i];
-
-      slide.style.position = "absolute";
-
-      if (i == slidenum)
-      {
-         slide.style.borderStyle = "none";
-         showSlide(slide);
-      }
-      else
-      {
-         slide.style.borderStyle = "none";
-         hideSlide(slide);
-      }
-   }
-
-   setVisibilityAllIncremental("visible");
-   lastShown = previousIncrementalItem(null);
-
-   var note;
-
-   for (var i = 0; i < notes.length; ++i)
-   {
-      hideSlide(notes[i]);
-   }
-}
-
-// the string str is a whitespace separated list of tokens
-// test if str contains a particular token, e.g. "slide"
-function hasToken(str, token)
-{
-   if (str)
-   {
-      // define pattern as regular expression
-      var pattern = /\w+/g;
-
-      // check for matches
-      // place result in array
-      var result = str.match(pattern);
-
-      // now check if desired token is present
-      for (var i = 0; i < result.length; i++)
-      {
-         if (result[i] == token)
-            return true;
-      }
-   }
-
-   return false;
-}
-
-function getClassList(element)
-{
-  if (typeof window.pageYOffset =='undefined')
-    return element.getAttribute("className");
-
-  return element.getAttribute("class");
-}
-
-function hasClass(element, name)
-{
-  var regexp = new RegExp("(^| )" + name + "\W*");
-
-  if (regexp.test(getClassList(element)))
-    return true;
-
-  return false;
-
-}
-
-function removeClass(element, name)
-{
-  // IE getAttribute requires "class" to be "className"
-  var clsname = ns_pos ? "class" : "className";
-  var clsval = element.getAttribute(clsname);
-
-  var regexp = new RegExp("(^| )" + name + "\W*");
-
-  if (clsval)
-  {
-    clsval = clsval.replace(regexp, "");
-    element.setAttribute(clsname, clsval);
-  }
-}
-
-function addClass(element, name)
-{
-  if (!hasClass(element, name))
-  {
-    // IE getAttribute requires "class" to be "className"
-    var clsname = ns_pos ? "class" : "className";
-    var clsval = element.getAttribute(clsname);
-    element.setAttribute(clsname, (clsval ? clsval + " " + name : name));
-  }
-}
-
-// wysiwyg editors make it hard to use div elements
-// e.g. amaya loses the div when you copy and paste
-// this function wraps div elements around implicit
-// slides which start with an h1 element and continue
-// up to the next heading or div element
-function wrapImplicitSlides()
-{
-   var i, heading, node, next, div;
-   var headings = document.getElementsByTagName("h1");
-
-   if (!headings)
-     return;
-
-   for (i = 0; i < headings.length; ++i)
-   {
-      heading = headings[i];
-
-      if (heading.parentNode != document.body)
-         continue;
-
-      node = heading.nextSibling;
-
-      div = document.createElement("div");
-      div.setAttribute((ns_pos ? "class" : "className"), "slide");
-      document.body.replaceChild(div, heading);
-      div.appendChild(heading);
-
-      while (node)
-      {
-         if (node.nodeType == 1 &&    // an element
-                  (node.nodeName == "H1" ||
-                   node.nodeName == "h1" ||
-                   node.nodeName == "DIV" ||
-                   node.nodeName == "div"))
-            break;
-
-         next = node.nextSibling;
-         node = document.body.removeChild(node);
-         div.appendChild(node);
-         node = next;
-      } 
-   }
-}
-
-// return new array of all slides
-function collectSlides()
-{
-   var slides = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "slide"))
-      {
-         // add slide to collection
-         slides[slides.length] = div;
-
-         // hide each slide as it is found
-         div.style.display = "none";
-         div.style.visibility = "hidden";
-
-         // add dummy <br/> at end for scrolling hack
-         var node1 = document.createElement("br");
-         div.appendChild(node1);
-         var node2 = document.createElement("br");
-         div.appendChild(node2);
-      }
-      else if (hasClass(div, "background"))
-      {  // work around for Firefox SVG reload bug
-         // which otherwise replaces 1st SVG graphic with 2nd
-         div.style.display = "block";
-      }
-   }
-
-   return slides;
-}
-
-// return new array of all <div class="handout">
-function collectNotes()
-{
-   var notes = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "handout"))
-      {
-         // add slide to collection
-         notes[notes.length] = div;
-
-         // hide handout notes as they are found
-         div.style.display = "none";
-         div.style.visibility = "hidden";
-      }
-   }
-
-   return notes;
-}
-
-// return new array of all <div class="background">
-// including named backgrounds e.g. class="background titlepage"
-function collectBackgrounds()
-{
-   var backgrounds = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "background"))
-      {
-         // add slide to collection
-         backgrounds[backgrounds.length] = div;
-
-         // hide named backgrounds as they are found
-         // e.g. class="background epilog"
-         if (getClassList(div) != "background")
-         {
-            div.style.display = "none";
-            div.style.visibility = "hidden";
-         }
-      }
-   }
-
-   return backgrounds;
-}
-
-// show just the backgrounds pertinent to this slide
-function syncBackground(slide)
-{
-   var background;
-   var bgColor;
-
-   if (slide.currentStyle)
-      bgColor = slide.currentStyle["backgroundColor"];
-   else if (document.defaultView)
-   {
-      var styles = document.defaultView.getComputedStyle(slide,null);
-
-      if (styles)
-          bgColor = styles.getPropertyValue("background-color");
-      else // broken implementation probably due Safari or Konqueror
-      {
-          //alert("defective implementation of getComputedStyle()");
-          bgColor = "transparent";
-      }
-   }
-   else
-      bgColor == "transparent";
-
-   if (bgColor == "transparent")
-   {
-      var slideClass = getClassList(slide);
-
-      for (var i = 0; i < backgrounds.length; i++)
-      {
-         background = backgrounds[i];
-
-         var bgClass = getClassList(background);
-
-         if (matchingBackground(slideClass, bgClass))
-         {
-            background.style.display = "block";
-            background.style.visibility = "visible";
-         }
-         else
-         {
-            background.style.display = "none";
-            background.style.visibility = "hidden";
-         }
-      }
-   }
-   else // forcibly hide all backgrounds
-      hideBackgrounds();
-}
-
-function hideBackgrounds()
-{
-   for (var i = 0; i < backgrounds.length; i++)
-   {
-      background = backgrounds[i];
-      background.style.display = "none";
-      background.style.visibility = "hidden";
-   }
-}
-
-// compare classes for slide and background
-function matchingBackground(slideClass, bgClass)
-{
-   if (bgClass == "background")
-      return true;
-
-   // define pattern as regular expression
-   var pattern = /\w+/g;
-
-   // check for matches and place result in array
-   var result = slideClass.match(pattern);
-
-   // now check if desired name is present for background
-   for (var i = 0; i < result.length; i++)
-   {
-      if (hasToken(bgClass, result[i]))
-         return true;
-   }
-
-   return false;
-}
-
-// left to right traversal of root's content
-function nextNode(root, node)
-{
-   if (node == null)
-      return root.firstChild;
-
-   if (node.firstChild)
-      return node.firstChild;
-
-   if (node.nextSibling)
-      return node.nextSibling;
-
-   for (;;)
-   {
-      node = node.parentNode;
-
-      if (!node || node == root)
-         break;
-
-      if (node && node.nextSibling)
-         return node.nextSibling;
-   }
-
-   return null;
-}
-
-// right to left traversal of root's content
-function previousNode(root, node)
-{
-   if (node == null)
-   {
-      node = root.lastChild;
-
-      if (node)
-      {
-         while (node.lastChild)
-            node = node.lastChild;
-      }
-
-      return node;
-   }
-
-   if (node.previousSibling)
-   {
-      node = node.previousSibling;
-
-      while (node.lastChild)
-         node = node.lastChild;
-
-      return node;
-   }
-
-   if (node.parentNode != root)
-      return node.parentNode;
-
-   return null;
-}
-
-// HTML elements that can be used with class="incremental"
-// note that you can also put the class on containers like
-// up, ol, dl, and div to make their contents appear
-// incrementally. Upper case is used since this is what
-// browsers report for HTML node names (text/html).
-function incrementalElementList()
-{
-   var inclist = new Array();
-   inclist["P"] = true;
-   inclist["PRE"] = true;
-   inclist["LI"] = true;
-   inclist["BLOCKQUOTE"] = true;
-   inclist["DT"] = true;
-   inclist["DD"] = true;
-   inclist["H2"] = true;
-   inclist["H3"] = true;
-   inclist["H4"] = true;
-   inclist["H5"] = true;
-   inclist["H6"] = true;
-   inclist["SPAN"] = true;
-   inclist["ADDRESS"] = true;
-   inclist["TABLE"] = true;
-   inclist["TR"] = true;
-   inclist["TH"] = true;
-   inclist["TD"] = true;
-   inclist["IMG"] = true;
-   inclist["OBJECT"] = true;
-   return inclist;
-}
-
-function nextIncrementalItem(node)
-{
-   var slide = slides[slidenum];
-
-   for (;;)
-   {
-      node = nextNode(slide, node);
-
-      if (node == null || node.parentNode == null)
-         break;
-
-      if (node.nodeType == 1)  // ELEMENT
-      {
-         if (node.nodeName == "BR")
-           continue;
-
-         if (hasClass(node, "incremental")
-             && okayForIncremental[node.nodeName])
-            return node;
-
-         if (hasClass(node.parentNode, "incremental")
-             && !hasClass(node, "non-incremental"))
-            return node;
-      }
-   }
-
-   return node;
-}
-
-function previousIncrementalItem(node)
-{
-   var slide = slides[slidenum];
-
-   for (;;)
-   {
-      node = previousNode(slide, node);
-
-      if (node == null || node.parentNode == null)
-         break;
-
-      if (node.nodeType == 1)
-      {
-         if (node.nodeName == "BR")
-           continue;
-
-         if (hasClass(node, "incremental")
-             && okayForIncremental[node.nodeName])
-            return node;
-
-         if (hasClass(node.parentNode, "incremental")
-             && !hasClass(node, "non-incremental"))
-            return node;
-      }
-   }
-
-   return node;
-}
-
-// set visibility for all elements on current slide with
-// a parent element with attribute class="incremental"
-function setVisibilityAllIncremental(value)
-{
-   var node = nextIncrementalItem(null);
-
-   while (node)
-   {
-      node.style.visibility = value;
-      node = nextIncrementalItem(node);
-   }
-}
-
-// reveal the next hidden item on the slide
-// node is null or the node that was last revealed
-function revealNextItem(node)
-{
-   node = nextIncrementalItem(node);
-
-   if (node && node.nodeType == 1)  // an element
-      node.style.visibility = "visible";
-
-   return node;
-}
-
-
-// exact inverse of revealNextItem(node)
-function hidePreviousItem(node)
-{
-   if (node && node.nodeType == 1)  // an element
-      node.style.visibility = "hidden";
-
-   return previousIncrementalItem(node);
-}
-
-
-/* set click handlers on all anchors */
-function patchAnchors()
-{
-   var anchors = document.body.getElementsByTagName("a");
-
-   for (var i = 0; i < anchors.length; ++i)
-   {
-      anchors[i].onclick = clickedAnchor;
-   }
-}
-
-function clickedAnchor(e)
-{
-   if (!e)
-      var e = window.event;
-
-   // compare this.href with location.href
-   // for link to another slide in this doc
-
-   if (pageAddress(this.href) == pageAddress(location.href))
-   {
-      // yes, so find new slide number
-      var newslidenum = findSlideNumber(this.href);
-
-      if (newslidenum != slidenum)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-         slidenum = newslidenum;
-         slide = slides[slidenum];
-         showSlide(slide);
-         setLocation();
-      }
-   }
-   else if (this.target == null)
-      location.href = this.href;
-
-   this.blur();
-   stopPropagation(e);
-}
-
-function pageAddress(uri)
-{
-   var i = uri.indexOf("#");
-
-   // check if anchor is entire page
-
-   if (i < 0)
-      return uri;  // yes
-
-   return uri.substr(0, i);
-}
-
-function showSlideNumber()
-{
-   slideNumElement.innerHTML = "slide".localize() + " " +
-           (slidenum + 1) + "/" + slides.length;
-}
-
-function setLocation()
-{
-   var uri = pageAddress(location.href);
-
-   //if (slidenum > 0)
-      uri = uri + "#(" + (slidenum+1) + ")";
-
-   if (uri != location.href && !khtml)
-      location.href = uri;
-
-   document.title = title + " (" + (slidenum+1) + ")";
-   //document.title = (slidenum+1) + ") " + slideName(slidenum);
-
-   showSlideNumber();
-}
-
-// find current slide based upon location
-// first find target anchor and then look
-// for associated div element enclosing it
-// finally map that to slide number
-function findSlideNumber(uri)
-{
-   // first get anchor from page location
-
-   var i = uri.indexOf("#");
-
-   // check if anchor is entire page
-
-   if (i < 0)
-      return 0;  // yes
-
-   var anchor = unescape(uri.substr(i+1));
-
-   // now use anchor as XML ID to find target
-   var target = document.getElementById(anchor);
-
-   if (!target)
-   {
-      // does anchor look like "(2)" for slide 2 ??
-      // where first slide is (1)
-      var re = /\((\d)+\)/;
-
-      if (anchor.match(re))
-      {
-         var num = parseInt(anchor.substring(1, anchor.length-1));
-
-         if (num > slides.length)
-            num = 1;
-
-         if (--num < 0)
-            num = 0;
-
-         return num;
-      }
-
-      // accept [2] for backwards compatibility
-      re = /\[(\d)+\]/;
-
-      if (anchor.match(re))
-      {
-         var num = parseInt(anchor.substring(1, anchor.length-1));
-
-         if (num > slides.length)
-            num = 1;
-
-         if (--num < 0)
-            num = 0;
-
-         return num;
-      }
-
-      // oh dear unknown anchor
-      return 0;
-   }
-
-   // search for enclosing slide
-
-   while (true)
-   {
-      // browser coerces html elements to uppercase!
-      if (target.nodeName.toLowerCase() == "div" &&
-            hasClass(target, "slide"))
-      {
-         // found the slide element
-         break;
-      }
-
-      // otherwise try parent element if any
-
-      target = target.parentNode;
-
-      if (!target)
-      {
-         return 0;   // no luck!
-      }
-   };
-
-   for (i = 0; i < slides.length; ++i)
-   {
-      if (slides[i] == target)
-         return i;  // success
-   }
-
-   // oh dear still no luck
-   return 0;
-}
-
-// find slide name from first h1 element
-// default to document title + slide number
-function slideName(index)
-{
-   var name = null;
-   var slide = slides[index];
-
-   var heading = findHeading(slide);
-
-   if (heading)
-     name = extractText(heading);
-
-   if (!name)
-     name = title + "(" + (index + 1) + ")";
-
-   name.replace(/\&/g, "&amp;");
-   name.replace(/\</g, "&lt;");
-   name.replace(/\>/g, "&gt;");
-
-   return name;
-}
-
-// find first h1 element in DOM tree
-function findHeading(node)
-{
-  if (!node || node.nodeType != 1)
-    return null;
-
-  if (node.nodeName == "H1" || node.nodeName == "h1")
-    return node;
-
-  var child = node.firstChild;
-
-  while (child)
-  {
-    node = findHeading(child);
-
-    if (node)
-      return node;
-
-    child = child.nextSibling;
-  }
-
-  return null;
-}
-
-// recursively extract text from DOM tree
-function extractText(node)
-{
-  if (!node)
-    return "";
-
-  // text nodes
-  if (node.nodeType == 3)
-    return node.nodeValue;
-
-  // elements
-  if (node.nodeType == 1)
-  {
-    node = node.firstChild;
-    var text = "";
-
-    while (node)
-    {
-      text = text + extractText(node);
-      node = node.nextSibling;
-    }
-
-    return text;
-  }
-
-  return "";
-}
-
-
-// find copyright text from meta element
-function findCopyright()
-{
-   var name, content;
-   var meta = document.getElementsByTagName("meta");
-
-   for (var i = 0; i < meta.length; ++i)
-   {
-      name = meta[i].getAttribute("name");
-      content = meta[i].getAttribute("content");
-
-      if (name == "copyright")
-         return content;
-   }
-
-   return null;
-}
-
-function findSizeAdjust()
-{
-   var name, content, offset;
-   var meta = document.getElementsByTagName("meta");
-
-   for (var i = 0; i < meta.length; ++i)
-   {
-      name = meta[i].getAttribute("name");
-      content = meta[i].getAttribute("content");
-
-      if (name == "font-size-adjustment")
-         return 1 * content;
-   }
-
-   return 0;
-}
-
-function addToolbar()
-{
-   var slideCounter, page;
-
-   var toolbar = createElement("div");
-   toolbar.setAttribute("class", "toolbar");
-
-   if (ns_pos) // a reasonably behaved browser
-   {
-      var right = document.createElement("div");
-      right.setAttribute("style", "float: right; text-align: right");
-
-      slideCounter = document.createElement("div")
-      slideCounter.innerHTML = "slide".localize() + " n/m";
-      right.appendChild(slideCounter);
-      toolbar.appendChild(right);
-
-      var left = document.createElement("div");
-      left.setAttribute("style", "text-align: left");
-
-      // global end of slide indicator
-      eos = document.createElement("span");
-      eos.innerHTML = "* ";
-      left.appendChild(eos);
-
-      var help = document.createElement("a");
-      help.setAttribute("href", helpPage);
-      help.setAttribute("title", helpText.localize());
-      help.innerHTML = "help?".localize();
-      left.appendChild(help);
-      helpAnchor = help;  // save for focus hack
-
-      var gap1 = document.createTextNode(" ");
-      left.appendChild(gap1);
-
-      var contents = document.createElement("a");
-      contents.setAttribute("href", "javascript:toggleTableOfContents()");
-      contents.setAttribute("title", "table of contents".localize());
-      contents.innerHTML = "contents?".localize();
-      left.appendChild(contents);
-
-      var gap2 = document.createTextNode(" ");
-      left.appendChild(gap2);
-
-      var i = location.href.indexOf("#");
-
-      // check if anchor is entire page
-
-      if (i > 0)
-         page = location.href.substr(0, i);
-      else
-         page = location.href;
-
-      var start = document.createElement("a");
-      start.setAttribute("href", page);
-      start.setAttribute("title", "restart presentation".localize());
-      start.innerHTML = "restart?".localize();
-//    start.setAttribute("href", "javascript:printSlides()");
-//    start.setAttribute("title", "print all slides".localize());
-//    start.innerHTML = "print!".localize();
-      left.appendChild(start);
-
-      var copyright = findCopyright();
-
-      if (copyright)
-      {
-         var span = document.createElement("span");
-         span.innerHTML = copyright;
-         span.style.color = "black";
-         span.style.marginLeft = "4em";
-         left.appendChild(span);
-      }
-
-      toolbar.appendChild(left);
-   }
-   else // IE so need to work around its poor CSS support
-   {
-      toolbar.style.position = (ie7 ? "fixed" : "absolute");
-      toolbar.style.zIndex = "200";
-      toolbar.style.width = "99.9%";
-      toolbar.style.height = "1.2em";
-      toolbar.style.top = "auto";
-      toolbar.style.bottom = "0";
-      toolbar.style.left = "0";
-      toolbar.style.right = "0";
-      toolbar.style.textAlign = "left";
-      toolbar.style.fontSize = "60%";
-      toolbar.style.color = "red";
-      toolbar.borderWidth = 0;
-      toolbar.style.background = "rgb(240,240,240)";
-
-      // would like to have help text left aligned
-      // and page counter right aligned, floating
-      // div's don't work, so instead use nested
-      // absolutely positioned div's.
-
-      var sp = document.createElement("span");
-      sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
-      toolbar.appendChild(sp);
-      eos = sp;  // end of slide indicator
-
-      var help = document.createElement("a");
-      help.setAttribute("href", helpPage);
-      help.setAttribute("title", helpText.localize());
-      help.innerHTML = "help?".localize();
-      toolbar.appendChild(help);
-      helpAnchor = help;  // save for focus hack
-
-      var gap1 = document.createTextNode(" ");
-      toolbar.appendChild(gap1);
-
-      var contents = document.createElement("a");
-      contents.setAttribute("href", "javascript:toggleTableOfContents()");
-      contents.setAttribute("title", "table of contents".localize());
-      contents.innerHTML = "contents?".localize();
-      toolbar.appendChild(contents);
-
-      var gap2 = document.createTextNode(" ");
-      toolbar.appendChild(gap2);
-
-      var i = location.href.indexOf("#");
-
-      // check if anchor is entire page
-
-      if (i > 0)
-         page = location.href.substr(0, i);
-      else
-         page = location.href;
-
-      var start = document.createElement("a");
-      start.setAttribute("href", page);
-      start.setAttribute("title", "restart presentation".localize());
-      start.innerHTML = "restart?".localize();
-//    start.setAttribute("href", "javascript:printSlides()");
-//    start.setAttribute("title", "print all slides".localize());
-//    start.innerHTML = "print!".localize();
-      toolbar.appendChild(start);
-
-      var copyright = findCopyright();
-
-      if (copyright)
-      {
-         var span = document.createElement("span");
-         span.innerHTML = copyright;
-         span.style.color = "black";
-         span.style.marginLeft = "2em";
-         toolbar.appendChild(span);
-      }
-
-      slideCounter = document.createElement("div")
-      slideCounter.style.position = "absolute";
-      slideCounter.style.width = "auto"; //"20%";
-      slideCounter.style.height = "1.2em";
-      slideCounter.style.top = "auto";
-      slideCounter.style.bottom = 0;
-      slideCounter.style.right = "0";
-      slideCounter.style.textAlign = "right";
-      slideCounter.style.color = "red";
-      slideCounter.style.background = "rgb(240,240,240)";
-
-      slideCounter.innerHTML = "slide".localize() + " n/m";
-      toolbar.appendChild(slideCounter);
-   }
-
-   // ensure that click isn't passed through to the page
-   toolbar.onclick = stopPropagation;
-   document.body.appendChild(toolbar);
-   slideNumElement = slideCounter;
-   setEosStatus(false);
-
-   return toolbar;
-}
-
-function isShownToc()
-{
-  if (toc && toc.style.visible == "visible")
-    return true;
-
-  return false;
-}
-
-function showTableOfContents()
-{
-  if (toc)
-  {
-    if (toc.style.visibility != "visible")
-    {
-      toc.style.visibility = "visible";
-      toc.style.display = "block";
-      toc.focus();
-
-      if (ie7 && slidenum == 0)
-        setTimeout("ieHack()", 100);
-    }
-    else
-      hideTableOfContents();
-  }
-}
-
-function hideTableOfContents()
-{
-  if (toc && toc.style.visibility != "hidden")
-  {
-    toc.style.visibility = "hidden";
-    toc.style.display = "none";
-
-    try
-    {
-       if (!opera)
-         helpAnchor.focus();
-    }
-    catch (e)
-    {
-    }
-  }
-}
-
-function toggleTableOfContents()
-{
-  if (toc)
-  {
-     if (toc.style.visible != "visible")
-       showTableOfContents();
-     else
-       hideTableOfContents();
-  }
-}
-
-// called on clicking toc entry
-function gotoEntry(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   if (target && target.nodeType == 1)
-   {
-     var uri = target.getAttribute("href");
-
-     if (uri)
-     {
-        //alert("going to " + uri);
-        var slide = slides[slidenum];
-        hideSlide(slide);
-        slidenum = findSlideNumber(uri);
-        slide = slides[slidenum];
-        lastShown = null;
-        setLocation();
-        setVisibilityAllIncremental("hidden");
-        setEosStatus(!nextIncrementalItem(lastShown));
-        showSlide(slide);
-        //target.focus();
-
-        try
-        {
-           if (!opera)
-             helpAnchor.focus();
-        }
-        catch (e)
-        {
-        }
-     }
-   }
-
-   hideTableOfContents(e);
-   if (ie7) ieHack();
-   stopPropagation(e);
-   return cancel(e);
-}
-
-// called onkeydown for toc entry
-function gotoTocEntry(event)
-{
-  var key;
-
-  if (!event)
-    var event = window.event;
-
-  // kludge around NS/IE differences 
-  if (window.event)
-    key = window.event.keyCode;
-  else if (event.which)
-    key = event.which;
-  else
-    return true; // Yikes! unknown browser
-
-  // ignore event if key value is zero
-  // as for alt on Opera and Konqueror
-  if (!key)
-     return true;
-
-  // check for concurrent control/command/alt key
-  // but are these only present on mouse events?
-
-  if (event.ctrlKey || event.altKey)
-     return true;
-
-  if (key == 13)
-  {
-    var uri = this.getAttribute("href");
-
-    if (uri)
-    {
-      //alert("going to " + uri);
-      var slide = slides[slidenum];
-      hideSlide(slide);
-      slidenum = findSlideNumber(uri);
-      slide = slides[slidenum];
-      lastShown = null;
-      setLocation();
-      setVisibilityAllIncremental("hidden");
-      setEosStatus(!nextIncrementalItem(lastShown));
-      showSlide(slide);
-      //target.focus();
-
-      try
-      {
-         if (!opera)
-           helpAnchor.focus();
-      }
-      catch (e)
-      {
-      }
-    }
-
-    hideTableOfContents();
-    if (ie7) ieHack();
-    return cancel(event);
-  }
-
-  if (key == 40 && this.next)
-  {
-    this.next.focus();
-    return cancel(event);
-  }
-
-  if (key == 38 && this.previous)
-  {
-    this.previous.focus();
-    return cancel(event);
-  }
-
-  return true;
-}
-
-function isTitleSlide(slide)
-{
-   return hasClass(slide, "title");
-}
-
-// create div element with links to each slide
-function tableOfContents()
-{
-  var toc = document.createElement("div");
-  addClass(toc, "toc");
-  //toc.setAttribute("tabindex", "0");
-
-  var heading = document.createElement("div");
-  addClass(heading, "toc-heading");
-  heading.innerHTML = "Table of Contents".localize();
-
-  heading.style.textAlign = "center";
-  heading.style.width = "100%";
-  heading.style.margin = "0";
-  heading.style.marginBottom = "1em";
-  heading.style.borderBottomStyle = "solid";
-  heading.style.borderBottomColor = "rgb(180,180,180)";
-  heading.style.borderBottomWidth = "1px";
-
-  toc.appendChild(heading);
-  var previous = null;
-
-  for (var i = 0; i < slides.length; ++i)
-  {
-    var title = hasClass(slides[i], "title");
-    var num = document.createTextNode((i + 1) + ". ");
-
-    toc.appendChild(num);
-
-    var a = document.createElement("a");
-    a.setAttribute("href", "#(" + (i+1) + ")");
-
-    if (title)
-      addClass(a, "titleslide");
-
-    var name = document.createTextNode(slideName(i));
-    a.appendChild(name);
-    a.onclick = gotoEntry;
-    a.onkeydown = gotoTocEntry;
-    a.previous = previous;
-
-    if (previous)
-      previous.next = a;
-
-    toc.appendChild(a);
-
-    if (i == 0)
-      toc.first = a;
-
-    if (i < slides.length - 1)
-    {
-      var br = document.createElement("br");
-      toc.appendChild(br);
-    }
-
-    previous = a;
-  }
-
-  toc.focus = function () {
-    if (this.first)
-      this.first.focus();
-  }
-
-  toc.onclick = function (e) {
-    e||(e=window.event);
-    hideTableOfContents();
-    stopPropagation(e);
-    
-    if (e.cancel != undefined)
-      e.cancel = true;
-      
-    if (e.returnValue != undefined)
-      e.returnValue = false;
-      
-    return false;
-  };
-
-  toc.style.position = "absolute";
-  toc.style.zIndex = "300";
-  toc.style.width = "60%";
-  toc.style.maxWidth = "30em";
-  toc.style.height = "30em";
-  toc.style.overflow = "auto";
-  toc.style.top = "auto";
-  toc.style.right = "auto";
-  toc.style.left = "4em";
-  toc.style.bottom = "4em";
-  toc.style.padding = "1em";
-  toc.style.background = "rgb(240,240,240)";
-  toc.style.borderStyle = "solid";
-  toc.style.borderWidth = "2px";
-  toc.style.fontSize = "60%";
-
-  document.body.insertBefore(toc, document.body.firstChild);
-  return toc;
-}
-
-function replaceByNonBreakingSpace(str)
-{
-   for (var i = 0; i < str.length; ++i)
-      str[i] = 160;
-}
-
-
-function initOutliner()
-{
-  var items = document.getElementsByTagName("LI");
-
-  for (var i = 0; i < items.length; ++i)
-  {
-     var target = items[i];
-
-     if (!hasClass(target.parentNode, "outline"))
-        continue;
-
-     target.onclick = outlineClick;
-
-     if (!ns_pos)
-     {
-        target.onmouseover = hoverOutline;
-        target.onmouseout = unhoverOutline;
-     }
-
-     if (foldable(target))
-     {
-       target.foldable = true;
-       target.onfocus = function () {outline = this;};
-       target.onblur = function () {outline = null;};
-
-       if (!target.getAttribute("tabindex"))
-         target.setAttribute("tabindex", "0");
-
-       if (hasClass(target, "expand"))
-         unfold(target);
-       else
-         fold(target);
-     }
-     else
-     {
-       addClass(target, "nofold");
-       target.visible = true;
-       target.foldable = false;
-     }
-  }
-}
-
-function foldable(item)
-{
-   if (!item || item.nodeType != 1)
-      return false;
-
-   var node = item.firstChild;
-
-   while (node)
-   {
-     if (node.nodeType == 1 && isBlock(node))
-       return true;
-
-      node = node.nextSibling;
-   }
-
-   return false;
-}
-
-function fold(item)
-{
-  if (item)
-  {
-    removeClass(item, "unfolded");
-    addClass(item, "folded");
-  }
-
-  var node = item ? item.firstChild : null;
-
-  while (node)
-  {
-    if (node.nodeType == 1 && isBlock(node)) // element
-    {
-      // note that getElementStyle won't work for Safari 1.3
-      node.display = getElementStyle(node, "display", "display");
-      node.style.display = "none";
-      node.style.visibility = "hidden";
-    }
-
-    node = node.nextSibling;
-  }
-
-  item.visible = false;
-}
-
-function unfold(item)
-{
-   if (item)
-   {
-     addClass(item, "unfolded");
-     removeClass(item, "folded");
-   }
-
-  var node = item ? item.firstChild : null;
-
-  while (node)
-  {
-    if (node.nodeType == 1 && isBlock(node)) // element
-    {
-      // with fallback for Safari, see above
-      node.style.display = (node.display ? node.display : "block");
-      node.style.visibility = "visible";
-    }
-
-    node = node.nextSibling;
-  }
-
-  item.visible = true;
-}
-
-function outlineClick(e)
-{
-   var rightclick = false;
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (!target)
-      return true;
-
-   if (e.which)
-      rightclick = (e.which == 3);
-   else if (e.button)
-      rightclick = (e.button == 2);
-
-   if (!rightclick && target.visible != undefined)
-   {
-      if (target.foldable)
-      {
-         if (target.visible)
-           fold(target);
-         else
-           unfold(target);
-      }
-
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-   }
-
-   return false;
-}
-
-function hoverOutline(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (target && target.foldable)
-      target.style.cursor = "pointer";
-
-   return true;
-}
-
-function unhoverOutline(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (target)
-     target.style.cursor = "default";
-
-   return true;
-}
-
-
-function stopPropagation(e)
-{
-   if (window.event)
-   {
-      window.event.cancelBubble = true;
-      //window.event.returnValue = false;
-   }
-   else if (e)
-   {
-      e.cancelBubble = true;
-      e.stopPropagation();
-      //e.preventDefault();
-   }
-}
-
-/* can't rely on display since we set that to none to hide things */
-function isBlock(elem)
-{
-   var tag = elem.nodeName;
-
-   return tag == "OL" || tag == "UL" || tag == "P" ||
-          tag == "LI" || tag == "TABLE" || tag == "PRE" ||
-          tag == "H1" || tag == "H2" || tag == "H3" ||
-          tag == "H4" || tag == "H5" || tag == "H6" ||
-          tag == "BLOCKQUOTE" || tag == "ADDRESS"; 
-}
-
-function getElementStyle(elem, IEStyleProp, CSSStyleProp)
-{
-   if (elem.currentStyle)
-   {
-      return elem.currentStyle[IEStyleProp];
-   }
-   else if (window.getComputedStyle)
-   {
-      var compStyle = window.getComputedStyle(elem, "");
-      return compStyle.getPropertyValue(CSSStyleProp);
-   }
-   return "";
-}
-
-// works with text/html and text/xhtml+xml with thanks to Simon Willison
-function createElement(element)
-{
-   if (typeof document.createElementNS != 'undefined')
-   {
-      return document.createElementNS('http://www.w3.org/1999/xhtml', element);
-   }
-
-   if (typeof document.createElement != 'undefined')
-   {
-      return document.createElement(element);
-   }
-
-   return false;
-}
-
-// designed to work with both text/html and text/xhtml+xml
-function getElementsByTagName(name)
-{
-   if (typeof document.getElementsByTagNameNS != 'undefined')
-   {
-      return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name);
-   }
-
-   if (typeof document.getElementsByTagName != 'undefined')
-   {
-      return document.getElementsByTagName(name);
-   }
-
-   return null;
-}
-
-/*
-// clean alternative to innerHTML method, but on IE6
-// it doesn't work with named entities like &nbsp;
-// which need to be replaced by numeric entities
-function insertText(element, text)
-{
-   try
-   {
-     element.textContent = text;  // DOM3 only
-   }
-   catch (e)
-   {
-      if (element.firstChild)
-      {
-         // remove current children
-         while (element.firstChild)
-            element.removeChild(element.firstChild);
-      }
-
-      element.appendChild(document.createTextNode(text));
-   }
-}
-
-// as above, but as method of all element nodes
-// doesn't work in IE6 which doesn't allow you to
-// add methods to the HTMLElement prototype
-if (HTMLElement != undefined)
-{
-  HTMLElement.prototype.insertText = function(text) {
-    var element = this;
-
-    try
-    {
-      element.textContent = text;  // DOM3 only
-    }
-    catch (e)
-    {
-      if (element.firstChild)
-      {
-         // remove current children
-         while (element.firstChild)
-           element.removeChild(element.firstChild);
-      }
-
-      element.appendChild(document.createTextNode(text));
-    }
-  };
-}
-*/
-
-function getSelectedText()
-{
-  try
-  {
-    if (window.getSelection)
-      return window.getSelection().toString();
-
-    if (document.getSelection)
-      return document.getSelection().toString();
-
-    if (document.selection)
-      return document.selection.createRange().text;
-  }
-  catch (e)
-  {
-    return "";
-  }
-  return "";
-}
diff --git a/content/2011/Real_World_Go.pdf b/content/2011/Real_World_Go.pdf
deleted file mode 100644
index 2a18711..0000000
--- a/content/2011/Real_World_Go.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2011/Writing_Web_Apps_in_Go.pdf b/content/2011/Writing_Web_Apps_in_Go.pdf
deleted file mode 100644
index ca4702e..0000000
--- a/content/2011/Writing_Web_Apps_in_Go.pdf
+++ /dev/null
Binary files differ
diff --git a/content/2011/lex.slide b/content/2011/lex.slide
deleted file mode 100644
index d2fed7b..0000000
--- a/content/2011/lex.slide
+++ /dev/null
@@ -1,351 +0,0 @@
-Lexical Scanning in Go
-GTUG Sydney
-30 Aug 2011
-
-Rob Pike
-r@golang.org
-
-
-* Video
-
-A video of this talk was recorded at the Go Sydney Meetup.
-
-.link https://www.youtube.com/watch?v=HxaD_trXwRE Watch the talk on YouTube
-
-
-* Structural mismatch
-
-Many programming problems realign one data structure to fit another structure.
-
-- breaking text into lines
-- "blocking" and "deblocking"
-- packet assembly and disassembly
-- parsing
-- lexing
-
-* Sometimes hard
-
-The pieces on either side have independent state, lookahead, buffers, ...
-Can be messy to do well.
-
-Coroutines were invented to solve this problem!
-They enable us to write the two pieces independently.
-
-Let's look at this topic in the context of a lexer.
-
-
-* A new template system
-
-Wanted to replace the old Go template package.
-It had many problems:
-
-- inflexible
-- inexpressive
-- code too fragile
-
-* A new template system
-
-Key change was re-engineering with a true lexer, parser, and evaluator.
-Has arbitrary text plus actions in `{{` `}}`.
-
-.code lex/snippets /Evaluation/,/Control.structures/
-
-* Today we focus on the lexer
-
-Must tokenize:
-
-- the stuff outside actions
-- action delimiters
-- identifiers
-- numeric constants
-- string constants
-- and others
-
-* Lex items
-
-Two things identify each lexed item:
-
-- its type
-- its value; a string is all we need
-
-.code lex/lex1.oldgo /item.represents/,/^}/
-
-* Lex type
-
-The type is just an integer constant.
-We use `iota` to define the values.
-
-.code lex/lex1.oldgo /itemType.identifies/,/type/
-.code lex/lex1.oldgo /const/,/itemEOF/
-
-* Lex type values (continued)
-
-.code lex/lex1.oldgo /itemElse/,/^\)/
-
-* Printing a lex item
-
-`Printf` has a convention making it easy to print any type: just define a `String()` method:
-
-.code lex/lex1.oldgo /func.*item.*String/,/^}/
-
-* How to tokenize?
-
-Many approaches available:
-
-- use a tool such as lex or ragel
-- use regular expressions
-- use states, actions, and a switch statement
-
-* Tools
-
-Nothing wrong with using a tool but:
-
-- hard to get good errors (can be very important)
-- tend to require learning another language
-- result can be large, even slow
-- often a poor fit
-- but lexing is easy to do yourself!
-
-* Regular expressions
-
-Blogged about this last week.
-
-- overkill
-- slow
-- can explore the state space too much
-- misuse of a dynamic engine to ask static questions
-
-* Let's write our own
-
-It's easy!
-
-Plus, most programming languages lex pretty much the same tokens, so once we learn how it's trivial to adapt the lexer for the next purpose.
-
-- an argument both for and against tools
-
-* State machine
-
-Many people will tell you to write a switch statement,
-something like this:
-
-.code lex/snippets /One/,/^}/
-
-* State machines are forgetful
-
-Boring and repetitive and error-prone, but anyway:
-
-Why switch?
-
-After each action, you know where you want to be;
-the new state is the result of the action.
-
-But we throw the info away and recompute it from the state.
-
-(A consequence of returning to the caller.)
-
-A tool can compile that out, but so can we.
-
-* What is a state? An action?
-
-State represents where we are and what we expect.
-
-Action represents what we do.
-
-Actions result in a new state.
-
-* State function
-
-Let's put them together: a state function.
-
-Executes an action, returns the next state—as a state function.
-
-Recursive definition but simple and clear.
-
-.code lex/lex1.oldgo /stateFn/,/type/
-
-* The run loop
-
-Our state machine is trivial:
-just run until the state goes to `nil`, representing "done".
-
-.code lex/snippets /run.lexes/,/^}/
-
-* The concurrent step
-
-How do we make tokens available to the client?
-Tokens can emerge at times that are inconvenient to stop to return to the caller.
-
-Use concurrency:
-Run the state machine as a goroutine,
-emit values on a channel.
-
-* The lexer type
-
-Here is the `lexer` type. Notice the channel of items; ignore the rest for now.
-
-.code lex/lex1.oldgo /lexer.holds/,/^}/
-
-* Starting the lexer
-
-A `lexer` initializes itself to lex a string and launches the state machine as a goroutine, returning the lexer itself and a channel of items.
-
-The API will change, don't worry about it now.
-
-.code lex/lex1.oldgo /func.lex/,/^}/
-
-* The real run routine
-
-Here's the real state machine run function, which runs as a goroutine.
-
-.code lex/lex1.oldgo /run.lexes/,/^}/
-
-* The token emitter
-
-A token is a type and a value, but (yay Go) the value can just be sliced from the input string.
-The `lexer` remembers where it is in the input and the emit routine just lobs that substring to the caller as the token's value.
-
-.code lex/lex1.oldgo /input.*scanned/,/pos.*position/
-.code lex/lex1.oldgo /emit.passes/,/^}/
-
-* Starting the machine
-
-As the `lexer` begins it's looking for plain text, so the initial state is the function `lexText`.
-It absorbs plain text until a "left meta" is encountered.
-
-.code lex/lex1.oldgo /run.lexes/,/^}/
-.code lex/lex1.oldgo /leftMeta/
-
-* lexText
-
-.code lex/lex1.oldgo /^func.lexText/,/^}/
-
-* lexLeftMeta
-
-A trivial state function.
-When we get here, we know there's a `leftMeta` in the input.
-
-.code lex/lex1.oldgo /^func.lexLeftMeta/,/^}/
-
-* lexInsideAction
-
-.code lex/lex1.oldgo /^func.lexInsideAction/,/itemPipe/
-
-* More of lexInsideAction
-
-This will give you the flavor.
-
-.code lex/lex1.oldgo /case.*"/,/lexRawQuote/
-.code lex/lex1.oldgo /case.*9/,/lexIdentifier/
-
-* The next function
-
-.code lex/lex1.oldgo /next.returns.the/,/^}/
-
-* Some lexing helpers
-
-.code lex/lex1.oldgo /ignore.skips/,/^}/
-.code lex/lex1.oldgo /backup.steps/,/^}/
-
-* The peek function
-
-.code lex/lex1.oldgo /peek.returns.but/,/^}/
-
-* The accept functions
-
-.code lex/lex1.oldgo /accept.consumes/,/^}/
-.code lex/lex1.oldgo /acceptRun.consumes/,/^}/
-
-* Lexing a number, including floating point
-
-.code lex/lex1.oldgo /^func.lexNumber/,/imaginary/
-
-* Lexing a number, continued
-
-This is more accepting than it should be, but not by much. Caller must call `Atof` to validate.
-
-.code lex/lex1.oldgo /Is.it.imaginary/,/^}/
-
-* Errors
-
-Easy to handle: emit the bad token and shut down the machine.
-
-.code lex/lex1.oldgo /error.returns/,/^}/
-
-* Summary
-
-Concurrency makes the lexer easy to design.
-
-Goroutines allow lexer and caller (parser) each to run at its own rate, as clean sequential code.
-
-Channels give us a clean way to emit tokens.
-
-* A problem
-
-Can't run a goroutine to completion during initialization.
-Forbidden by the language specification.
-(Raises awful issues about order of init, best avoided.)
-
-That means we can't lex & parse a template during init.
-
-The goroutine is a problem....
-
-_(Note:_This_restriction_was_lifted_in_Go_version_1_but_the_discussion_is_still_interesting.)_
-
-* Design vs. implementation
-
-…but it's not necessary anyway.
-
-The work is done by the design; now we just adjust the API.
-
-We can change the API to hide the channel, provide a function to get the next token, and rewrite the run function.
-
-It's easy.
-
-* A new API
-
-Hide the channel and buffer it slightly, turning it into a ring buffer.
-
-.code lex/r59-lex.go /lex.creates.a.new/,/^}/
-
-* A function for the next item
-
-Traditional lexer API: return next item.
-Includes the modified state machine runner.
-
-.code lex/r59-lex.go /nextItem.returns/,/^}/
-
-* That's it
-
-We now have a traditional API for a lexer with a simple, concurrent implementation under the covers.
-
-Even though the implementation is no longer truly concurrent, it still has all the advantages of concurrent design.
-
-We wouldn't have such a clean, efficient design if we hadn't thought about the problem in a concurrent way, without worrying about "restart".
-
-Model completely removes concerns about "structural mismatch".
-
-* Concurrency is a design approach
-
-Concurrency is not about parallelism.
-
-(Although it can enable parallelism).
-
-Concurrency is a way to design a program by decomposing it into independently executing pieces.
-
-The result can be clean, efficient, and very adaptable.
-
-* Conclusion
-
-Lexers are fun.
-
-Concurrency is fun.
-
-Go is fun.
-
-* For more information
-
-Go: [[http://golang.org]]
-
-New templates: http://golang.org/pkg/exp/template/
-
-(Next release will move them out of experimental.)
diff --git a/content/2011/lex/lex1.oldgo b/content/2011/lex/lex1.oldgo
deleted file mode 100644
index 0a1b1d4..0000000
--- a/content/2011/lex/lex1.oldgo
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// reformatted, slightly edited version of lex.go from weekly.11-06-23
-
-package template
-
-import (
-	"fmt"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// item represents a token returned from the scanner.
-type item struct {
-	typ itemType  // Type, such as itemNumber.
-	val string    // Value, such as "23.2".
-}
-
-func (i item) String() string {
-	switch i.typ {
-	case itemEOF:
-		return "EOF"
-	case itemError:
-		return i.val
-	}
-	if len(i.val) > 10 {
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError itemType = iota // error occurred;
-	                          // value is text of error
-	itemDot                   // the cursor, spelled '.'
-	itemEOF
-	itemElse       // else keyword
-	itemEnd        // end keyword
-	itemField      // identifier, starting with '.'
-	itemIdentifier // identifier
-	itemIf         // if keyword
-	itemLeftMeta   // left meta-string
-	itemNumber     // number
-	itemPipe       // pipe symbol
-	itemRange      // range keyword
-	itemRawString  // raw quoted string (includes quotes)
-	itemRightMeta  // right meta-string
-	itemString     // quoted string (includes quotes)
-	itemText       // plain text
-)
-
-// Make the types prettyprint.
-var itemName = map[itemType]string{
-	itemError:      "error",
-	itemDot:        ".",
-	itemEOF:        "EOF",
-	itemElse:       "else",
-	itemEnd:        "end",
-	itemField:      "field",
-	itemIdentifier: "identifier",
-	itemIf:         "if",
-	itemLeftMeta:   "left meta",
-	itemNumber:     "number",
-	itemPipe:       "pipe",
-	itemRange:      "range",
-	itemRawString:  "raw string",
-	itemRightMeta:  "rightMeta",
-	itemString:     "string",
-	itemText:       "text",
-}
-
-func (i itemType) String() string {
-	s := itemName[i]
-	if s == "" {
-		return fmt.Sprintf("item%d", int(i))
-	}
-	return s
-}
-
-var key = map[string]itemType{
-	".":     itemDot,
-	"else":  itemElse,
-	"end":   itemEnd,
-	"if":    itemIf,
-	"range": itemRange,
-}
-
-const eof = -1
-
-// stateFn represents the state of the scanner
-// as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	name  string    // used only for error reports.
-	input string    // the string being scanned.
-	start int       // start position of this item.
-	pos   int       // current position in the input.
-	width int       // width of last rune read from input.
-	items chan item // channel of scanned items.
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() (rune int) {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	rune, l.width =
-		utf8.DecodeRuneInString(l.input[l.pos:])
-	l.pos += l.width
-	return rune
-}
-
-// peek returns but does not consume
-// the next rune in the input.
-func (l *lexer) peek() int {
-	rune := l.next()
-	l.backup()
-	return rune
-}
-
-// backup steps back one rune.
-// Can be called only once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	l.items <- item{t, l.input[l.start:l.pos]}
-	l.start = l.pos
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// accept consumes the next rune
-// if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.IndexRune(valid, l.next()) >= 0 {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.IndexRune(valid, l.next()) >= 0 {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.pos], "\n")
-}
-
-// error returns an error token and terminates the scan
-// by passing back a nil pointer that will be the next
-// state, terminating l.run.
-func (l *lexer) errorf(format string, args ...interface{})
-  stateFn {
-	l.items <- item{
-		itemError,
-		fmt.Sprintf(format, args...),
-	}
-	return nil
-}
-
-// run lexes the input by executing state functions until
-// the state is nil.
-func (l *lexer) run() {
-	for state := lexText; state != nil; {
-		state = state(l)
-	}
-	close(l.items) // No more tokens will be delivered.
-}
-
-// lex launches a new scanner and returns the channel of items.
-func lex(name, input string) (*lexer, chan item) {
-	l := &lexer{
-		name:  name,
-		input: input,
-		items: make(chan item),
-	}
-	go l.run()  // Concurrently run state machine.
-	return l, l.items
-}
-
-// state functions
-
-const leftMeta = "{{"
-const rightMeta = "}}"
-
-// lexText scans until a metacharacter
-func lexText(l *lexer) stateFn {
-	for {
-		if strings.HasPrefix(l.input[l.pos:], leftMeta) {
-			if l.pos > l.start {
-				l.emit(itemText)
-			}
-			return lexLeftMeta    // Next state.
-		}
-		if l.next() == eof { break }
-	}
-	// Correctly reached EOF.
-	if l.pos > l.start {
-		l.emit(itemText)
-	}
-	l.emit(itemEOF)  // Useful to make EOF a token.
-	return nil       // Stop the run loop.
-}
-
-// leftMeta scans the left "metacharacter", which is known to be present.
-func lexLeftMeta(l *lexer) stateFn {
-	l.pos += len(leftMeta)
-	l.emit(itemLeftMeta)
-	return lexInsideAction    // Now inside {{ }}.
-}
-
-// rightMeta scans the right "metacharacter", which is known to be present.
-func lexRightMeta(l *lexer) stateFn {
-	l.pos += len(rightMeta)
-	l.emit(itemRightMeta)
-	return lexText
-}
-
-// lexInsideAction scans the elements inside "metacharacters".
-func lexInsideAction(l *lexer) stateFn {
-	// Either number, quoted string, or identifier.
-	// Spaces separate and are ignored.
-	// Pipe symbols separate and are emitted.
-	for {
-		if strings.HasPrefix(l.input[l.pos:], rightMeta) {
-			return lexRightMeta
-		}
-		switch r := l.next(); {
-		case r == eof || r == '\n':
-			return l.errorf("unclosed action")
-		case isSpace(r):
-			l.ignore()
-		case r == '|':
-			l.emit(itemPipe)
-		case r == '"':
-			return lexQuote
-		case r == '`':
-			return lexRawQuote
-		case r == '.':
-			// special look-ahead for ".field" so we don't break l.backup().
-			if l.pos < len(l.input) {
-				r := l.input[l.pos]
-				if r < '0' || '9' < r {
-					return lexIdentifier // itemDot comes from the keyword table.
-				}
-			}
-			fallthrough // '.' can start a number.
-		case r == '+' || r == '-' || '0' <= r && r <= '9':
-			l.backup()
-			return lexNumber
-		case isAlphaNumeric(r):
-			l.backup()
-			return lexIdentifier
-		default:
-			return l.errorf("unrecognized character in action: %#U", r)
-		}
-	}
-	return nil
-}
-
-// lexIdentifier scans an alphanumeric or field.
-func lexIdentifier(l *lexer) stateFn {
-Loop:
-	for {
-		switch r := l.next(); {
-		case isAlphaNumeric(r):
-			// absorb
-		default:
-			l.backup()
-			word := l.input[l.start:l.pos]
-			switch {
-			case key[word] != itemError:
-				l.emit(key[word])
-			case word[0] == '.':
-				l.emit(itemField)
-			default:
-				l.emit(itemIdentifier)
-			}
-			break Loop
-		}
-	}
-	return lexInsideAction
-}
-
-// lexNumber scans a number: decimal, octal, hex, float, or imaginary.  This
-// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
-// and "089" - but when it's wrong the input is invalid and the parser (via
-// strconv) will notice.
-// TODO: without expressions you can do imaginary but not complex.
-func lexNumber(l *lexer) stateFn {
-	// Optional leading sign.
-	l.accept("+-")
-	// Is it hex?
-	digits := "0123456789"
-	if l.accept("0") && l.accept("xX") {
-		digits = "0123456789abcdefABCDEF"
-	}
-	l.acceptRun(digits)
-	if l.accept(".") {
-		l.acceptRun(digits)
-	}
-	if l.accept("eE") {
-		l.accept("+-")
-		l.acceptRun("0123456789")
-	}
-	// Is it imaginary?
-	l.accept("i")
-	// Next thing mustn't be alphanumeric.
-	if isAlphaNumeric(l.peek()) {
-		l.next()
-		return l.errorf("bad number syntax: %q",
-			l.input[l.start:l.pos])
-	}
-	l.emit(itemNumber)
-	return lexInsideAction
-}
-
-// lexQuote scans a quoted string.
-func lexQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case '\\':
-			if r := l.next(); r != eof && r != '\n' {
-				break
-			}
-			fallthrough
-		case eof, '\n':
-			return l.errorf("unterminated quoted string")
-		case '"':
-			break Loop
-		}
-	}
-	l.emit(itemString)
-	return lexInsideAction
-}
-
-// lexRawQuote scans a raw quoted string.
-func lexRawQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case eof, '\n':
-			return l.errorf("unterminated raw quoted string")
-		case '`':
-			break Loop
-		}
-	}
-	l.emit(itemRawString)
-	return lexInsideAction
-}
-
-// isSpace reports whether r is a space character.
-func isSpace(r int) bool {
-	switch r {
-	case ' ', '\t', '\n', '\r':
-		return true
-	}
-	return false
-}
-
-// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
-func isAlphaNumeric(r int) bool {
-	return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
-}
diff --git a/content/2011/lex/r59-lex.go b/content/2011/lex/r59-lex.go
deleted file mode 100644
index 33af2db..0000000
--- a/content/2011/lex/r59-lex.go
+++ /dev/null
@@ -1,433 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-package template
-
-import (
-	"fmt"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// item represents a token or text string returned from the scanner.
-type item struct {
-	typ itemType
-	val string
-}
-
-func (i item) String() string {
-	switch {
-	case i.typ == itemEOF:
-		return "EOF"
-	case i.typ == itemError:
-		return i.val
-	case i.typ > itemKeyword:
-		return fmt.Sprintf("<%s>", i.val)
-	case len(i.val) > 10:
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError   itemType = iota // error occurred; value is text of error
-	itemBool                    // boolean constant
-	itemComplex                 // complex constant (1+2i); imaginary is just a number
-	itemEOF
-	itemField      // alphanumeric identifier, starting with '.', possibly chained ('.x.y')
-	itemIdentifier // alphanumeric identifier
-	itemLeftDelim  // left action delimiter
-	itemNumber     // simple number, including imaginary
-	itemPipe       // pipe symbol
-	itemRawString  // raw quoted string (includes quotes)
-	itemRightDelim // right action delimiter
-	itemString     // quoted string (includes quotes)
-	itemText       // plain text
-	// Keywords appear after all the rest.
-	itemKeyword  // used only to delimit the keywords
-	itemDot      // the cursor, spelled '.'.
-	itemDefine   // define keyword
-	itemElse     // else keyword
-	itemEnd      // end keyword
-	itemIf       // if keyword
-	itemRange    // range keyword
-	itemTemplate // template keyword
-	itemWith     // with keyword
-)
-
-// Make the types prettyprint.
-var itemName = map[itemType]string{
-	itemError:      "error",
-	itemBool:       "bool",
-	itemComplex:    "complex",
-	itemEOF:        "EOF",
-	itemField:      "field",
-	itemIdentifier: "identifier",
-	itemLeftDelim:  "left delim",
-	itemNumber:     "number",
-	itemPipe:       "pipe",
-	itemRawString:  "raw string",
-	itemRightDelim: "right delim",
-	itemString:     "string",
-	// keywords
-	itemDot:      ".",
-	itemDefine:   "define",
-	itemElse:     "else",
-	itemIf:       "if",
-	itemEnd:      "end",
-	itemRange:    "range",
-	itemTemplate: "template",
-	itemWith:     "with",
-}
-
-func (i itemType) String() string {
-	s := itemName[i]
-	if s == "" {
-		return fmt.Sprintf("item%d", int(i))
-	}
-	return s
-}
-
-var key = map[string]itemType{
-	".":        itemDot,
-	"define":   itemDefine,
-	"else":     itemElse,
-	"end":      itemEnd,
-	"if":       itemIf,
-	"range":    itemRange,
-	"template": itemTemplate,
-	"with":     itemWith,
-}
-
-const eof = -1
-
-// stateFn represents the state of the scanner as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	name  string    // the name of the input; used only for error reports.
-	input string    // the string being scanned.
-	state stateFn   // the next lexing function to enter
-	pos   int       // current position in the input.
-	start int       // start position of this item.
-	width int       // width of last rune read from input.
-	items chan item // channel of scanned items.
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() (rune int) {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
-	l.pos += l.width
-	return rune
-}
-
-// peek returns but does not consume the next rune in the input.
-func (l *lexer) peek() int {
-	rune := l.next()
-	l.backup()
-	return rune
-}
-
-// backup steps back one rune. Can only be called once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	l.items <- item{t, l.input[l.start:l.pos]}
-	l.start = l.pos
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// accept consumes the next rune if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.IndexRune(valid, l.next()) >= 0 {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.IndexRune(valid, l.next()) >= 0 {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.pos], "\n")
-}
-
-// error returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.run.
-func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, fmt.Sprintf(format, args...)}
-	return nil
-}
-
-// nextItem returns the next item from the input.
-func (l *lexer) nextItem() item {
-	for {
-		select {
-		case item := <-l.items:
-			return item
-		default:
-			l.state = l.state(l)
-		}
-	}
-	panic("not reached")
-}
-
-// lex creates a new scanner for the input string.
-func lex(name, input string) *lexer {
-	l := &lexer{
-		name:  name,
-		input: input,
-		state: lexText,
-		items: make(chan item, 2), // Two items sufficient.
-	}
-	return l
-}
-
-// state functions
-
-const (
-	leftDelim    = "{{"
-	rightDelim   = "}}"
-	leftComment  = "{{/*"
-	rightComment = "*/}}"
-)
-
-// lexText scans until an opening action delimiter, "{{".
-func lexText(l *lexer) stateFn {
-	for {
-		if strings.HasPrefix(l.input[l.pos:], leftDelim) {
-			if l.pos > l.start {
-				l.emit(itemText)
-			}
-			return lexLeftDelim
-		}
-		if l.next() == eof {
-			break
-		}
-	}
-	// Correctly reached EOF.
-	if l.pos > l.start {
-		l.emit(itemText)
-	}
-	l.emit(itemEOF)
-	return nil
-}
-
-// lexLeftDelim scans the left delimiter, which is known to be present.
-func lexLeftDelim(l *lexer) stateFn {
-	if strings.HasPrefix(l.input[l.pos:], leftComment) {
-		return lexComment
-	}
-	l.pos += len(leftDelim)
-	l.emit(itemLeftDelim)
-	return lexInsideAction
-}
-
-// lexComment scans a comment. The left comment marker is known to be present.
-func lexComment(l *lexer) stateFn {
-	i := strings.Index(l.input[l.pos:], rightComment)
-	if i < 0 {
-		return l.errorf("unclosed comment")
-	}
-	l.pos += i + len(rightComment)
-	l.ignore()
-	return lexText
-}
-
-// lexRightDelim scans the right delimiter, which is known to be present.
-func lexRightDelim(l *lexer) stateFn {
-	l.pos += len(rightDelim)
-	l.emit(itemRightDelim)
-	return lexText
-}
-
-// lexInsideAction scans the elements inside action delimiters.
-func lexInsideAction(l *lexer) stateFn {
-	// Either number, quoted string, or identifier.
-	// Spaces separate and are ignored.
-	// Pipe symbols separate and are emitted.
-	for {
-		if strings.HasPrefix(l.input[l.pos:], rightDelim) {
-			return lexRightDelim
-		}
-		switch r := l.next(); {
-		case r == eof || r == '\n':
-			return l.errorf("unclosed action")
-		case isSpace(r):
-			l.ignore()
-		case r == '|':
-			l.emit(itemPipe)
-		case r == '"':
-			return lexQuote
-		case r == '`':
-			return lexRawQuote
-		case r == '.':
-			// special look-ahead for ".field" so we don't break l.backup().
-			if l.pos < len(l.input) {
-				r := l.input[l.pos]
-				if r < '0' || '9' < r {
-					return lexIdentifier // itemDot comes from the keyword table.
-				}
-			}
-			fallthrough // '.' can start a number.
-		case r == '+' || r == '-' || ('0' <= r && r <= '9'):
-			l.backup()
-			return lexNumber
-		case isAlphaNumeric(r):
-			l.backup()
-			return lexIdentifier
-		default:
-			return l.errorf("unrecognized character in action: %#U", r)
-		}
-	}
-	return nil
-}
-
-// lexIdentifier scans an alphanumeric or field.
-func lexIdentifier(l *lexer) stateFn {
-Loop:
-	for {
-		switch r := l.next(); {
-		case isAlphaNumeric(r):
-			// absorb.
-		case r == '.' && l.input[l.start] == '.':
-			// field chaining; absorb into one token.
-		default:
-			l.backup()
-			word := l.input[l.start:l.pos]
-			switch {
-			case key[word] > itemKeyword:
-				l.emit(key[word])
-			case word[0] == '.':
-				l.emit(itemField)
-			case word == "true", word == "false":
-				l.emit(itemBool)
-			default:
-				l.emit(itemIdentifier)
-			}
-			break Loop
-		}
-	}
-	return lexInsideAction
-}
-
-// lexNumber scans a number: decimal, octal, hex, float, or imaginary.  This
-// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
-// and "089" - but when it's wrong the input is invalid and the parser (via
-// strconv) will notice.
-func lexNumber(l *lexer) stateFn {
-	if !l.scanNumber() {
-		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
-	}
-	if sign := l.peek(); sign == '+' || sign == '-' {
-		// Complex: 1+2i.  No spaces, must end in 'i'.
-		if !l.scanNumber() || l.input[l.pos-1] != 'i' {
-			return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
-		}
-		l.emit(itemComplex)
-	} else {
-		l.emit(itemNumber)
-	}
-	return lexInsideAction
-}
-
-func (l *lexer) scanNumber() bool {
-	// Optional leading sign.
-	l.accept("+-")
-	// Is it hex?
-	digits := "0123456789"
-	if l.accept("0") && l.accept("xX") {
-		digits = "0123456789abcdefABCDEF"
-	}
-	l.acceptRun(digits)
-	if l.accept(".") {
-		l.acceptRun(digits)
-	}
-	if l.accept("eE") {
-		l.accept("+-")
-		l.acceptRun("0123456789")
-	}
-	// Is it imaginary?
-	l.accept("i")
-	// Next thing mustn't be alphanumeric.
-	if isAlphaNumeric(l.peek()) {
-		l.next()
-		return false
-	}
-	return true
-}
-
-// lexQuote scans a quoted string.
-func lexQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case '\\':
-			if r := l.next(); r != eof && r != '\n' {
-				break
-			}
-			fallthrough
-		case eof, '\n':
-			return l.errorf("unterminated quoted string")
-		case '"':
-			break Loop
-		}
-	}
-	l.emit(itemString)
-	return lexInsideAction
-}
-
-// lexRawQuote scans a raw quoted string.
-func lexRawQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case eof, '\n':
-			return l.errorf("unterminated raw quoted string")
-		case '`':
-			break Loop
-		}
-	}
-	l.emit(itemRawString)
-	return lexInsideAction
-}
-
-// isSpace reports whether r is a space character.
-func isSpace(r int) bool {
-	switch r {
-	case ' ', '\t', '\n', '\r':
-		return true
-	}
-	return false
-}
-
-// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
-func isAlphaNumeric(r int) bool {
-	return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
-}
diff --git a/content/2011/lex/snippets b/content/2011/lex/snippets
deleted file mode 100644
index c00822b..0000000
--- a/content/2011/lex/snippets
+++ /dev/null
@@ -1,21 +0,0 @@
-Evaluation: {{.Title}}
-Constants and functions: {{printf "%g: %#3X" 1.2+2i 123}}
-Control structures {{range $s.Text}} {{.}} {{end}}
-
-// One iteration:
-switch state {
-case state1: 
-	state = action1()
-case state2:
-	state = action2()
-case state3: 
-	state = action3()
-}
-
-// run lexes the input by executing state functions
-// until the state is nil.
-func run() {
-	for state := startState; state != nil; {
-		state = state(lexer)
-	}
-}
diff --git a/content/2012/10things.slide b/content/2012/10things.slide
deleted file mode 100644
index 4ec3f88..0000000
--- a/content/2012/10things.slide
+++ /dev/null
@@ -1,214 +0,0 @@
-10 things you (probably) don't know about Go
-
-Andrew Gerrand
-Gopher
-https://plus.google.com/106356964679457436995
-@enneff
-http://golang.org
-
-* 1. Anonymous structs
-
-- Grouped globals
-
-	var config struct {
-		APIKey      string
-		OAuthConfig oauth.Config
-	}
-
-	config.APIKey = "BADC0C0A"
-
-- Template data
-
-	data := struct {
-		Title string
-		Users []*User
-	}{
-		title,
-		users,
-	}
-	err := tmpl.Execute(w, data)
-
-(Cheaper and safer than using `map[string]interface{}`.)
-
-* 1b. Anonymous structs
-
-- Test tables
-
-	var indexRuneTests = []struct {
-		s    string
-		rune rune
-		out  int
-	}{
-		{"a A x", 'A', 2},
-		{"some_text=some_value", '=', 9},
-		{"☺a", 'a', 3},
-		{"a☻☺b", '☺', 4},
-	}
-
-- Embedded lock
-
-	var hits struct {
-		sync.Mutex
-		n int
-	}
-
-	hits.Lock()
-	hits.n++
-	hits.Unlock()
-
-
-* 2. Nested structs
-
-- Decoding deeply nested JSON data
-
-  {"data": {"children": [
-    {"data": {
-      "title": "The Go homepage",
-      "url": "http://golang.org/"
-    }},
-    ...
-  ]}}
-
-	type Item struct {
-		Title string
-		URL   string
-	}
-
-	type Response struct {
-		Data struct {
-			Children []struct {
-				Data Item
-			}
-		}
-	}
-
-
-* 3. Command-line godoc
-
-  % godoc sync Mutex
-  PACKAGE
-  
-  package sync
-      import "sync"
-  
-  TYPES
-  
-  type Mutex struct {
-      // contains filtered or unexported fields
-  }
-      A Mutex is a mutual exclusion lock. Mutexes can be created as part of
-      other structures; the zero value for a Mutex is an unlocked mutex.
-  
-  func (m *Mutex) Lock()
-      Lock locks m. If the lock is already in use, the calling goroutine
-      blocks until the mutex is available.
-  
-  func (m *Mutex) Unlock()
-      Unlock unlocks m. It is a run-time error if m is not locked on entry to
-      Unlock.
-  
-      A locked Mutex is not associated with a particular goroutine. It is
-      allowed for one goroutine to lock a Mutex and then arrange for another
-      goroutine to unlock it.
-
-
-* 4. godoc -src
-
-  % godoc -src sync Mutex
-  // A Mutex is a mutual exclusion lock.
-  // Mutexes can be created as part of other structures;
-  // the zero value for a Mutex is an unlocked mutex.
-  type Mutex struct {
-      state int32
-      sema  uint32
-  }
-
-Also shows unexported state! Great for digging around.
-
-
-* 5. go get supports custom domains
-
-Yep:
-
-	go get camlistore.org/pkg/netutil
-
-See `go help importpath` for the details.
-
-
-* 6. Mock out the file system
-
-Got a package that works with the file system, but don't want your tests to actually use the disk?
-
-  var fs fileSystem = osFS{}
-  
-  type fileSystem interface {
-  	Open(name string) (file, error)
-  	Stat(name string) (os.FileInfo, error)
-  }
-  
-  type file interface {
-  	io.Closer
-  	io.Reader
-  	io.ReaderAt
-  	io.Seeker
-  	Stat() (os.FileInfo, error)
-  }
-  
-  // osFS implements fileSystem using the local disk.
-  type osFS struct{}
-  
-  func (osFS) Open(name string) (file, error)        { return os.Open(name) }
-  func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) }
-
-Implement your own fake `fileSystem` in and put it in `fs` while testing.
-
-
-* 7. Method expressions
-
-  type T struct {}
-  func (T) Foo(s string) { println(s) }
-
-  var fn func(T, string) = T.Foo
-
-Real example from `os/exec`:
-
-  func (c *Cmd) stdin() (f *os.File, err error)
-  func (c *Cmd) stdout() (f *os.File, err error)
-  func (c *Cmd) stderr() (f *os.File, err error)
-
-	type F func(*Cmd) (*os.File, error)
-	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
-		fd, err := setupFd(c)
-		if err != nil {
-			c.closeDescriptors(c.closeAfterStart)
-			c.closeDescriptors(c.closeAfterWait)
-			return err
-		}
-		c.childFiles = append(c.childFiles, fd)
-	}
-
-
-* 8. Send and receive on the same channel
-
-.play 10things/8.go
-
-
-* 9. Using close to broadcast
-
-.play 10things/9.go /func.waiter/,/endmain/
-
-
-* 9b. Using close to broadcast
-
-.play 10things/9b.go /func.worker/,/endmain/
-
-
-* 10. Nil channel in select
-
-.play 10things/10.go /func.worker/,/endmain/
-
-
-* 11. The gopher's name
-
-.image 10things/gopher.jpg
-
diff --git a/content/2012/10things/10.go b/content/2012/10things/10.go
deleted file mode 100644
index 986cb87..0000000
--- a/content/2012/10things/10.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func worker(i int, ch chan Work, quit chan struct{}) {
-	for {
-		select {
-		case w := <-ch:
-			if quit == nil { // HL
-				w.Refuse(); fmt.Println("worker", i, "refused", w)
-				break
-			}
-			w.Do(); fmt.Println("worker", i, "processed", w)
-		case <-quit:
-			fmt.Println("worker", i, "quitting")
-			quit = nil // HL
-		}
-	}
-}
-
-func main() {
-	ch, quit := make(chan Work), make(chan struct{})
-	go makeWork(ch)
-	for i := 0; i < 4; i++ { go worker(i, ch, quit) }
-	time.Sleep(5 * time.Second)
-	close(quit)
-	time.Sleep(2 * time.Second)
-}
-// endmain OMIT
-
-type Work string
-func (w Work) Do() {
-	time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
-}
-func (w Work) Refuse() {
-	time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond)
-}
-
-func makeWork(ch chan Work) {
-	for i := 0; ; i++ {
-		ch <- Work(fmt.Sprintf("job %x", i))
-	}
-}
diff --git a/content/2012/10things/8.go b/content/2012/10things/8.go
deleted file mode 100644
index 9be9a4d..0000000
--- a/content/2012/10things/8.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-var battle = make(chan string)
-
-func warrior(name string, done chan struct{}) {
-	select {
-	case opponent := <-battle:
-		fmt.Printf("%s beat %s\n", name, opponent)
-	case battle <- name:
-		// I lost :-(
-	}
-	done <- struct{}{}
-}
-
-func main() {
-	done := make(chan struct{})
-	langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"}
-	for _, l := range langs { go warrior(l, done) }
-	for _ = range langs { <-done }
-}
diff --git a/content/2012/10things/9.go b/content/2012/10things/9.go
deleted file mode 100644
index ce6791f..0000000
--- a/content/2012/10things/9.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-	"math/rand"
-)
-
-func waiter(i int, block, done chan struct{}) {
-	time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
-	fmt.Println(i, "waiting...")
-	<-block // HL
-	fmt.Println(i, "done!")
-	done <- struct{}{}
-}
-
-func main() {
-	block, done := make(chan struct{}), make(chan struct{})
-	for i := 0; i < 4; i++ {
-		go waiter(i, block, done)
-	}
-	time.Sleep(5 * time.Second)
-	close(block) // HL
-	for i := 0; i < 4; i++ {
-		<-done
-	}
-}
-// endmain OMIT
diff --git a/content/2012/10things/9b.go b/content/2012/10things/9b.go
deleted file mode 100644
index 577b016..0000000
--- a/content/2012/10things/9b.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func worker(i int, ch chan Work, quit chan struct{}) {
-	var quitting bool
-	for {
-		select {
-		case w := <-ch:
-			if quitting {
-				w.Refuse(); fmt.Println("worker", i, "refused", w)
-				break
-			}
-			w.Do(); fmt.Println("worker", i, "processed", w)
-		case <-quit:
-			fmt.Println("worker", i, "quitting")
-			quitting = true
-		}
-	}
-}
-
-func main() {
-	ch, quit := make(chan Work), make(chan struct{})
-	go makeWork(ch)
-	for i := 0; i < 4; i++ { go worker(i, ch, quit) }
-	time.Sleep(5 * time.Second)
-	close(quit)
-	time.Sleep(2 * time.Second)
-}
-// endmain OMIT
-
-type Work string
-func (w Work) Do() {
-	time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
-}
-func (w Work) Refuse() {
-	time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond)
-}
-
-func makeWork(ch chan Work) {
-	for i := 0; ; i++ {
-		ch <- Work(fmt.Sprintf("job %x", i))
-	}
-}
diff --git a/content/2012/10things/gopher.jpg b/content/2012/10things/gopher.jpg
deleted file mode 100644
index b3d3327..0000000
--- a/content/2012/10things/gopher.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/README b/content/2012/README
deleted file mode 100644
index 8be91a0..0000000
--- a/content/2012/README
+++ /dev/null
@@ -1,5 +0,0 @@
-These slide files are intended to be viewed with the 'present' tool.
-To install 'present':
-
-	go get code.google.com/p/go.talks/present
-
diff --git a/content/2012/chat.slide b/content/2012/chat.slide
deleted file mode 100644
index 727a121..0000000
--- a/content/2012/chat.slide
+++ /dev/null
@@ -1,300 +0,0 @@
-Go: code that grows with grace
-
-Andrew Gerrand
-Google Sydney
-http://andrewgerrand.com
-@enneff
-http://golang.org
-
-* Video
-
-A video of this talk was recorded at Øredev in Malmö, Sweden in November 2012.
-
-.link http://vimeo.com/53221560 Watch the talk on Vimeo
-
-* Go
-
-You may have heard of Go.
-
-It's my favorite language. I think you'll like it, too.
-
-* What is Go?
-
-An open source (BSD licensed) project:
-
-- Language specification,
-- Small runtime (garbage collector, scheduler, etc),
-- Two compilers (`gc` and `gccgo`),
-- 'Batteries included' standard library,
-- Tools (build, fetch, test, document, profile, format),
-- Documentation.
-
-As of September 2012 we have more than 300 contributors.
-
-* Go is about composition
-
-Go is Object Oriented, but not in the usual way.
-
-- no classes (methods may be declared on any type)
-- no subtype inheritance
-- interfaces are satisfied implicitly (structural typing)
-
-The result: simple pieces connected by small interfaces.
-
-* Go is about concurrency
-
-Go provides CSP-like concurrency primitives.
-
-- lightweight threads (goroutines)
-- typed thread-safe communication and synchronization (channels)
-
-The result: comprehensible concurrent code.
-
-* Go is about gophers
-
-.image chat/gophers.jpg
-
-* Core values
-
-Go is about composition, concurrency, and gophers.
-
-Keep that in mind.
-
-* Hello, go
-
-.play chat/support/hello.go
-
-* Hello, net
-
-.play chat/support/hello-net.go
-
-* Interfaces
-
-Hey neato! We just used `Fprintln` to write to a net connection.
-
-That's because a `Fprintln` writes to an `io.Writer`, and `net.Conn` is an `io.Writer`.
-
-.code chat/support/hello-net.go /Fprintln/
-.code chat/support/defs.go /Fprintln/
-.code chat/support/defs.go /type.Writer/,/^}/
-.code chat/support/defs.go /type.Conn/,/^}/
-
-* An echo server
-
-.play chat/support/echo-no-concurrency.go
-
-* A closer look at io.Copy
-
-.code chat/support/echo-no-concurrency.go /Copy/
-.code chat/support/defs.go /Copy/,/func/
-.code chat/support/defs.go /type.Conn/,/^}/
-.code chat/support/defs.go /type.Writer/,/^}/
-.code chat/support/defs.go /type.Reader/,/^}/
-
-* Goroutines
-
-Goroutines are lightweight threads that are managed by the Go runtime. To run a function in a new goroutine, just put `"go"` before the function call.
-
-.play chat/support/goroutines.go
-
-* A concurrent echo server
-
-.play chat/support/echo.go
-
-* "Chat roulette"
-
-In this talk we'll look at a simple program, based on the popular "chat roulette" site.
-
-In short:
-
-- a user connects,
-- another user connects,
-- everything one user types is sent to the other.
-
-* Design
-
-The chat program is similar to the echo program. With echo, we copy a connection's incoming data back to the same connection.
-
-For chat, we must copy the incoming data from one user's connection to another's.
-
-Copying the data is easy. As in real life, the hard part is matching one partner with another.
-
-* Design diagram
-
-.image chat/diagrams.png
-
-* Channels
-
-Goroutines communicate via channels. A channel is a typed conduit that may be synchronous (unbuffered) or asynchronous (buffered).
-
-.play chat/support/chan.go
-
-* Select
-
-A select statement is like a switch, but it selects over channel operations (and chooses exactly one of them).
-
-.play chat/support/select.go
-
-* Modifying echo to create chat
-
-In the accept loop, we replace the call to `io.Copy`:
-
-.code chat/support/echo.go /for {/,/\n	}/
-
-with a call to a new function, `match`:
-
-.code chat/tcp-simple/chat.go /for {/,/\n	}/
-
-* The matcher
-
-The `match` function simultaneously tries to send and receive a connection on a channel.
-
-- If the send succeeds, the connection has been handed off to another goroutine, so the function exits and the goroutine shuts down.
-- If the receive succeeds, a connection has been received from another goroutine. The current goroutine then has two connections, so it starts a chat session between them.
-
-.code chat/tcp-simple/chat.go /var.partner/,/^}/
-
-* The conversation
-
-The chat function sends a greeting to each connection and then copies data from one to the other, and vice versa.
-
-Notice that it launches another goroutine so that the copy operations may happen concurrently.
-
-.code chat/tcp-simple/chat.go /func.chat/,/^}/
-
-* Demo
-
-* Error handling
-
-It's important to clean up when the conversation is over. To do this we send the error value from each `io.Copy` call to a channel, log any non-nil errors, and close both connections.
-
-.code chat/tcp/chat.go /func.chat/,/^}/
-.code chat/tcp/chat.go /func.cp/,/^}/
-
-* Demo
-
-* Taking it to the web 
-
-"Cute program," you say, "But who wants to chat over a raw TCP connection?"
-
-Good point. Let's modernize it by turning it a web application.
-
-Instead of TCP sockets, we'll use websockets.
-
-We'll serve the user interface with Go's standard `net/http` package, and websocket support is provided by the `websocket` package from the `go.net` sub-repository,
-
-* Hello, web
-
-.play chat/support/hello-web.go
-
-* Hello, WebSocket
-
-.code chat/support/websocket.js
-.play chat/support/websocket.go
-
-* Using the http and websocket packages
-
-.code chat/http/chat.go /package/,/^}/
-
-* Serving the HTML and JavaScript
-
-.code chat/http/html.go /import/
-.code chat/http/html.go /func/,/<script>/
-.code chat/http/html.go /websocket.=/,/onClose/
-.code chat/http/html.go /<\/html>/,$
-
-* Adding a socket type
-
-We can't just use a `websocket.Conn` instead of the `net.Conn`, because a `websocket.Conn` is held open by its handler function. Here we use a channel to keep the handler running until the socket's `Close` method is called.
-
-.code chat/http-noembed/chat.go /type.socket/,/END/
-
-* Struct embedding
-
-Go supports a kind of "mix-in" functionality with a feature known as "struct embedding". The embedding struct delegates calls to the embedded type's methods.
-
-.play chat/support/embed.go /type/,$
-
-* Embedding the websocket connection
-
-By embedding the `*websocket.Conn` as an `io.ReadWriter`, we can drop the explicit `socket` `Read` and `Write` methods. 
-
-.code chat/http/chat.go /type.socket/,/END/
-
-* Demo
-
-* Relieving loneliness
-
-What if you connect, but there's noone there?
-
-Wouldn't it be nice if we could synthesize a chat partner?
-
-Let's do it.
-
-* Generating text with markov chains
-
-.code chat/support/markov.txt
-
-* Generating text with markov chains
-
-Fortunately, the Go docs include a markov chain implementation:
-
-.link http://golang.org/doc/codewalk/markov
-
-We'll use a version that has been modified to be safe for concurrent use.
-
-.code chat/markov/markov.go /Chain/,/{/
-.code chat/markov/markov.go /Write/,/{/
-.code chat/markov/markov.go /Generate/,/{/
-
-* Feeding the chain
-
-We will use all text that enters the system to build the markov chains.
-To do this we split the socket's `ReadWriter` into a `Reader` and a `Writer`,
-and feed all incoming data to the `Chain` instance.
-
-.code chat/markov/chat.go /type.socket/,/^}/
-.code chat/markov/chat.go /var.chain/,/^}/
-
-* The markov bot
-
-.code chat/markov/chat.go /\/\/.Bot/,/^}/
-.code chat/markov/chat.go /type.bot/,/^}/
-.code chat/markov/chat.go /func.+bot.+Write/,/^}/
-.code chat/markov/chat.go /func.+bot.+speak/,/^}/
-
-* Integrating the markov bot
-
-The bot should jump in if a real partner doesn't join.
-To do this, we add a case to the select that triggers after 5 seconds, starting a chat between the user's socket and a bot.
-
-.code chat/markov/chat.go /func.match/,/^}/
-
-The `chat` function remains untouched.
-
-* Demo
-
-* One more thing
-
-* TCP and HTTP at the same time
-
-.code chat/both/chat.go /func main/,/^}/
-.code chat/both/chat.go /func netListen/,/^}/
-
-* Demo
-
-* Discussion
-
-* Further reading
-
-All about Go:
-
-.link http://golang.org
-
-The slides for this talk:
-
-.link http://talks.golang.org/2012/chat.slide
-
-"Go Concurrency Patterns" by Rob Pike:
-
-.link http://golang.org/s/concurrency-patterns
diff --git a/content/2012/chat/both/chat.go b/content/2012/chat/both/chat.go
deleted file mode 100644
index d712b91..0000000
--- a/content/2012/chat/both/chat.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"net/http"
-	"time"
-
-	"golang.org/x/net/websocket"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	go netListen() // HL
-	http.HandleFunc("/", rootHandler)
-	http.Handle("/socket", websocket.Handler(socketHandler))
-	err := http.ListenAndServe(listenAddr, nil)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-func netListen() {
-	l, err := net.Listen("tcp", "localhost:4001")
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		go match(c)
-	}
-}
-
-type socket struct {
-	io.Reader
-	io.Writer
-	done chan bool
-}
-
-func (s socket) Close() error {
-	s.done <- true
-	return nil
-}
-
-var chain = NewChain(2) // 2-word prefixes
-
-func socketHandler(ws *websocket.Conn) {
-	r, w := io.Pipe()
-	go func() {
-		_, err := io.Copy(io.MultiWriter(w, chain), ws)
-		w.CloseWithError(err)
-	}()
-	s := socket{r, ws, make(chan bool)}
-	go match(s)
-	<-s.done
-}
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	case <-time.After(5 * time.Second):
-		chat(Bot(), c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	errc := make(chan error, 1)
-	go cp(a, b, errc)
-	go cp(b, a, errc)
-	if err := <-errc; err != nil {
-		log.Println(err)
-	}
-	a.Close()
-	b.Close()
-}
-
-func cp(w io.Writer, r io.Reader, errc chan<- error) {
-	_, err := io.Copy(w, r)
-	errc <- err
-}
-
-// Bot returns an io.ReadWriteCloser that responds to
-// each incoming write with a generated sentence.
-func Bot() io.ReadWriteCloser {
-	r, out := io.Pipe() // for outgoing data
-	return bot{r, out}
-}
-
-type bot struct {
-	io.ReadCloser
-	out io.Writer
-}
-
-func (b bot) Write(buf []byte) (int, error) {
-	go b.speak()
-	return len(buf), nil
-}
-
-func (b bot) speak() {
-	time.Sleep(time.Second)
-	msg := chain.Generate(10) // at most 10 words
-	b.out.Write([]byte(msg))
-}
diff --git a/content/2012/chat/both/html.go b/content/2012/chat/both/html.go
deleted file mode 100644
index 090e80d..0000000
--- a/content/2012/chat/both/html.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "html/template"
-import "net/http"
-
-func rootHandler(w http.ResponseWriter, r *http.Request) {
-	rootTemplate.Execute(w, listenAddr)
-}
-
-var rootTemplate = template.Must(template.New("root").Parse(`
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<script>
-
-var input, output, websocket;
-
-function showMessage(m) {
-	var p = document.createElement("p");
-	p.innerHTML = m;
-	output.appendChild(p);
-}
-
-function onMessage(e) {
-	showMessage(e.data);
-}
-
-function onClose() {
-	showMessage("Connection closed.");
-}
-
-function sendMessage() {
-	var m = input.value;
-	input.value = "";
-	websocket.send(m + "\n");
-	showMessage(m);
-}
-
-function onKey(e) {
-	if (e.keyCode == 13) {
-		sendMessage();
-	}
-}
-
-function init() {
-	input = document.getElementById("input");
-	input.addEventListener("keyup", onKey, false);
-
-	output = document.getElementById("output");
-
-	websocket = new WebSocket("ws://{{.}}/socket");
-	websocket.onmessage = onMessage;
-	websocket.onclose = onClose;
-}
-
-window.addEventListener("load", init, false);
-
-</script>
-</head>
-<body>
-<input id="input" type="text">
-<div id="output"></div>
-</body>
-</html>
-`))
diff --git a/content/2012/chat/both/markov.go b/content/2012/chat/both/markov.go
deleted file mode 100644
index 97dfe41..0000000
--- a/content/2012/chat/both/markov.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-// This Markov chain code is taken from the "Generating arbitrary text"
-// codewalk: http://golang.org/doc/codewalk/markov/
-
-import (
-	"bytes"
-	"fmt"
-	"math/rand"
-	"strings"
-	"sync"
-)
-
-// Prefix is a Markov chain prefix of one or more words.
-type Prefix []string
-
-// String returns the Prefix as a string (for use as a map key).
-func (p Prefix) String() string {
-	return strings.Join(p, " ")
-}
-
-// Shift removes the first word from the Prefix and appends the given word.
-func (p Prefix) Shift(word string) {
-	copy(p, p[1:])
-	p[len(p)-1] = word
-}
-
-// Chain contains a map ("chain") of prefixes to a list of suffixes.
-// A prefix is a string of prefixLen words joined with spaces.
-// A suffix is a single word. A prefix can have multiple suffixes.
-type Chain struct {
-	chain     map[string][]string
-	prefixLen int
-	mu        sync.Mutex
-}
-
-// NewChain returns a new Chain with prefixes of prefixLen words.
-func NewChain(prefixLen int) *Chain {
-	return &Chain{
-		chain:     make(map[string][]string),
-		prefixLen: prefixLen,
-	}
-}
-
-// Write parses the bytes into prefixes and suffixes that are stored in Chain.
-func (c *Chain) Write(b []byte) (int, error) {
-	br := bytes.NewReader(b)
-	p := make(Prefix, c.prefixLen)
-	for {
-		var s string
-		if _, err := fmt.Fscan(br, &s); err != nil {
-			break
-		}
-		key := p.String()
-		c.mu.Lock()
-		c.chain[key] = append(c.chain[key], s)
-		c.mu.Unlock()
-		p.Shift(s)
-	}
-	return len(b), nil
-}
-
-// Generate returns a string of at most n words generated from Chain.
-func (c *Chain) Generate(n int) string {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	p := make(Prefix, c.prefixLen)
-	var words []string
-	for i := 0; i < n; i++ {
-		choices := c.chain[p.String()]
-		if len(choices) == 0 {
-			break
-		}
-		next := choices[rand.Intn(len(choices))]
-		words = append(words, next)
-		p.Shift(next)
-	}
-	return strings.Join(words, " ")
-}
diff --git a/content/2012/chat/diagrams.png b/content/2012/chat/diagrams.png
deleted file mode 100644
index 8c8ceac..0000000
--- a/content/2012/chat/diagrams.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/chat/gophers.jpg b/content/2012/chat/gophers.jpg
deleted file mode 100644
index 2158dee..0000000
--- a/content/2012/chat/gophers.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/chat/http-noembed/chat.go b/content/2012/chat/http-noembed/chat.go
deleted file mode 100644
index 095934a..0000000
--- a/content/2012/chat/http-noembed/chat.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net/http"
-
-	"golang.org/x/net/websocket"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	http.HandleFunc("/", rootHandler)
-	http.Handle("/socket", websocket.Handler(socketHandler))
-	err := http.ListenAndServe(listenAddr, nil)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-type socket struct {
-	conn *websocket.Conn
-	done chan bool
-}
-
-func (s socket) Read(b []byte) (int, error)  { return s.conn.Read(b) }
-func (s socket) Write(b []byte) (int, error) { return s.conn.Write(b) }
-
-func (s socket) Close() error {
-	s.done <- true
-	return nil
-}
-
-func socketHandler(ws *websocket.Conn) {
-	s := socket{conn: ws, done: make(chan bool)}
-	go match(s)
-	<-s.done
-}
-
-// END OMIT
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	errc := make(chan error, 1)
-	go cp(a, b, errc)
-	go cp(b, a, errc)
-	if err := <-errc; err != nil {
-		log.Println(err)
-	}
-	a.Close()
-	b.Close()
-}
-
-func cp(w io.Writer, r io.Reader, errc chan<- error) {
-	_, err := io.Copy(w, r)
-	errc <- err
-}
diff --git a/content/2012/chat/http-noembed/html.go b/content/2012/chat/http-noembed/html.go
deleted file mode 100644
index b4e1fdc..0000000
--- a/content/2012/chat/http-noembed/html.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "html/template"
-import "net/http"
-
-func rootHandler(w http.ResponseWriter, r *http.Request) {
-	rootTemplate.Execute(w, listenAddr)
-}
-
-var rootTemplate = template.Must(template.New("root").Parse(`
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<script>
-
-var input, output, websocket;
-
-function showMessage(m) {
-	var p = document.createElement("p");
-	p.innerHTML = m;
-	output.appendChild(p);
-}
-
-function onMessage(e) {
-	showMessage(e.data);
-}
-
-function onClose() {
-	showMessage("Connection closed.");
-}
-
-function sendMessage() {
-	var m = input.value;
-	input.value = "";
-	websocket.send(m);
-	showMessage(m);
-}
-
-function onKey(e) {
-	if (e.keyCode == 13) {
-		sendMessage();
-	}
-}
-
-function init() {
-	input = document.getElementById("input");
-	input.addEventListener("keyup", onKey, false);
-
-	output = document.getElementById("output");
-
-	websocket = new WebSocket("ws://{{.}}/socket");
-	websocket.onmessage = onMessage;
-	websocket.onclose = onClose;
-}
-
-window.addEventListener("load", init, false);
-
-</script>
-</head>
-<body>
-<input id="input" type="text">
-<div id="output"></div>
-</body>
-</html>
-`))
diff --git a/content/2012/chat/http/chat.go b/content/2012/chat/http/chat.go
deleted file mode 100644
index 031a518..0000000
--- a/content/2012/chat/http/chat.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net/http"
-
-	"golang.org/x/net/websocket"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	http.HandleFunc("/", rootHandler)
-	http.Handle("/socket", websocket.Handler(socketHandler))
-	err := http.ListenAndServe(listenAddr, nil)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-type socket struct {
-	io.ReadWriter // HL
-	done          chan bool
-}
-
-func (s socket) Close() error {
-	s.done <- true
-	return nil
-}
-
-func socketHandler(ws *websocket.Conn) {
-	s := socket{ws, make(chan bool)} // HL
-	go match(s)
-	<-s.done
-}
-
-// END OMIT
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	errc := make(chan error, 1)
-	go cp(a, b, errc)
-	go cp(b, a, errc)
-	if err := <-errc; err != nil {
-		log.Println(err)
-	}
-	a.Close()
-	b.Close()
-}
-
-func cp(w io.Writer, r io.Reader, errc chan<- error) {
-	_, err := io.Copy(w, r)
-	errc <- err
-}
diff --git a/content/2012/chat/http/html.go b/content/2012/chat/http/html.go
deleted file mode 100644
index b4e1fdc..0000000
--- a/content/2012/chat/http/html.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "html/template"
-import "net/http"
-
-func rootHandler(w http.ResponseWriter, r *http.Request) {
-	rootTemplate.Execute(w, listenAddr)
-}
-
-var rootTemplate = template.Must(template.New("root").Parse(`
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<script>
-
-var input, output, websocket;
-
-function showMessage(m) {
-	var p = document.createElement("p");
-	p.innerHTML = m;
-	output.appendChild(p);
-}
-
-function onMessage(e) {
-	showMessage(e.data);
-}
-
-function onClose() {
-	showMessage("Connection closed.");
-}
-
-function sendMessage() {
-	var m = input.value;
-	input.value = "";
-	websocket.send(m);
-	showMessage(m);
-}
-
-function onKey(e) {
-	if (e.keyCode == 13) {
-		sendMessage();
-	}
-}
-
-function init() {
-	input = document.getElementById("input");
-	input.addEventListener("keyup", onKey, false);
-
-	output = document.getElementById("output");
-
-	websocket = new WebSocket("ws://{{.}}/socket");
-	websocket.onmessage = onMessage;
-	websocket.onclose = onClose;
-}
-
-window.addEventListener("load", init, false);
-
-</script>
-</head>
-<body>
-<input id="input" type="text">
-<div id="output"></div>
-</body>
-</html>
-`))
diff --git a/content/2012/chat/markov/chat.go b/content/2012/chat/markov/chat.go
deleted file mode 100644
index 5654f3c..0000000
--- a/content/2012/chat/markov/chat.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net/http"
-	"time"
-
-	"golang.org/x/net/websocket"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	http.HandleFunc("/", rootHandler)
-	http.Handle("/socket", websocket.Handler(socketHandler))
-	err := http.ListenAndServe(listenAddr, nil)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-type socket struct {
-	io.Reader
-	io.Writer
-	done chan bool
-}
-
-func (s socket) Close() error {
-	s.done <- true
-	return nil
-}
-
-var chain = NewChain(2) // 2-word prefixes
-
-func socketHandler(ws *websocket.Conn) {
-	r, w := io.Pipe() // HL
-	go func() {       // HL
-		_, err := io.Copy(io.MultiWriter(w, chain), ws) // HL
-		w.CloseWithError(err)                           // HL
-	}() // HL
-	s := socket{r, ws, make(chan bool)}
-	go match(s)
-	<-s.done
-}
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	case <-time.After(5 * time.Second): // HL
-		chat(Bot(), c) // HL
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	errc := make(chan error, 1)
-	go cp(a, b, errc)
-	go cp(b, a, errc)
-	if err := <-errc; err != nil {
-		log.Println(err)
-	}
-	a.Close()
-	b.Close()
-}
-
-func cp(w io.Writer, r io.Reader, errc chan<- error) {
-	_, err := io.Copy(w, r)
-	errc <- err
-}
-
-// Bot returns an io.ReadWriteCloser that responds to
-// each incoming write with a generated sentence.
-func Bot() io.ReadWriteCloser {
-	r, out := io.Pipe() // for outgoing data
-	return bot{r, out}
-}
-
-type bot struct {
-	io.ReadCloser
-	out io.Writer
-}
-
-func (b bot) Write(buf []byte) (int, error) {
-	go b.speak()
-	return len(buf), nil
-}
-
-func (b bot) speak() {
-	time.Sleep(time.Second)
-	msg := chain.Generate(10) // at most 10 words
-	b.out.Write([]byte(msg))
-}
diff --git a/content/2012/chat/markov/html.go b/content/2012/chat/markov/html.go
deleted file mode 100644
index b4e1fdc..0000000
--- a/content/2012/chat/markov/html.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "html/template"
-import "net/http"
-
-func rootHandler(w http.ResponseWriter, r *http.Request) {
-	rootTemplate.Execute(w, listenAddr)
-}
-
-var rootTemplate = template.Must(template.New("root").Parse(`
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<script>
-
-var input, output, websocket;
-
-function showMessage(m) {
-	var p = document.createElement("p");
-	p.innerHTML = m;
-	output.appendChild(p);
-}
-
-function onMessage(e) {
-	showMessage(e.data);
-}
-
-function onClose() {
-	showMessage("Connection closed.");
-}
-
-function sendMessage() {
-	var m = input.value;
-	input.value = "";
-	websocket.send(m);
-	showMessage(m);
-}
-
-function onKey(e) {
-	if (e.keyCode == 13) {
-		sendMessage();
-	}
-}
-
-function init() {
-	input = document.getElementById("input");
-	input.addEventListener("keyup", onKey, false);
-
-	output = document.getElementById("output");
-
-	websocket = new WebSocket("ws://{{.}}/socket");
-	websocket.onmessage = onMessage;
-	websocket.onclose = onClose;
-}
-
-window.addEventListener("load", init, false);
-
-</script>
-</head>
-<body>
-<input id="input" type="text">
-<div id="output"></div>
-</body>
-</html>
-`))
diff --git a/content/2012/chat/markov/markov.go b/content/2012/chat/markov/markov.go
deleted file mode 100644
index 97dfe41..0000000
--- a/content/2012/chat/markov/markov.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-// This Markov chain code is taken from the "Generating arbitrary text"
-// codewalk: http://golang.org/doc/codewalk/markov/
-
-import (
-	"bytes"
-	"fmt"
-	"math/rand"
-	"strings"
-	"sync"
-)
-
-// Prefix is a Markov chain prefix of one or more words.
-type Prefix []string
-
-// String returns the Prefix as a string (for use as a map key).
-func (p Prefix) String() string {
-	return strings.Join(p, " ")
-}
-
-// Shift removes the first word from the Prefix and appends the given word.
-func (p Prefix) Shift(word string) {
-	copy(p, p[1:])
-	p[len(p)-1] = word
-}
-
-// Chain contains a map ("chain") of prefixes to a list of suffixes.
-// A prefix is a string of prefixLen words joined with spaces.
-// A suffix is a single word. A prefix can have multiple suffixes.
-type Chain struct {
-	chain     map[string][]string
-	prefixLen int
-	mu        sync.Mutex
-}
-
-// NewChain returns a new Chain with prefixes of prefixLen words.
-func NewChain(prefixLen int) *Chain {
-	return &Chain{
-		chain:     make(map[string][]string),
-		prefixLen: prefixLen,
-	}
-}
-
-// Write parses the bytes into prefixes and suffixes that are stored in Chain.
-func (c *Chain) Write(b []byte) (int, error) {
-	br := bytes.NewReader(b)
-	p := make(Prefix, c.prefixLen)
-	for {
-		var s string
-		if _, err := fmt.Fscan(br, &s); err != nil {
-			break
-		}
-		key := p.String()
-		c.mu.Lock()
-		c.chain[key] = append(c.chain[key], s)
-		c.mu.Unlock()
-		p.Shift(s)
-	}
-	return len(b), nil
-}
-
-// Generate returns a string of at most n words generated from Chain.
-func (c *Chain) Generate(n int) string {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	p := make(Prefix, c.prefixLen)
-	var words []string
-	for i := 0; i < n; i++ {
-		choices := c.chain[p.String()]
-		if len(choices) == 0 {
-			break
-		}
-		next := choices[rand.Intn(len(choices))]
-		words = append(words, next)
-		p.Shift(next)
-	}
-	return strings.Join(words, " ")
-}
diff --git a/content/2012/chat/support/chan.go b/content/2012/chat/support/chan.go
deleted file mode 100644
index fa27d24..0000000
--- a/content/2012/chat/support/chan.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-func main() {
-	ch := make(chan int)
-	go fibs(ch)
-	for i := 0; i < 20; i++ {
-		fmt.Println(<-ch)
-	}
-}
-
-func fibs(ch chan int) {
-	i, j := 0, 1
-	for {
-		ch <- j
-		i, j = j, i+j
-	}
-}
diff --git a/content/2012/chat/support/defs.go b/content/2012/chat/support/defs.go
deleted file mode 100644
index 1da4ee4..0000000
--- a/content/2012/chat/support/defs.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
-
-// Writer is the interface that wraps the basic Write method.
-//
-// Write writes len(p) bytes from p to the underlying data stream. It
-// returns the number of bytes written from p (0 <= n <= len(p)) and any
-// error encountered that caused the write to stop early. Write must return
-// a non-nil error if it returns n < len(p).
-type Writer interface {
-	Write(p []byte) (n int, err error)
-}
-
-// Reader is the interface that wraps the basic Read method.
-//
-// Read reads up to len(p) bytes into p.  It returns the number of bytes
-// read (0 <= n <= len(p)) and any error encountered.  Even if Read
-// returns n < len(p), it may use all of p as scratch space during the call.
-// If some data is available but not len(p) bytes, Read conventionally
-// returns what is available instead of waiting for more.
-//
-// When Read encounters an error or end-of-file condition after
-// successfully reading n > 0 bytes, it returns the number of
-// bytes read.  It may return the (non-nil) error from the same call
-// or return the error (and n == 0) from a subsequent call.
-// An instance of this general case is that a Reader returning
-// a non-zero number of bytes at the end of the input stream may
-// return either err == EOF or err == nil.  The next Read should
-// return 0, EOF regardless.
-//
-// Callers should always process the n > 0 bytes returned before
-// considering the error err.  Doing so correctly handles I/O errors
-// that happen after reading some bytes and also both of the
-// allowed EOF behaviors.
-type Reader interface {
-	Read(p []byte) (n int, err error)
-}
-
-// ReadWriter is the interface that groups the basic Read and Write methods.
-type ReadWriter interface {
-	Reader
-	// contains filtered or unexported methods
-}
-
-// ReadCloser is the interface that groups the basic Read and Close methods.
-type ReadCloser interface {
-	Reader
-	// contains filtered or unexported methods
-}
-
-// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods.
-type ReadWriteCloser interface {
-	Reader
-	// contains filtered or unexported methods
-}
-
-// ReadSeeker is the interface that groups the basic Read and Seek methods.
-type ReadSeeker interface {
-	Reader
-	// contains filtered or unexported methods
-}
-
-// ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods.
-type ReadWriteSeeker interface {
-	Reader
-	// contains filtered or unexported methods
-}
-
-type Conn interface {
-	Read(b []byte) (n int, err error)
-	Write(b []byte) (n int, err error)
-	Close() error
-	// ... some additional methods omitted ...
-}
-
-// Copy copies from src to dst until either EOF is reached
-// on src or an error occurs.  It returns the number of bytes
-// copied and the first error encountered while copying, if any.
-func Copy(dst Writer, src Reader) (written int64, err error)
diff --git a/content/2012/chat/support/echo-no-concurrency.go b/content/2012/chat/support/echo-no-concurrency.go
deleted file mode 100644
index a6aa2d7..0000000
--- a/content/2012/chat/support/echo-no-concurrency.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"io"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		io.Copy(c, c)
-	}
-}
diff --git a/content/2012/chat/support/echo.go b/content/2012/chat/support/echo.go
deleted file mode 100644
index 37dce1e..0000000
--- a/content/2012/chat/support/echo.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"io"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		go io.Copy(c, c)
-	}
-}
diff --git a/content/2012/chat/support/embed.go b/content/2012/chat/support/embed.go
deleted file mode 100644
index fdecb21..0000000
--- a/content/2012/chat/support/embed.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-type A struct{}
-
-func (A) Hello() {
-	fmt.Println("Hello!")
-}
-
-type B struct {
-	A
-}
-
-// func (b B) Hello() { b.A.Hello() } // (implicitly!)
-
-func main() {
-	var b B
-	b.Hello()
-}
diff --git a/content/2012/chat/support/goroutines.go b/content/2012/chat/support/goroutines.go
deleted file mode 100644
index b86d97b..0000000
--- a/content/2012/chat/support/goroutines.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	go say("let's go!", 3)
-	go say("ho!", 2)
-	go say("hey!", 1)
-	time.Sleep(4 * time.Second)
-}
-
-func say(text string, secs int) {
-	time.Sleep(time.Duration(secs) * time.Second)
-	fmt.Println(text)
-}
diff --git a/content/2012/chat/support/hello-net.go b/content/2012/chat/support/hello-net.go
deleted file mode 100644
index 298e5c7..0000000
--- a/content/2012/chat/support/hello-net.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		fmt.Fprintln(c, "Hello!")
-		c.Close()
-	}
-}
diff --git a/content/2012/chat/support/hello-web.go b/content/2012/chat/support/hello-web.go
deleted file mode 100644
index 020fb48..0000000
--- a/content/2012/chat/support/hello-web.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	http.HandleFunc("/", handler)
-	err := http.ListenAndServe(listenAddr, nil)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-func handler(w http.ResponseWriter, r *http.Request) {
-	fmt.Fprint(w, "Hello, web")
-}
diff --git a/content/2012/chat/support/hello.go b/content/2012/chat/support/hello.go
deleted file mode 100644
index 0757c53..0000000
--- a/content/2012/chat/support/hello.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hello, go")
-}
diff --git a/content/2012/chat/support/markov.txt b/content/2012/chat/support/markov.txt
deleted file mode 100644
index 8d84c04..0000000
--- a/content/2012/chat/support/markov.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Source
-"I am not a number! I am a free man!"
-
-Prefix           Suffix 
-"" ""            "I"
-"" "I"           "am"
-"I" "am"         "a"
-"I" "am"         "not"
-"a" "free"       "man!"
-"am" "a"         "free"
-"am" "not"       "a"
-"a" "number!"    "I"
-"number!" "I"    "am"
-"not" "a"        "number!"
-
-Generated sentences beginning with the prefix "I am"
-"I am a free man!"
-"I am not a number! I am a free man!"
-"I am not a number! I am not a number! I am a free man!"
-"I am not a number! I am not a number! I am not a number! I am a free man!"
-
diff --git a/content/2012/chat/support/select.go b/content/2012/chat/support/select.go
deleted file mode 100644
index b236f41..0000000
--- a/content/2012/chat/support/select.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	ticker := time.NewTicker(time.Millisecond * 250)
-	boom := time.After(time.Second * 1)
-	for {
-		select {
-		case <-ticker.C:
-			fmt.Println("tick")
-		case <-boom:
-			fmt.Println("boom!")
-			return
-		}
-	}
-}
diff --git a/content/2012/chat/support/websocket.go b/content/2012/chat/support/websocket.go
deleted file mode 100644
index 5b056ca..0000000
--- a/content/2012/chat/support/websocket.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"golang.org/x/net/websocket"
-	"net/http"
-)
-
-func main() {
-	http.Handle("/", websocket.Handler(handler))
-	http.ListenAndServe("localhost:4000", nil)
-}
-
-func handler(c *websocket.Conn) {
-	var s string
-	fmt.Fscan(c, &s)
-	fmt.Println("Received:", s)
-	fmt.Fprint(c, "How do you do?")
-}
diff --git a/content/2012/chat/support/websocket.js b/content/2012/chat/support/websocket.js
deleted file mode 100644
index f9809d6..0000000
--- a/content/2012/chat/support/websocket.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var sock = new WebSocket("ws://localhost:4000/");
-sock.onmessage = function(m) { console.log("Received:", m.data); }
-sock.send("Hello!\n")
diff --git a/content/2012/chat/tcp-simple/chat.go b/content/2012/chat/tcp-simple/chat.go
deleted file mode 100644
index 9333691..0000000
--- a/content/2012/chat/tcp-simple/chat.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		go match(c) // HL
-	}
-}
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	go io.Copy(a, b)
-	io.Copy(b, a)
-}
diff --git a/content/2012/chat/tcp/chat.go b/content/2012/chat/tcp/chat.go
deleted file mode 100644
index c07fa27..0000000
--- a/content/2012/chat/tcp/chat.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		go match(c)
-	}
-}
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	errc := make(chan error, 1)
-	go cp(a, b, errc)
-	go cp(b, a, errc)
-	if err := <-errc; err != nil {
-		log.Println(err)
-	}
-	a.Close()
-	b.Close()
-}
-
-func cp(w io.Writer, r io.Reader, errc chan<- error) {
-	_, err := io.Copy(w, r)
-	errc <- err
-}
diff --git a/content/2012/concurrency.slide b/content/2012/concurrency.slide
deleted file mode 100644
index 2d2f3d1..0000000
--- a/content/2012/concurrency.slide
+++ /dev/null
@@ -1,467 +0,0 @@
-Go Concurrency Patterns
-
-Rob Pike
-Google
-http://golang.org/s/plusrob
-@rob_pike
-http://golang.org
-
-* Video
-
-This talk was presented at Google I/O in June 2012.
-
-.link http://www.youtube.com/watch?v=f6kdp27TYZs Watch the talk on YouTube
-
-* Introduction
-
-* Concurrency features in Go
-
-People seemed fascinated by the concurrency features of Go when the language was first announced.
-
-Questions:
-
-- Why is concurrency supported?
-- What is concurrency, anyway?
-- Where does the idea come from?
-- What is it good for?
-- How do I use it?
-
-* Why?
-
-Look around you. What do you see?
-
-Do you see a single-stepping world doing one thing at a time?
-
-Or do you see a complex world of interacting, independently behaving pieces?
-
-That's why. Sequential processing on its own does not model the world's behavior.
-
-* What is concurrency?
-
-Concurrency is the composition of independently executing computations.
-
-Concurrency is a way to structure software, particularly as a way to write clean code that interacts well with the real world.
-
-It is not parallelism.
-
-* Concurrency is not parallelism
-
-Concurrency is not parallelism, although it enables parallelism.
-
-If you have only one processor, your program can still be concurrent  but it cannot be parallel.
-
-On the other hand, a well-written concurrent program might run efficiently in parallel on a multiprocessor. That property could be important...
-
-For more on that distinction, see the link below. Too much to discuss here.
-
-.link http://golang.org/s/concurrency-is-not-parallelism
-
-* A model for software construction
-
-Easy to understand.
-
-Easy to use.
-
-Easy to reason about.
-
-You don't need to be an expert!
-
-(Much nicer than dealing with the minutiae of parallelism (threads, semaphores, locks, barriers, etc.))
-
-* History
-
-To many, the concurrency features of Go seemed new.
-
-But they are rooted in a long history, reaching back to Hoare's CSP in 1978 and even Dijkstra's guarded commands (1975).
-
-Languages with similar features:
-
-- Occam (May, 1983)
-- Erlang (Armstrong, 1986)
-- Newsqueak (Pike, 1988)
-- Concurrent ML (Reppy, 1993)
-- Alef (Winterbottom, 1995)
-- Limbo (Dorward, Pike, Winterbottom, 1996).
-
-* Distinction
-
-Go is the latest on the Newsqueak-Alef-Limbo branch, distinguished by first-class channels.
-
-Erlang is closer to the original CSP, where you communicate to a process by name rather than over a channel.
-
-The models are equivalent but express things differently.
-
-Rough analogy: writing to a file by name (process, Erlang) vs. writing to a file descriptor (channel, Go).
-
-* Basic Examples
-
-* A boring function
-
-We need an example to show the interesting properties of the concurrency primitives.
-
-To avoid distraction, we make it a boring example.
-
-.play concurrency/support/boring.go /START/,/STOP.*/
-
-* Slightly less boring
-
-Make the intervals between messages unpredictable (still under a second).
-
-.play concurrency/support/lessboring.go /START/,/STOP/
-
-* Running it
-
-The boring function runs on forever, like a boring party guest.
-
-.play concurrency/support/lessboring.go /^func.main/,$
-
-* Ignoring it
-
-The go statement runs the function as usual, but doesn't make the caller wait.
-
-It launches a goroutine.
-
-The functionality is analogous to the & on the end of a shell command.
-
-.play concurrency/support/goboring.go 1,/^}/
-
-* Ignoring it a little less
-
-When main returns, the program exits and takes the boring function down with it.
-
-We can hang around a little, and on the way show that both main and the launched goroutine are running.
-
-.play concurrency/support/waitgoboring.go /func.main/,/^}/
-
-* Goroutines
-
-What is a goroutine? It's an independently executing function, launched by a go statement.
-
-It has its own call stack, which grows and shrinks as required.
-
-It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines.
-
-It's not a thread.
-
-There might be only one thread in a program with thousands of goroutines.
-
-Instead, goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running.
-
-But if you think of it as a very cheap thread, you won't be far off.
-
-* Communication
-
-Our boring examples cheated: the main function couldn't see the output from the other goroutine.
-
-It was just printed to the screen, where we pretended we saw a conversation.
-
-Real conversations require communication.
-
-* Channels
-
-A channel in Go provides a connection between two goroutines, allowing them to communicate.
-
-.code concurrency/support/helpers.go /START1/,/STOP1/
-.code concurrency/support/helpers.go /START2/,/STOP2/
-.code concurrency/support/helpers.go /START3/,/STOP3/
-
-* Using channels
-
-A channel connects the main and boring goroutines so they can communicate.
-
-.play concurrency/support/changoboring.go /START1/,/STOP1/
-.code concurrency/support/changoboring.go /START2/,/STOP2/
-
-* Synchronization
-
-When the main function executes <–c, it will wait for a value to be sent.
-
-Similarly, when the boring function executes c <– value, it waits for a receiver to be ready.
-
-A sender and receiver must both be ready to play their part in the communication. Otherwise we wait until they are.
-
-Thus channels both communicate and synchronize.
-
-* An aside about buffered channels
-
-Note for experts: Go channels can also be created with a buffer.
-
-Buffering removes synchronization.
-
-Buffering makes them more like Erlang's mailboxes.
-
-Buffered channels can be important for some problems but they are more subtle to reason about.
-
-We won't need them today.
-
-* The Go approach
-
-Don't communicate by sharing memory, share memory by communicating.
-
-* "Patterns"
-
-* Generator: function that returns a channel
-
-Channels are first-class values, just like strings or integers.
-
-.play concurrency/support/generatorboring.go /START1/,/STOP1/
-.code concurrency/support/generatorboring.go /START2/,/STOP2/
-
-* Channels as a handle on a service
-
-Our boring function returns a channel that lets us communicate with the boring service it provides.
-
-We can have more instances of the service.
-
-.play concurrency/support/generator2boring.go /START1/,/STOP1/
-
-* Multiplexing
-
-These programs make Joe and Ann count in lockstep.
-We can instead use a fan-in function to let whosoever is ready talk.
-
-.code concurrency/support/faninboring.go /START3/,/STOP3/
-.play concurrency/support/faninboring.go /START1/,/STOP1/
-
-* Fan-in
-
-.image concurrency/images/gophermegaphones.jpg
-
-* Restoring sequencing
-
-Send a channel on a channel, making goroutine wait its turn.
-
-Receive all messages, then enable them again by sending on a private channel.
-
-First we define a message type that contains a channel for the reply.
-
-.code concurrency/support/sequenceboring.go /START0/,/STOP0/
-
-* Restoring sequencing.
-
-Each speaker must wait for a go-ahead.
-
-.code concurrency/support/sequenceboring.go /START1/,/STOP1/
-.code concurrency/support/sequenceboring.go /START2/,/STOP2/
-.play concurrency/support/sequenceboring.go /START3/,/STOP3/
-
-* Select
-
-A control structure unique to concurrency.
-
-The reason channels and goroutines are built into the language.
-
-* Select
-
-The select statement provides another way to handle multiple channels.
-It's like a switch, but each case is a communication:
-- All channels are evaluated.
-- Selection blocks until one communication can proceed, which then does.
-- If multiple can proceed, select chooses pseudo-randomly.
-- A default clause, if present, executes immediately if no channel is ready.
-
-.code concurrency/support/select.go /START0/,/STOP0/
-
-* Fan-in again
-
-Rewrite our original fanIn function. Only one goroutine is needed. Old:
-
-.code concurrency/support/faninboring.go /START3/,/STOP3/
-
-* Fan-in using select
-
-Rewrite our original fanIn function. Only one goroutine is needed. New:
-
-.play concurrency/support/selectboring.go /START3/,/STOP3/
-
-* Timeout using select
-
-The time.After function returns a channel that blocks for the specified duration.
-After the interval, the channel delivers the current time, once.
-
-.play concurrency/support/timeout.go /START1/,/STOP1/
-
-* Timeout for whole conversation using select
-
-Create the timer once, outside the loop, to time out the entire conversation.
-(In the previous program, we had a timeout for each message.)
-
-.play concurrency/support/timeoutall.go /START1/,/STOP1/
-
-
-* Quit channel
-
-We can turn this around and tell Joe to stop when we're tired of listening to him.
-
-.code concurrency/support/quit.go /START1/,/STOP1/
-.play concurrency/support/quit.go /START2/,/STOP2/
-
-
-* Receive on quit channel
-
-How do we know it's finished? Wait for it to tell us it's done: receive on the quit channel
-
-.code concurrency/support/rcvquit.go /START1/,/STOP1/
-.play concurrency/support/rcvquit.go /START2/,/STOP2/
-
-* Daisy-chain
-
-.play concurrency/support/daisy.go /func/,$
-
-* Chinese whispers, gopher style
-
-.image concurrency/images/gophereartrumpet.jpg
-
-* Systems software
-
-Go was designed for writing systems software.
-Let's see how the concurrency features come into play.
-
-* Example: Google Search
-	
-Q: What does Google search do?
-
-A: Given a query, return a page of search results (and some ads).
-
-Q: How do we get the search results?
-
-A: Send the query to Web search, Image search, YouTube, Maps, News,etc., then mix the results.
-
-How do we implement this?
-
-* Google Search: A fake framework
-
-We can simulate the search function, much as we simulated conversation before.
-
-.code concurrency/support/google.go /START2/,/STOP2/
-
-* Google Search: Test the framework
-
-.play concurrency/support/google.go /func.main/,/}/
-
-* Google Search 1.0
-
-The Google function takes a query and returns a slice of Results (which are just strings).
-
-Google invokes Web, Image, and Video searches serially, appending them to the results slice.
-
-.play concurrency/support/google.go /START1/,/STOP1/
-
-* Google Search 2.0
-
-Run the Web, Image, and Video searches concurrently, and wait for all results.
-
-No locks.  No condition variables.  No callbacks.
-
-.play concurrency/support/google2.1.go /Google/,/^}/
-
-* Google Search 2.1
-
-Don't wait for slow servers. No locks.  No condition variables.  No callbacks.
-
-.play concurrency/support/google2.2.go /START/,/STOP/
-
-* Avoid timeout
-
-Q: How do we avoid discarding results from slow servers?
-
-A: Replicate the servers.  Send requests to multiple replicas, and use the first response.
-
-.code concurrency/support/google2.3.go /START1/,/STOP1/
-
-* Using the First function
-
-.play concurrency/support/google2.3.go /START2/,/STOP2/
-
-* Google Search 3.0
-
-Reduce tail latency using replicated search servers.
-
-.play concurrency/support/google3.0.go /START/,/STOP/
-
-* And still…
-
-No locks.  No condition variables.  No callbacks.
-
-* Summary
-
-In just a few simple transformations we used Go's concurrency primitives to convert a
-
-- slow
-- sequential
-- failure-sensitive
-
-program into one that is
-
-- fast
-- concurrent
-- replicated
-- robust.
-
-* More party tricks
-
-There are endless ways to use these tools, many presented elsewhere.
-
-Chatroulette toy:
-
-.link http://golang.org/s/chat-roulette
-
-Load balancer:
-
-.link http://golang.org/s/load-balancer
-
-Concurrent prime sieve:
-
-.link http://golang.org/s/prime-sieve
-
-Concurrent power series (by McIlroy):
-
-.link http://golang.org/s/power-series
-
-* Don't overdo it
-
-They're fun to play with, but don't overuse these ideas.
-
-Goroutines and channels are big ideas. They're tools for program construction.
-
-But sometimes all you need is a reference counter.
-
-Go has "sync" and "sync/atomic" packages that provide mutexes, condition variables, etc. They provide tools for smaller problems.
-
-Often, these things will work together to solve a bigger problem.
-
-Always use the right tool for the job.
-
-* Conclusions
-
-Goroutines and channels make it easy to express complex operations dealing with
-
-- multiple inputs
-- multiple outputs
-- timeouts
-- failure
-
-And they're fun to use.
-
-
-* Links
-
-Go Home Page:
-
-.link http://golang.org
-
-Go Tour (learn Go in your browser)
-
-.link http://tour.golang.org
-
-Package documentation:
-
-.link http://golang.org/pkg
-
-Articles galore:
-
-.link http://golang.org/doc
-
-Concurrency is not parallelism:
-
-.link http://golang.org/s/concurrency-is-not-parallelism
diff --git a/content/2012/concurrency/images/gophereartrumpet.jpg b/content/2012/concurrency/images/gophereartrumpet.jpg
deleted file mode 100644
index 87f8571..0000000
--- a/content/2012/concurrency/images/gophereartrumpet.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/concurrency/images/gophermegaphones.jpg b/content/2012/concurrency/images/gophermegaphones.jpg
deleted file mode 100644
index 2bf6873..0000000
--- a/content/2012/concurrency/images/gophermegaphones.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/concurrency/support/boring.go b/content/2012/concurrency/support/boring.go
deleted file mode 100644
index b049ee0..0000000
--- a/content/2012/concurrency/support/boring.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	boring("boring!")
-}
-
-// START OMIT
-func boring(msg string) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(time.Second)
-	}
-}
-// STOP OMIT
diff --git a/content/2012/concurrency/support/changoboring.go b/content/2012/concurrency/support/changoboring.go
deleted file mode 100644
index f534359..0000000
--- a/content/2012/concurrency/support/changoboring.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := make(chan string)
-	go boring("boring!", c)
-	for i := 0; i < 5; i++ {
-		fmt.Printf("You say: %q\n", <-c) // Receive expression is just a value. // HL
-	}
-	fmt.Println("You're boring; I'm leaving.")
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string, c chan string) {
-	for i := 0; ; i++ {
-		c <- fmt.Sprintf("%s %d", msg, i) // Expression to be sent can be any suitable value. // HL
-		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-	}
-}
-// STOP2 OMIT
-
diff --git a/content/2012/concurrency/support/chat.go b/content/2012/concurrency/support/chat.go
deleted file mode 100644
index 200451a..0000000
--- a/content/2012/concurrency/support/chat.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net"
-)
-
-const listenAddr = "localhost:4000"
-
-func main() {
-	l, err := net.Listen("tcp", listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for {
-		c, err := l.Accept()
-		if err != nil {
-			log.Fatal(err)
-		}
-		go match(c)
-	}
-}
-
-var partner = make(chan io.ReadWriteCloser)
-
-func match(c io.ReadWriteCloser) {
-	fmt.Fprint(c, "Waiting for a partner...")
-	select {
-	case partner <- c:
-		// now handled by the other goroutine
-	case p := <-partner:
-		chat(p, c)
-	}
-}
-
-func chat(a, b io.ReadWriteCloser) {
-	fmt.Fprintln(a, "Found one! Say hi.")
-	fmt.Fprintln(b, "Found one! Say hi.")
-	go io.Copy(a, b)
-	io.Copy(b, a)
-}
diff --git a/content/2012/concurrency/support/daisy.go b/content/2012/concurrency/support/daisy.go
deleted file mode 100644
index 0f39812..0000000
--- a/content/2012/concurrency/support/daisy.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-func f(left, right chan int) {
-	left <- 1 + <-right
-}
-
-func main() {
-	const n = 10000
-	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 <- 1 }(right)
-	fmt.Println(<-leftmost)
-}
diff --git a/content/2012/concurrency/support/faninboring.go b/content/2012/concurrency/support/faninboring.go
deleted file mode 100644
index 08b3d80..0000000
--- a/content/2012/concurrency/support/faninboring.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := fanIn(boring("Joe"), boring("Ann")) // HL
-	for i := 0; i < 10; i++ {
-		fmt.Println(<-c) // HL
-	}
-	fmt.Println("You're both boring; I'm leaving.")
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
-
-// START3 OMIT
-func fanIn(input1, input2 <-chan string) <-chan string { // HL
-	c := make(chan string)
-	go func() { for { c <- <-input1 } }() // HL
-	go func() { for { c <- <-input2 } }() // HL
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/concurrency/support/generator2boring.go b/content/2012/concurrency/support/generator2boring.go
deleted file mode 100644
index 45be6f8..0000000
--- a/content/2012/concurrency/support/generator2boring.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	joe := boring("Joe") // HL
-	ann := boring("Ann") // HL
-	for i := 0; i < 5; i++ {
-		fmt.Println(<-joe)
-		fmt.Println(<-ann)
-	}
-	fmt.Println("You're both boring; I'm leaving.")
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
diff --git a/content/2012/concurrency/support/generatorboring.go b/content/2012/concurrency/support/generatorboring.go
deleted file mode 100644
index eeae3ca..0000000
--- a/content/2012/concurrency/support/generatorboring.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-// START1 OMIT
-	c := boring("boring!") // Function returning a channel. // HL
-	for i := 0; i < 5; i++ {
-		fmt.Printf("You say: %q\n", <-c)
-	}
-	fmt.Println("You're boring; I'm leaving.")
-// STOP1 OMIT
-}
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
diff --git a/content/2012/concurrency/support/goboring.go b/content/2012/concurrency/support/goboring.go
deleted file mode 100644
index e28b6a3..0000000
--- a/content/2012/concurrency/support/goboring.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-	go boring("boring!") // HL
-}
-// STOP OMIT
-
-func boring(msg string) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-	}
-}
diff --git a/content/2012/concurrency/support/google.go b/content/2012/concurrency/support/google.go
deleted file mode 100644
index 10089d3..0000000
--- a/content/2012/concurrency/support/google.go
+++ /dev/null
@@ -1,47 +0,0 @@
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-type Result string
-
-// START1 OMIT
-func Google(query string) (results []Result) {
-	results = append(results, Web(query))
-	results = append(results, Image(query))
-	results = append(results, Video(query))
-	return
-}
-// STOP1 OMIT
-
-// START2 OMIT
-var (
-	Web = fakeSearch("web")
-	Image = fakeSearch("image")
-	Video = fakeSearch("video")
-)
-
-type Search func(query string) Result // HL
-
-func fakeSearch(kind string) Search {
-        return func(query string) Result {
-	          time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-	          return Result(fmt.Sprintf("%s result for %q\n", kind, query))
-        }
-}
-// STOP2 OMIT
-
-func main() {
-	rand.Seed(time.Now().UnixNano())
-	start := time.Now()
-	results := Google("golang") // HL
-	elapsed := time.Since(start)
-	fmt.Println(results)
-	fmt.Println(elapsed)
-}
diff --git a/content/2012/concurrency/support/google2.1.go b/content/2012/concurrency/support/google2.1.go
deleted file mode 100644
index 53be753..0000000
--- a/content/2012/concurrency/support/google2.1.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-type Result string
-type Search func(query string) Result
-
-var (
-	Web = fakeSearch("web")
-	Image = fakeSearch("image")
-	Video = fakeSearch("video")
-)
-
-
-func Google(query string) (results []Result) {
-	c := make(chan Result)
-	go func() { c <- Web(query) } ()
-	go func() { c <- Image(query) } ()
-	go func() { c <- Video(query) } ()
-
-	for i := 0; i < 3; i++ {
-		result := <-c
-		results = append(results, result)
-	}
-	return
-}
-
-func fakeSearch(kind string) Search {
-        return func(query string) Result {
-	          time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-	          return Result(fmt.Sprintf("%s result for %q\n", kind, query))
-        }
-}
-
-func main() {
-	rand.Seed(time.Now().UnixNano())
-	start := time.Now()
-	results := Google("golang")
-	elapsed := time.Since(start)
-	fmt.Println(results)
-	fmt.Println(elapsed)
-}
-
-
diff --git a/content/2012/concurrency/support/google2.2.go b/content/2012/concurrency/support/google2.2.go
deleted file mode 100644
index 2dac79f..0000000
--- a/content/2012/concurrency/support/google2.2.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-type Result string
-type Search func(query string) Result
-
-var (
-	Web = fakeSearch("web")
-	Image = fakeSearch("image")
-	Video = fakeSearch("video")
-)
-
-func Google(query string) (results []Result) {
-// START OMIT
-	c := make(chan Result)
-	go func() { c <- Web(query) } ()
-	go func() { c <- Image(query) } ()
-	go func() { c <- Video(query) } ()
-
-	timeout := time.After(80 * time.Millisecond)
-	for i := 0; i < 3; i++ {
-		select {
-		case result := <-c:
-			results = append(results, result)
-		case <-timeout:
-			fmt.Println("timed out")
-			return
-		}
-	}
-	return
-// STOP OMIT
-}
-
-func fakeSearch(kind string) Search {
-        return func(query string) Result {
-	          time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-	          return Result(fmt.Sprintf("%s result for %q\n", kind, query))
-        }
-}
-
-func main() {
-	rand.Seed(time.Now().UnixNano())
-	start := time.Now()
-	results := Google("golang")
-	elapsed := time.Since(start)
-	fmt.Println(results)
-	fmt.Println(elapsed)
-}
-
diff --git a/content/2012/concurrency/support/google2.3.go b/content/2012/concurrency/support/google2.3.go
deleted file mode 100644
index 9382430..0000000
--- a/content/2012/concurrency/support/google2.3.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-type Result string
-type Search func(query string) Result
-
-// START1 OMIT
-func First(query string, replicas ...Search) Result {
-	c := make(chan Result)
-	searchReplica := func(i int) { c <- replicas[i](query) }
-	for i := range replicas {
-		go searchReplica(i)
-	}
-	return <-c
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func main() {
-	rand.Seed(time.Now().UnixNano())
-	start := time.Now()
-	result := First("golang",
-		fakeSearch("replica 1"),
-		fakeSearch("replica 2"))
-	elapsed := time.Since(start)
-	fmt.Println(result)
-	fmt.Println(elapsed)
-}
-// STOP2 OMIT
-
-func fakeSearch(kind string) Search {
-        return func(query string) Result {
-	          time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-	          return Result(fmt.Sprintf("%s result for %q\n", kind, query))
-        }
-}
-
diff --git a/content/2012/concurrency/support/google3.0.go b/content/2012/concurrency/support/google3.0.go
deleted file mode 100644
index 4188fcd..0000000
--- a/content/2012/concurrency/support/google3.0.go
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-type Result string
-type Search func(query string) Result
-
-var (
-	Web1 = fakeSearch("web1")
-        Web2 = fakeSearch("web2")
-	Image1 = fakeSearch("image1")
-	Image2 = fakeSearch("image2")
-	Video1 = fakeSearch("video1")
-	Video2 = fakeSearch("video2")
-)
-
-func Google(query string) (results []Result) {
-// START OMIT
-	c := make(chan Result)
-	go func() { c <- First(query, Web1, Web2) } ()
-	go func() { c <- First(query, Image1, Image2) } ()
-	go func() { c <- First(query, Video1, Video2) } ()
-	timeout := time.After(80 * time.Millisecond)
-	for i := 0; i < 3; i++ {
-		select {
-		case result := <-c:
-			results = append(results, result)
-		case <-timeout:
-			fmt.Println("timed out")
-			return
-		}
-	}
-	return
-// STOP OMIT
-}
-
-func First(query string, replicas ...Search) Result {
-	c := make(chan Result)
-	searchReplica := func(i int) {
-		c <- replicas[i](query)
-	}
-	for i := range replicas {
-		go searchReplica(i)
-	}
-        return <-c
-}
-
-func fakeSearch(kind string) Search {
-        return func(query string) Result {
-	          time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
-	          return Result(fmt.Sprintf("%s result for %q\n", kind, query))
-        }
-}
-
-func main() {
-	rand.Seed(time.Now().UnixNano())
-	start := time.Now()
-	results := Google("golang")
-	elapsed := time.Since(start)
-	fmt.Println(results)
-	fmt.Println(elapsed)
-}
diff --git a/content/2012/concurrency/support/helpers.go b/content/2012/concurrency/support/helpers.go
deleted file mode 100644
index a10c9cb..0000000
--- a/content/2012/concurrency/support/helpers.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-func main() {
-	var value int
-
-	// START1 OMIT
-	// Declaring and initializing.
-	var c chan int
-	c = make(chan int)
-	// or
-	c := make(chan int) // HL
-	// STOP1 OMIT
-
-	// START2 OMIT
-	// Sending on a channel.
-	c <- 1 // HL
-	// STOP2 OMIT
-
-	// START3 OMIT
-	// Receiving from a channel.
-	// The "arrow" indicates the direction of data flow.
-	value = <-c // HL
-	// STOP3 OMIT
-
-	_ = value
-}
diff --git a/content/2012/concurrency/support/lessboring.go b/content/2012/concurrency/support/lessboring.go
deleted file mode 100644
index 5549d51..0000000
--- a/content/2012/concurrency/support/lessboring.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-	boring("boring!") // HL
-}
-
-// START OMIT
-func boring(msg string) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-	}
-}
-// STOP OMIT
diff --git a/content/2012/concurrency/support/mainboring.go b/content/2012/concurrency/support/mainboring.go
deleted file mode 100644
index 31f1c1e..0000000
--- a/content/2012/concurrency/support/mainboring.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-	boring("boring!")
-}
-// STOP OMIT
-
-func boring(msg string) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-	}
-}
diff --git a/content/2012/concurrency/support/quit.go b/content/2012/concurrency/support/quit.go
deleted file mode 100644
index 9e16caf..0000000
--- a/content/2012/concurrency/support/quit.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-// START1 OMIT
-	quit := make(chan bool) // HL
-	c := boring("Joe", quit)
-	for i := rand.Intn(10); i >= 0; i-- { fmt.Println(<-c) }
-	quit <- true // HL
-// STOP1 OMIT
-}
-
-func boring(msg string, quit <-chan bool) <-chan string {
-	c := make(chan string)
-	go func() { // HL
-		for i := 0; ; i++ {
-			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-// START2 OMIT
-			select {
-			case c <- fmt.Sprintf("%s: %d", msg, i):
-				// do nothing
-			case <-quit: // HL
-				return
-			}
-// STOP2 OMIT
-		}
-	}()
-	return c
-}
diff --git a/content/2012/concurrency/support/rcvquit.go b/content/2012/concurrency/support/rcvquit.go
deleted file mode 100644
index 855332e..0000000
--- a/content/2012/concurrency/support/rcvquit.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func cleanup() {
-}
-
-func main() {
-// START1 OMIT
-	quit := make(chan string) // HL
-	c := boring("Joe", quit) // HL
-	for i := rand.Intn(10); i >= 0; i-- { fmt.Println(<-c) }
-	quit <- "Bye!" // HL
-	fmt.Printf("Joe says: %q\n", <-quit) // HL
-// STOP1 OMIT
-}
-
-func boring(msg string, quit chan string) <-chan string {
-	c := make(chan string) // HL
-	go func() {
-		for i := 0; ; i++ {
-			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-// START2 OMIT
-			select {
-			case c <- fmt.Sprintf("%s: %d", msg, i):
-				// do nothing
-			case <-quit: // HL
-				cleanup()
-				quit <- "See you!" // HL
-				return
-			}
-// STOP2 OMIT
-		}
-	}()
-	return c
-}
diff --git a/content/2012/concurrency/support/select.go b/content/2012/concurrency/support/select.go
deleted file mode 100644
index aa707af..0000000
--- a/content/2012/concurrency/support/select.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-func main() {
-	var c1, c2, c3 chan int
-	// START0 OMIT
-	select {
-	case v1 := <-c1:
-		fmt.Printf("received %v from c1\n", v1)
-	case v2 := <-c2:
-		fmt.Printf("received %v from c2\n", v1)
-	case c3 <- 23:
-		fmt.Printf("sent %v to c3\n", 23)
-	default:
-		fmt.Printf("no one was ready to communicate\n")
-	}
-	// STOP0 OMIT
-}
diff --git a/content/2012/concurrency/support/selectboring.go b/content/2012/concurrency/support/selectboring.go
deleted file mode 100644
index 78cb5c7..0000000
--- a/content/2012/concurrency/support/selectboring.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := fanIn(boring("Joe"), boring("Ann")) // HL
-	for i := 0; i < 10; i++ {
-		fmt.Println(<-c) // HL
-	}
-	fmt.Println("You're both boring; I'm leaving.")
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
-
-// START3 OMIT
-func fanIn(input1, input2 <-chan string) <-chan string { // HL
-	c := make(chan string)
-	go func() { // HL
-		for {
-			select { // HL
-			case s := <-input1:  c <- s  // HL
-			case s := <-input2:  c <- s  // HL
-			}  // HL
-		}
-	}()
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/concurrency/support/sequenceboring.go b/content/2012/concurrency/support/sequenceboring.go
deleted file mode 100644
index 1117466..0000000
--- a/content/2012/concurrency/support/sequenceboring.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START0 OMIT
-type Message struct {
-	str string
-	wait chan bool // HL
-}
-// STOP0 OMIT
-
-func main() {
-	c := fanIn(boring("Joe"), boring("Ann")) // HL
-// START1 OMIT
-	for i := 0; i < 5; i++ {
-		msg1 := <-c; fmt.Println(msg1.str)
-		msg2 := <-c; fmt.Println(msg2.str)
-		msg1.wait <- true
-		msg2.wait <- true
-	}
-// STOP1 OMIT
-	fmt.Println("You're all boring; I'm leaving.")
-}
-
-func boring(msg string) <-chan Message { // Returns receive-only channel of strings. // HL
-	c := make(chan Message)
-// START2 OMIT
-	waitForIt := make(chan bool) // Shared between all messages.
-// STOP2 OMIT
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-// START3 OMIT
-			c <- Message{ fmt.Sprintf("%s: %d", msg, i), waitForIt }
-			time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
-			<-waitForIt
-// STOP3 OMIT
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-
-
-// START3 OMIT
-func fanIn(inputs ... <-chan Message) <-chan Message { // HL
-	c := make(chan Message)
-	for i := range inputs {
-		input := inputs[i] // New instance of 'input' for each loop.
-		go func() { for { c <- <-input } }()
-	}
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/concurrency/support/timeout.go b/content/2012/concurrency/support/timeout.go
deleted file mode 100644
index 7d8cab9..0000000
--- a/content/2012/concurrency/support/timeout.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := boring("Joe")
-	for {
-		select {
-		case s := <-c:
-			fmt.Println(s)
-		case <-time.After(1 * time.Second): // HL
-			fmt.Println("You're too slow.")
-			return
-		}
-	}
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
-
-// START3 OMIT
-func fanIn(input1, input2 <-chan string) <-chan string { // HL
-	c := make(chan string)
-	go func() {
-		for {
-			select {
-			case s := <-input1:
-				c <- s
-			case s := <-input2:
-				c <- s
-			}
-		}
-	}()
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/concurrency/support/timeoutall.go b/content/2012/concurrency/support/timeoutall.go
deleted file mode 100644
index 5dd4a89..0000000
--- a/content/2012/concurrency/support/timeoutall.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := boring("Joe")
-	timeout := time.After(5 * time.Second) // HL
-	for {
-		select {
-		case s := <-c:
-			fmt.Println(s)
-		case <-timeout: // HL
-			fmt.Println("You talk too much.")
-			return
-		}
-	}
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
-
-// START3 OMIT
-func fanIn(input1, input2 <-chan string) <-chan string { // HL
-	c := make(chan string)
-	go func() {
-		for {
-			select {
-			case s := <-input1:
-				c <- s
-			case s := <-input2:
-				c <- s
-			}
-		}
-	}()
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/concurrency/support/waitgoboring.go b/content/2012/concurrency/support/waitgoboring.go
deleted file mode 100644
index 3fb1fb8..0000000
--- a/content/2012/concurrency/support/waitgoboring.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-func main() {
-	go boring("boring!")
-	fmt.Println("I'm listening.")
-	time.Sleep(2 * time.Second)
-	fmt.Println("You're boring; I'm leaving.")
-}
-// STOP OMIT
-
-func boring(msg string) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
-	}
-}
diff --git a/content/2012/go-docs.slide b/content/2012/go-docs.slide
deleted file mode 100644
index b160c6c..0000000
--- a/content/2012/go-docs.slide
+++ /dev/null
@@ -1,242 +0,0 @@
-Go docs
-Golang-Syd, Oct 17, 2012
-
-Rob Pike
-Google, Inc.
-@rob_pike
-http://golang.org/s/plusrob
-http://golang.org
-
-* Documentation
-
-* Text
-
-There are many ways to show documentation as text
-
-* Man pages: Unix 1st Edition, 1971
-
-.image go-docs/seek.png
-
-* Man pages: Apple OS X 10.8, 2012
-
-.image go-docs/lseek.png
-
-* Javadoc 1996+
-
-.image go-docs/javadoc.png
-
-* Javadoc 1996+
-
-.image go-docs/javadoc1.png
-
-* Godoc 2009+
-
-.image go-docs/godoc.png
-
-* Godoc 2009+
-
-.image go-docs/godoc1.png
-
-* Godoc
-
-.link http://golang.org/pkg/utf16
-
-* blog.golang.org
-
-.image go-docs/blog.png
-
-* Code walks
-
-.image go-docs/codewalk.png
-
-* Community contributions
-
-* Go wiki
-
-.link http://golang.org/wiki
-
-.image go-docs/gowiki.png
-
-* Gopkgdoc
-
-.link http://go.pkgdoc.org
-
-.image go-docs/gopkgdoc.png
-
-* Gopkgdoc
-
-.link http://go.pkgdoc.org/code.google.com/p/goauth2/oauth
-
-* Go By Example
-
-.link https://gobyexample.com
-
-.image go-docs/gobyexample.png
-
-* Go By Example
-
-.link https://gobyexample.com/timeouts
-
-* Talks
-
-* Presentations
-
-We give a lot of talks.
-
-Most of the tools for presentations focus on style, not ease of creation.
-
-* Present
-
-In the `go.talks` repo, have a new tool: `present`.
-
-	go get code.google.com/p/go.talks/present
-
-- Simple
-- Easy to use
-- Easy, smooth to present
-
-Took about an hour to put this talk together.
-
-Docs:
-
-.link http://go.pkgdoc.org/code.google.com/p/go.talks/present
-
-* Input for the previous slide
-
-.code go-docs.slide /^\* Present$/,/^\.link/
-
-* Input for the previous slide redux
-
-.code go-docs.slide /^\*.*previous/,/^\.code/
-
-* Revenge of the input for the the previous slide 
-
-.code go-docs.slide /^\*.*redux/,/^\.code/
-
-
-* Many choices
-
-Lots of presentations, different styles.
-
-* Fatal flaw
-
-They all have code.
-
-Can't execute the code!
-
-Want to edit and play.
-
-* The playground
-
-.image go-docs/play.png
-
-* Can run code from the browser
-
-.link http://play.golang.org
-
-* The tour
-
-.image go-docs/tour.png
-
-* Can run code from the browser
-
-.link http://tour.golang.org
-
-* Use this technology
-
-Want to embed the playground technology in the other media.
-
-Triggering example: Go Concurrency Patterns, Google I/O, 2012
-
-Needed to demonstrate concurrency and the passage of time.
-
-* Go Concurrency Patterns
-
-An extract from the talk.
-
-* Multiplexing
-
-These programs make Joe and Ann count in lockstep.
-We can instead use a fan-in function to let whosoever is ready talk.
-
-.code go-docs/faninboring.go /START3/,/STOP3/
-.play go-docs/faninboring.go /START1/,/STOP1/
-
-* .code and .play
-
-Input for the previous slide:
-
-.code go-docs.slide /^\* Multiplexing/,/^.play/
-
-* faninboring.go (I)
-
-	package main
-
-	import (
-		"fmt"
-		"math/rand"
-		"time"
-	)
-
-	// START1 OMIT
-	func main() {
-		c := fanIn(boring("Joe"), boring("Ann")) // HL
-		for i := 0; i < 10; i++ {
-			fmt.Println(<-c) // HL
-		}
-		fmt.Println("You're both boring; I'm leaving.")
-	}
-	// STOP1 OMIT
-	
-* faninboring.go (II)
-
-	// START2 OMIT
-	func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-		c := make(chan string)
-		go func() { // We launch the goroutine from inside the function. // HL
-			for i := 0; ; i++ {
-				c <- fmt.Sprintf("%s: %d", msg, i)
-				time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
-			}
-		}()
-		return c // Return the channel to the caller. // HL
-	}
-	// STOP2 OMIT
-
-
-	// START3 OMIT
-	func fanIn(input1, input2 <-chan string) <-chan string { // HL
-		c := make(chan string)
-		go func() { for { c <- <-input1 } }() // HL
-		go func() { for { c <- <-input2 } }() // HL
-		return c
-	}
-	// STOP3 OMIT
-
-* .code and .play again
-
-The input for the Multiplexing slide again:
-
-.code go-docs.slide /^\* Multiplexing/,/^.play/
-
-* Multiplexing again
-
-These programs make Joe and Ann count in lockstep.
-We can instead use a fan-in function to let whosoever is ready talk.
-
-.code go-docs/faninboring.go /START3/,/STOP3/
-.play go-docs/faninboring.go /START1/,/STOP1/
-
-* Executable documentation
-
-* Plans
-
-Deploy executable examples throughout:
-
-- godoc (already done)
-- blog
-- code walks
-- Go By Example
-- wiki
-
-.link http://golang.org/pkg/strings/#example_Contains
diff --git a/content/2012/go-docs/blog.png b/content/2012/go-docs/blog.png
deleted file mode 100644
index d0a63fd..0000000
--- a/content/2012/go-docs/blog.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/codewalk.png b/content/2012/go-docs/codewalk.png
deleted file mode 100644
index 7cfcaca..0000000
--- a/content/2012/go-docs/codewalk.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/faninboring.go b/content/2012/go-docs/faninboring.go
deleted file mode 100644
index 08b3d80..0000000
--- a/content/2012/go-docs/faninboring.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := fanIn(boring("Joe"), boring("Ann")) // HL
-	for i := 0; i < 10; i++ {
-		fmt.Println(<-c) // HL
-	}
-	fmt.Println("You're both boring; I'm leaving.")
-}
-// STOP1 OMIT
-
-// START2 OMIT
-func boring(msg string) <-chan string { // Returns receive-only channel of strings. // HL
-	c := make(chan string)
-	go func() { // We launch the goroutine from inside the function. // HL
-		for i := 0; ; i++ {
-			c <- fmt.Sprintf("%s: %d", msg, i)
-			time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
-		}
-	}()
-	return c // Return the channel to the caller. // HL
-}
-// STOP2 OMIT
-
-
-// START3 OMIT
-func fanIn(input1, input2 <-chan string) <-chan string { // HL
-	c := make(chan string)
-	go func() { for { c <- <-input1 } }() // HL
-	go func() { for { c <- <-input2 } }() // HL
-	return c
-}
-// STOP3 OMIT
diff --git a/content/2012/go-docs/gobyexample.png b/content/2012/go-docs/gobyexample.png
deleted file mode 100644
index 48e5f5c..0000000
--- a/content/2012/go-docs/gobyexample.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/godoc.png b/content/2012/go-docs/godoc.png
deleted file mode 100644
index 7582f9c..0000000
--- a/content/2012/go-docs/godoc.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/godoc1.png b/content/2012/go-docs/godoc1.png
deleted file mode 100644
index 013e1cd..0000000
--- a/content/2012/go-docs/godoc1.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/gopkgdoc.png b/content/2012/go-docs/gopkgdoc.png
deleted file mode 100644
index 49a2709..0000000
--- a/content/2012/go-docs/gopkgdoc.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/gowiki.png b/content/2012/go-docs/gowiki.png
deleted file mode 100644
index c00702e..0000000
--- a/content/2012/go-docs/gowiki.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/javadoc.png b/content/2012/go-docs/javadoc.png
deleted file mode 100644
index 1930159..0000000
--- a/content/2012/go-docs/javadoc.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/javadoc1.png b/content/2012/go-docs/javadoc1.png
deleted file mode 100644
index 5dde5a7..0000000
--- a/content/2012/go-docs/javadoc1.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/lseek.png b/content/2012/go-docs/lseek.png
deleted file mode 100644
index 4e88af9..0000000
--- a/content/2012/go-docs/lseek.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/play.png b/content/2012/go-docs/play.png
deleted file mode 100644
index 546914b..0000000
--- a/content/2012/go-docs/play.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/seek.png b/content/2012/go-docs/seek.png
deleted file mode 100644
index 7a89771..0000000
--- a/content/2012/go-docs/seek.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go-docs/tour.png b/content/2012/go-docs/tour.png
deleted file mode 100644
index 998787a..0000000
--- a/content/2012/go-docs/tour.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go1.slide b/content/2012/go1.slide
deleted file mode 100644
index be0eb63..0000000
--- a/content/2012/go1.slide
+++ /dev/null
@@ -1,507 +0,0 @@
-The Path to Go 1
-
-Rob Pike
-Google
-http://golang.org/s/plusrob
-@rob_pike
-http://golang.org
-
-Andrew Gerrand
-Google
-http://andrewgerrand.com
-@go_nuts
-http://golang.org
-
-
-* Introduction
-
-Go is a concurrent open source programming language developed at Google.
-
-Combines native compilation and static types with a lightweight dynamic feel.
-
-Fast, fun, and productive.
-
-
-* What is Go?
-
-Features:
-
-- Native code generation (compiled)
-- Statically typed
-- Composition via interfaces
-- Memory safe
-- Garbage collected
-- Native concurrency support
-- Excellent standard library
-- Great tools
-
-
-* History
-
-
-* History
-
-Began as a Google 20% project in late 2007.
-
-Released as an open source project in November 2009.
-
-Go 1 released in March 2012.
-
-
-* The Go project
-
-Planned from the start as an open source project.
-
-Publicly released under a BSD license.
-
-To date: 28 committers from Google and elsewhere.
-
-More than 200 other people have contributed to the project.
-
-9735 changes committed since release.
-
-
-* Development process
-
-Mercurial version control system with plugin for code review.
-
-No branches; linear history.
-
-Code review central to the project. All changes reviewed on golang-dev list using Rietveld (codereview.appspot.com).
-
-Custom continuous build system tests across all supported platforms.
-
-Contributions accepted on a "Discuss first, code later" basis.
-
-
-* Contributions over time
-
-The project moves fast:
-
-.image go1/changes.png
-
-Windows, FreeBSD, OpenBSD, NetBSD, and Plan 9 ports are community-driven.
-
-
-* Managing the project
-
-* Development cycle
-
-Changes are made continuously.
-
-Things break. Things get fixed.
-Some days are better than others.
-
-Continuous builders help, but don't reveal all issues.
-
-We needed to provide some stability for our users.
-
-
-* Weekly snapshots
-
-Attempt to keep everyone in sync.
-
-- Apply a Mercurial tag to a specific, stable revision.
-- Announce to user mailing list with detailed changelog.
-
-Great for early adopters and core developers.
-
-
-* Problems with weeklies
-
-Contributors work at tip; users sync to weeklies.
-
-Burden on users:
-
-- annoying to update weekly,
-- painful to update less often.
-
-Version skew results because users are at different weeklies.
-
-Skew fragments the community and slows adoption.
-
-
-* Formal release process
-
-March 2011: introduced releases every 1-2 months.
-
-- Pick the most stable of the past few snapshots and tag it.
-- Announce with abridged "must read" release notes.
-
-Keeps the community more in sync. Reduces churn.
-
-Popular with users.
-
-
-* Problem with releases
-
-Easy to make a few small changes once a week...
-
-\...but hard to make many small changes once a month.
-
-Skew still prevalent: adventurers and core devs still use weeklies (or tip!).
-
-
-* Introducing Gofix
-
-A tool to mechanically update code to accommodate language and library changes.
-
-  gofix prog.go
-
-Announced in May 2011.
-Gofix automates updates for backward-incompatible changes.
-Eases the burden of staying current.
-
-Release notes now mostly say "run gofix."
-
-Not a sed script. Works on the AST.
-
-
-* Gofix
-
-Gofix enables sweeping changes without fear of breaking the code base.
-
-Gofix gave us the freedom to make widespread changes that would have been too daunting otherwise.
-
-Can even update foreign code:
-
-"Yesterday I gofixed some third-party packages without even reading their code and without waiting for the authors to update them." - Dmitry Chestnykh
-
-
-* Versioning issues persist
-
-Gofix is no panacea.
-
-As the root of the dependency graph, a programming language can suffer acutely from version skew.
-
-The fundamental issue remains:
-Code you write today may not compile tomorrow.
-
-Some companies unwilling to bet on Go as they saw it as unstable.
-
-
-* A need for stability
-
-Gofix makes changes very easy, and also makes it easy to experiment.
-But it can't do everything.
-
-Priorities: If change is easy, what change is important?
-
-Wanted to make major changes to the language and libraries but, even with gofix, some things are too disruptive without proper planning.
-
-Decision: design and implement a stable version of Go, its libraries, and its tools.
-
-
-* Go 1
-
-* What is Go 1?
-
-A specification of the language and libraries that will be supported for years.
-
-Available as downloadable binary packages.
-
-An opportunity to:
-
-- fix minor language irritations,
-- fix inconsistencies in the standard library,
-- focus on bug fixing and cleaning up TODOs,
-- design and build a strong build tool set (get rid of make),
-- bring Windows support up to par.
-
-Polish and refine, not redesign.
-
-
-* Planning Go 1
-
-Wrote a detailed proposal document.
-
-Implemented (but not committed) many of the proposed changes.
-
-Core team met for a week to discuss and refine the document (October 2011).
-
-Presented the document to the community for discussion.
-
-Community feedback essential in refining the proposal.
-
-
-* Preparing Go 1
-
-
-Create many new issues on the tracker.
-
-Categorize new and existing issues as either "Go 1" or "after Go 1".
-
-Contributors nominate themselves to address specific issues.
-
-Stop developing new features; prioritize stability.
-
-
-* Rolling it out
-
-Daily number of lines changed in the months leading up to Go 1:
-
-.image go1/go1lines.png
-
-
-* Gofix and Go 1
-
-The largest Go 1 edits were performed by gofix.
-
-Gofix made it easy to try out a change and refine it incrementally.
-
-Some significant changes were tried and abandoned.
-
-
-* Gofix work flow
-
-Scripted work flow allowed us to avoid branches and merging nightmares.
-#Total automation of edits makes it easy to do large changes without branching.
-
-Process:
-
-  while !satisfied {
-    in tree 1:
-      refine gofix module in tree 1, build binary
-    in tree 2:
-      revert to tip (note: tip)
-      apply gofix binary from tree 2
-      build and test
-  }
-  commit tree 1
-  commit tree 2
-
-Even as other changes are happening, this leads to no branching or skew.
-
-* Sample change
-
-.image go1/errordiff1.png
-.image go1/errordiff2.png
-
-* Go 1 release process
-
-Releases paused from r60 (August 2011).
-Weeklies continued as normal.
-
-Issued release candidates in the weeks leading up to launch.
-
-Release candidates included binary distributions for the supported operating systems (FreeBSD, Linux, Mac OS X, and Windows).
-
-
-* What is in Go 1?
-
-* Go 1
-
-Specification of the language.
-
-Specification of the libraries.
-
-Promise of long term compatibility.
-
-Windows as a first class citizen.
-
-New tool chain centered around the `go` tool.
-
-"Phase change" in the way the project runs.
-
-
-* Language changes
-
-A new `rune` type to represent a Unicode code point.
-(Important step in making `int` either 32 or 64 bits; currently just 32.)
-
-A new built-in `error` type to replace `os.Error`.
-This affected almost all Go code in existence.
-
-Equality defined on structs.
-
-Cleaned up some clumsy operations.
-
-
-* API changes
-
-A re-designed `time` package with a clean, simple interface.
-
-Regularization of `strconv`, breaking away from the old C-style API.
-
-Widespread package re-organization. Put things in more appropriate places.
-
-Dozens of lesser changes.
-
-
-* Time
-
-Old time package was based on the Unix epoch. Limited range, poor features,
-no type safety (just integer nanoseconds).
-
-Substantial redesign creates separate Time and Duration types.
-Time can represent huge range of times with nanosecond precision.
-
-Duration specifies intervals. Example:
-
-  time.Sleep(2)             // Old API, unsafe: How long is this?
-  time.Sleep(2*time.Second) // New API: type-safe, readable.
-
-  fmt.Println(time.Now().Add(1e6*time.Hour))
-
-Also a new flag type!
-
-  $ command -timeout 1m30s
-
-* Re-organization
-
-Rearranged the organically constructed tree to group related things together.
-Examples:
-
-  Old         New
-
-  "asn1"      "encoding/asn1"
-  "csv"       "encoding/csv"
-  "gob"       "encoding/gob"
-  "json"      "encoding/json"
-  "xml"       "encoding/xml"
-  
-  "unicode"   "unicode"
-  "utf8"      "unicode/utf8"
-  "utf16"     "unicode/utf16"
-
-All updated by gofix, of course.
-
-* Demoting immature packages and commands
-
-Parts of the tree deemed unready should not be part of Go 1.
-
-Working but immature packages were moved to sub-repositories of the main Go repository. (They remain installable.)
-
-Unfinished and old packages and tools were left out.
-
-
-* How to build
-
-Before Go 1, Go programs were built with make, but Makefiles are annoying to write and, for Go, redundant.
-
-From the beginning, a goal of Go was good dependency management.
-
-By design, Go source code contains all the information necessary to build.
-
-Go 1 includes a new "go tool" that eliminates the need for make.
-
-Given a Go tree (including remote dependencies), can build and install directly:
-
-  $ go build file.go
-
-* The go tool
-
-A complete build, test, and install tool for Go programs.
-
-Some realistic examples:
-
-  $ go run hello.go       # Compile-and-go. (Ha!).
-  $ go build package      # Build everything in directory (and deps).
-  $ go install            # Install everything in dir and (and deps).
-  $ go test archive/zip   # Compile and run unit tests for package.
-
-The go tool also wraps `gofmt`, `gofix`, etc.:
-
-  $ go fmt                # Run gofmt on package in current dir.
-  $ go fix                # Run gofix on package in current dir.
-
-* The go tool and remote repositories
-
-The go tool automates installation of remote packages.
-
-Packages are addressed by import strings.
-Import strings are just source repository URLs.
-Go tool downloads and installs all dependencies, transitively.
-
-  $ go get code.google.com/p/myrepo/mypackage
-
-Installs my package, plus any remote dependencies it may have.
-And to use the package in Go source:
-
-	import "code.google.com/p/myrepo/mypackage"
-
-The tool can even run gofix as it installs:
-
-  $ go get -fix code.google.com/p/myrepo/mypackage
-
-
-* Documentation
-
-Complete reworking:
-
-- updated,
-- unified,
-- added new documents,
-- added new (executable) examples,
-- redesigned web site.
-
-
-* API compatibility tool
-
-Scans the entire standard library and checks it against a master list (`go1.txt`).
-
-Helps guarantee compatibility as development continues.
-
-Part of our build process in the lead up to Go 1 (and continues today).
-
-
-* Today and tomorrow
-
-* What are we working on?
-
-The goal for Go 1 was a stable, productive environment.
-
-Now that Go 1 is out, we are shifting our focus to using Go more than just developing it.
-
-Only through using Go extensively can we learn what might be needed in a future version, say Go 2.
-
-* There is still active development
-
-The design is locked down but work continues.
-
-Stability: bug fixes.
-
-Efficiency:
-
-- code generation,
-- garbage collection,
-- scheduling,
-- hot spots in standard libraries.
-
-Portability: NetBSD, OpenBSD, and Plan 9 ports in progress.
-
-New libraries: HTML parsing and Unicode collation packages, for example.
-
-* Releases after Go 1
-
-Two minor point releases (`go1.0.1` and `go1.0.2`) have been issued to fix bugs.
-
-The next major point release (`go1.1`) is planned for the end of 2012.
-It will include:
-
-- code generation improvements to the `gc` compiler,
-- performance and accuracy improvements to the garbage collector,
-- (possibly) an improved scheduler,
-- a slew of bug fixes.
-
-Go 2 is likely years away.
-
-
-* Learn more
-
-The Go web site has a huge amount of documentation:
-
-.link http://golang.org
-
-Learn Go from a web browser:
-
-.link http://tour.golang.org
-
-"Meet the Go team" panel from Google I/O 2012:
-
-.link http://golang.org/s/meet-the-go-team
-
-Google Code project:
-
-.link http://code.google.com/p/go
-
diff --git a/content/2012/go1/changes.png b/content/2012/go1/changes.png
deleted file mode 100644
index 3406e97..0000000
--- a/content/2012/go1/changes.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go1/errordiff1.png b/content/2012/go1/errordiff1.png
deleted file mode 100644
index 4e2b951..0000000
--- a/content/2012/go1/errordiff1.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go1/errordiff2.png b/content/2012/go1/errordiff2.png
deleted file mode 100644
index 3eae7d4..0000000
--- a/content/2012/go1/errordiff2.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/go1/go1lines.png b/content/2012/go1/go1lines.png
deleted file mode 100644
index 100f6c7..0000000
--- a/content/2012/go1/go1lines.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/goforc.slide b/content/2012/goforc.slide
deleted file mode 100644
index 14ce425..0000000
--- a/content/2012/goforc.slide
+++ /dev/null
@@ -1,726 +0,0 @@
-Go for C programmers
-ACCU, Silicon Valley Chapter, Nov. 14, 2012
-
-# Go is a general-purpose programming language developed at Google.
-# Go's design is influenced by the C and Pascal lineage, but instead of providing
-# a conglomerate of features, Go takes a fresh look at the essential mechanisms
-# required for modern programming tasks. As a result, Go has evolved to a compact
-# language of surprising power. In this presentation we give a brief introduction
-# to Go, slightly slanted towards programmers with a C/C++ background, and then
-# talk about particularly interesting aspects of Go.
-
-Robert Griesemer
-Google Inc.
-gri@golang.org
-
-* Organization of this talk
-
-Part 1: Introduction to Go
-
-Break
-
-Part 2: Object-oriented and concurrent programming in Go
-
-# if time permits and desire exists
-
-* Motivation
-
-* Have
-
-Incomprehensible and unsafe code.
-
-Extremely slow builds.
-
-Missing concurrency support.
-
-Outdated tools.
-
-# C, C++ are > 30 years old!
-# Java is 15 years old, but not really a systems-programming language.
-# (No control over data layout, no unsigned, verbose, etc.)
-
-* Want
-
-Readable, safe, and efficient code.
-
-A build system that scales.
-
-Good concurrency support.
-
-Tools that can operate at Google-scale.
-
-# A language for the 21. century!
-
-* Meet Go
-
-Compact, yet expressive
-# spec is ~50 pages
-
-Statically typed and garbage collected
-
-Object- but not type-oriented
-
-Strong concurrency support
-
-Efficient implementation
-
-Rich standard library
-
-Fast compilers
-
-Scalable tools
-
-* Hello, World
-
-.play goforc/hello.go
-
-# the canonical first program
-# note: immediately readable for a C programmer even without prior knowledge of Go
-# (not the case with C++'s Hello, World, which is using the << operator)
-# which bring us to the first item on the "Want" list: readable code.
-
-* Syntax
-
-* Syntax
-
-_Syntax_is_not_important..._-_unless_you_are_a_programmer._
-Rob Pike.
-
-_The_readability_of_programs_is_immeasurably_more_important_than_their_writeability._
-Hints on Programming Language Design
-C. A. R. Hoare 1973
-
-# A lot of effort has gone into honing Go's syntax over more than 3 years.
-# The result is a clutter- and stutter-free, compact, yet readable notation.
-# Consider some alternatives...
-
-* Too verbose
-
-	scoped_ptr<logStats::LogStats>
-		logStats(logStats::LogStats::NewLogStats(FLAGS_logStats, logStats::LogStats::kFIFO));
-
-# real example from C++ (2012) (names changed)
-# logStats mentioned 9 times!
-# too much clutter
-
-* Too dense
-
-	(n: Int) => (2 to n) |> (r => r.foldLeft(r.toSet)((ps, x) =>
-		if (ps(x)) ps -- (x * x to n by x) else ps))
-
-# prime sieve in Scala
-# pretty and short but incomprehensible
-
-* Just right
-
-	t := time.Now()
-	switch {
-	case t.Hour() < 12:
-	    return "morning"
-	case t.Hour() < 18:
-	    return "afternoon"
-	default:
-	    return "evening"
-	}
-
-# looks like pseudo code
-# readable even w/o knowing Go
-# lots of things are going on but not relevant for understanding
-# no clutter
-
-* Reading Go code
-
-* Packages
-
-A Go program consists of _packages_.
-
-A _package_ consists of one or more _source_files_ (`.go` files).
-
-Each _source_file_ starts with a _package_clause_ followed by declarations.
-
-.code goforc/hello.go
-
-By convention, all files belonging to a single package are located in a single directory.
-
-* Declarations, "Pascal-style" (left to right)
-
-Pattern: keyword names [type] [initializer]
-
-.code goforc/decls.go /START/,/STOP/
-
-* Why?
-
-	p, q *Point
-
-	func adder(delta int) func(x int) int
-
-# try this in C
-# composition of types straight-forward
-
-* Constants
-
-In Go, constants are _mathematically_precise_.
-
-There is no need for qualifiers (`-42LL`, `7UL`, etc.)
-
-.code goforc/consts.go /START1/,/STOP1/
-
-Only when used, constants are truncated to size:
-
-.play goforc/consts.go /START2/,/STOP2/
-
-Huge win in readability and ease of use.
-
-* Types
-
-Familiar:
-- Basic types, arrays, structs, pointers, functions.
-
-But:
-- `string` is a basic type.
-- No automatic conversion of basic types in expressions.
-- No pointer arithmetic; pointers and arrays are different.
-- A function type represents a function; context and all.
-
-New:
-- _Slices_ instead of array pointers + separate length: `[]int`
-- _Maps_ because everybody needs them: `map[string]int`
-- _Interfaces_ for polymorphism: `interface{}`
-- _Channels_ for communication between goroutines: `chan` `int`
-
-* Variables
-
-Familiar:
-
-.code goforc/vars.go /START1/,/STOP1/
-
-New: Type can be inferred from type of initializing expression.
-
-.code goforc/vars.go /START2/,/STOP2/
-
-Shortcut (inside functions):
-
-.code goforc/vars.go /i :=/
-
-It is _safe_ to take the address of _any_ variable:
-
-.code goforc/vars.go /return/
-
-* Functions
-
-Functions may have multiple return values:
-
-	func atoi(s string) (i int, err error)
-
-Functions are first-class citizens (_closures_):
-
-.code goforc/adder.go /START1/,/STOP1/
-.play goforc/adder.go /START2/,/STOP2/
-
-* Statements
-
-.code goforc/stmts.go /START/,/STOP/
-
-* Go statements for C programmers
-
-Cleanups:
-
-- No semicolons
-- Multiple assignments
-- `++` and `--` are statements
-- No parentheses around conditions; curly braces mandatory
-- Implicit `break` in `switch`; explicit `fallthrough`
-
-New:
-
-- `for` `range`
-- type `switch`
-- `go`, `select`
-- `defer`
-
-* Assignments
-
-Assignments may assign multiple values simultaneously:
-
-	a, b = x, y
-
-Equivalent to:
-
-	t1 := x
-	t2 := y
-	a = t1
-	b = t2
-
-For instance:
-
-	a, b = b, a       // swap a and b
-	i, err = atoi(s)  // assign results of atoi
-	i, _ = atoi(991)  // discard 2nd value
-
-* Switch statements
-
-Switch statements may have multiple case values, and `break` is implicit:
-
-	switch day {
-	case 1, 2, 3, 4, 5:
-		tag = "workday"
-	case 0, 6:
-		tag = "weekend"
-	default:
-		tag = "invalid"
-	}
-
-The case values don't have to be constants:
-
-	switch {
-	case day < 0 || day > 6:
-		tag = "invalid"
-	case day == 0 || day == 6:
-		tag = "weekend"
-	default:
-		tag = "workday"
-	}
-
-* For loops
-
-.code goforc/forloop.go /START1/,/STOP1/
-
-A `range` clause permits easy iteration over arrays and slices:
-
-.play goforc/forloop.go /START3/,/STOP3/
-
-Unused values are discarded by assigning to the blank (_) identifier:
-
-.code goforc/forloop.go /START2/,/STOP2/
-
-* Dependencies
-
-* Dependencies in Go
-
-An _import_declaration_ is used to express a _dependency_ on another package:
-
-	import "net/rpc"
-
-Here, the importing package depends on the Go package "rpc".
-
-The _import_path_ ("net/rpc") uniquely identifies a package; multiple packages may have the same name, but they all reside at different locations (directories).
-
-By convention, the package name matches the last element of the import path (here: "rpc").
-
-_Exported_ functionality of the `rpc` package is available via the _package_qualifier_ (`rpc`):
-
-	rpc.Call
-
-A Go import declaration takes the place of a C _include_.
-
-* Naming: An excursion
-
-How names work in a programming language is critical to readability.
-Scopes control how names work.
-Go has very simple scope hierarchy:
-
-- universe
-- package
-- file (for imports only)
-- function
-- block
-
-* Locality of names
-
-Upper case names are _exported_: `Name` _vs._ `name`.
-
-The package qualifier is always present for imported names.
-
-(First component of) every name is always declared in the current package.
-
-One of the best (and hardest!) decisions made in Go.
-
-* Locality scales
-
-No surprises when importing:
-
-- Adding an exported name to my package cannot break your package!
-
-Names do not leak across boundaries.
-
-In C, C++, Java the name `y` could refer to anything.
-In Go, `y` (or even `Y`) is always defined within the package.
-In Go, `x.Y` is clear: find `x` locally, `Y` belongs to it, and there is only one such `Y`.
-
-Immediate consequences for readability.
-
-* Back to imports
-
-Importing a package means reading a package's exported API.
-
-This export information is self-contained. For instance:
-
-- A imports B
-- B imports C
-- B exports contain references to C
-
-B's export data contains all necessary information about C. There is no need for a compiler to read the export data of C.
-
-This has huge consequences for build times!
-
-* Dependencies in C
-
-`.h` files are not self-contained.
-
-As a result, a compiler ends up reading core header files over and over again.
-
-`ifdef` still requires the preprocessor to read a lot of code.
-
-No wonder it takes a long time to compile...
-
-At Google scale: dependencies explode, are exponential, become almost non-computable.
-
-A large Google C++ build can read the same header file tens of thousands of times!
-
-# it is real work, too, teaching the compiler what a string is each time
-
-* Tools
-
-* A brief overview
-
-Two compilers: gc, gccgo
-
-Support for multiple platforms: x86 (32/64bit), ARM (32bit), Linux, BSD, OS X, ...
-
-Automatic formatting of source code: `gofmt`
-
-Automatic documentation extraction: `godoc`
-
-Automatic API adaption: `gofix`
-
-All (and more!) integrated into the `go` command.
-
-* Building a Go program
-
-A Go program can be compiled and linked without additional build information (`make` files, etc.).
-
-By convention, all files belonging to a package are found in the same directory.
-
-All depending packages are found by inspecting the import paths of the top-most (_main_) package.
-
-A single integrated tool takes care of compiling individual files or entire systems.
-
-* The go command
-
-Usage:
-
-	go command [arguments]
-
-Selected commands:
-
-	build       compile packages and dependencies
-	clean       remove object files
-	doc         run godoc on package sources
-	fix         run go tool fix on packages
-	fmt         run gofmt on package sources
-	get         download and install packages and dependencies
-	install     compile and install packages and dependencies
-	list        list packages
-	run         compile and run Go program
-	test        test packages
-	vet         run go tool vet on packages
-
-.link http://golang.org/cmd/go/
-
-* Break
-
-# After the break, we will discuss OOP and concurrency in Go.
-
-* Object-oriented programming
-
-* What is object-oriented programming?
-
-"Object-oriented programming (OOP) is a programming paradigm using _objects_ – usually instances of a class – consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction, encapsulation, messaging, modularity, polymorphism, and inheritance. Many modern programming languages now support forms of OOP, at least as an option."
-
-(Wikipedia)
-
-# Important:
-# Notion of _objects_
-# _Objects_ have _state_ (data fields), and _methods_ (for interactions)
-
-* OOP requires very little extra programming language support
-
-We only need
-
-- the notion of an _Object_,
-- a mechanism to interact with them (_Methods_),
-- and support for polymorphism (_Interfaces_).
-
-Claim: Data abstraction, encapsulation, and modularity are mechanisms
-in their own right, not OOP specific, and a modern language (OO or not)
-should have support for them independently.
-
-
-* Object-oriented programming in Go
-
-Methods without classes
-
-Interfaces without hierarchies
-
-Code reuse without inheritance
-
-Specifically:
-
-- Any _value_ can be an _object_
-- Any _type_ can play the role of a _class_
-- _Methods_ can be attached to any _type_
-- _Interfaces_ implement polymorphism.
-
-* Methods
-
-.play goforc/point.go
-
-* Methods can be attached to any type
-
-.play goforc/celsius.go
-
-* Interfaces
-
-	type Stringer interface {
-	     String() string
-	}
-
-	type Reader interface {
-	     Read(p []byte) (n int, err error)
-	}
-
-	type Writer interface {
-	     Write(p []byte) (n int, err error)
-	}
-
-	type Empty interface{}
-
-An interface defines a set of methods.
-A type that implements all methods of an interface is said to implement the interface.
-All types implement the empty interface interface{}.
-
-* Dynamic dispatch
-
-.play goforc/interface.go /START/,/STOP/
-
-A value (here: `corner`, `boiling`) of a type (`Point`, `Celsius`) that implements
-an interface (`Stringer`) can be assigned to a variable (`v`) of that interface type.
-
-* Composition and chaining
-
-Typically, interfaces are small (1-3 methods).
-
-Pervasive use of key interfaces in the standard library make it easy to chain APIs together.
-
-	package io
-	func Copy(dst Writer, src Reader) (int64, error)
-
-The io.Copy function copies by reading from any Reader and writing to any Writer.
-
-Interfaces are often introduced ad-hoc, and after the fact.
-
-There is no explicit hierarchy and thus no need to design one!
-
-* cat
-
-.code goforc/cat.go
-
-# An `os.File` implements the `Reader` interface;
-# `os.Stdout` implements the `Writer` interface.
-
-* Interfaces in practice
-
-Methods on any types and _ad_hoc_ interfaces make for a light-weight OO programming style.
-
-Go interfaces enable post-facto abstraction.
-# Existing code may not know about a new interface
-
-No explicit type hierarchies.
-# Coming up with the correct type hierarchy is hard
-# They are often wrong
-# They are difficult and time-consuming to change
-
-"Plug'n play" in a type-safe way.
-
-# There's much more but we won't have time for more detail.
-
-* Concurrency
-
-* What is concurrency?
-
-Concurrency is the composition of independently executing computations.
-
-Concurrency is a way to structure software, particularly as a way to write clean code that interacts well with the real world.
-
-It is not parallelism.
-
-* Concurrency is not parallelism
-
-Concurrency is not parallelism, although it enables parallelism.
-
-If you have only one processor, your program can still be concurrent  but it cannot be parallel.
-
-On the other hand, a well-written concurrent program might run efficiently in parallel on a multiprocessor. That property could be important...
-
-For more on that distinction, see the link below. Too much to discuss here.
-
-.link http://golang.org/s/concurrency-is-not-parallelism
-
-* A model for software construction
-
-Easy to understand.
-
-Easy to use.
-
-Easy to reason about.
-
-You don't need to be an expert!
-
-(Much nicer than dealing with the minutiae of parallelism (threads, semaphores, locks, barriers, etc.))
-
-There is a long history behind Go's concurrency features, going back to Hoare's CSP in 1978 and even Dijkstra's guarded commands (1975).
-
-* Basic Examples
-
-* A boring function
-
-We need an example to show the interesting properties of the concurrency primitives.
-
-To avoid distraction, we make it a boring example.
-
-.code goforc/example0.go /START1/,/STOP1/
-.play goforc/example0.go /START2/,/STOP2/
-
-* Ignoring it
-
-The `go` statement runs the function as usual, but doesn't make the caller wait.
-
-It launches a goroutine.
-
-The functionality is analogous to the & on the end of a shell command.
-
-.play goforc/example1.go /START/,/STOP/
-
-* Ignoring it a little less
-
-When main returns, the program exits and takes the function `f` down with it.
-
-We can hang around a little, and on the way show that both main and the launched goroutine are running.
-
-.play goforc/example2.go /START/,/STOP/
-
-* Goroutines
-
-What is a goroutine? It's an independently executing function, launched by a `go` statement.
-
-It has its own call stack, which grows and shrinks as required.
-
-It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines.
-
-It's not a thread.
-
-There might be only one thread in a program with thousands of goroutines.
-
-Instead, goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running.
-
-But if you think of it as a very cheap thread, you won't be far off.
-
-* Channels
-
-A channel in Go provides a connection between two goroutines, allowing them to communicate.
-
-.code goforc/channels.go /START1/,/STOP1/
-.code goforc/channels.go /START2/,/STOP2/
-.code goforc/channels.go /START3/,/STOP3/
-
-* Using channels
-
-A channel connects the `main` and `f` goroutines so they can communicate.
-
-.play goforc/communication1.go /START1/,/STOP1/
-.code goforc/communication1.go /START2/,/STOP2/
-
-* Synchronization
-
-When the main function executes `<–c`, it will wait for a value to be sent.
-
-Similarly, when the function `f` executes `c<–value`, it waits for a receiver to be ready.
-
-A sender and receiver must both be ready to play their part in the communication. Otherwise we wait until they are.
-
-Thus channels both communicate and synchronize.
-
-Channels can be unbuffered or buffered.
-
-* Using channels between many goroutines
-
-.play goforc/communication2.go /START1/,/STOP1/
-
-A single channel may be used to communicate between many (not just two) goroutines; many goroutines may communicate via one or multiple channels.
-
-This enables a rich variety of concurrency patterns.
-
-# There's enough material for several talks on this subject alone.
-
-* Elements of a work-stealing scheduler
-
-.code goforc/worker1.go /START2/,/STOP2/
-
-The `worker` uses two channels to communicate:
-- The `in` channel waits for some work order.
-- The `out` channel communicates the result.
-- As work load, a worker (very slowly) computes the list of prime factors for a given order.
-
-* A matching producer and consumer
-
-.code goforc/worker1.go /START3/,/STOP3/
-
-The `producer` produces and endless supply of work orders and sends them `out`.
-
-The `consumer` receives `n` results from the `in` channel and then terminates.
-
-* Putting it all together
-
-.play goforc/worker1.go /START1/,/STOP1/
-
-We use one worker to handle the entire work load.
-
-Because there is only one worker, we see the result coming back in order.
-
-This is running rather slow...
-
-* Using 10 workers
-
-.play goforc/worker2.go /START1/,/STOP1/
-
-A ready worker will read the next order from the `in` channel and start working on it. Another ready worker will proceed with the next order, and so forth.
-
-Because we have many workers and since different orders take different amounts of time to work on, we see the results coming back out-of-order.
-
-On a multi-core system, many workers may truly run in parallel.
-
-This is running much faster...
-
-* The Go approach
-
-Don't communicate by sharing memory, share memory by communicating.
-
-* There's much more...
-
-* Links
-
-Go Home Page:
-
-.link http://golang.org
-
-Go Tour (learn Go in your browser)
-
-.link http://tour.golang.org
-
-Package documentation:
-
-.link http://golang.org/pkg
-
-Articles galore:
-
-.link http://golang.org/doc
diff --git a/content/2012/goforc/adder.go b/content/2012/goforc/adder.go
deleted file mode 100644
index 1ebc71a..0000000
--- a/content/2012/goforc/adder.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-// START1 OMIT
-func adder(delta int) func(x int) int {
-	f := func(x int) int { // HL
-		return x + delta // HL
-	} // HL
-	return f
-}
-
-// STOP1 OMIT
-
-func main() {
-	// START2 OMIT
-	var inc = adder(1)
-	fmt.Println(inc(0))
-	fmt.Println(adder(-1)(10))
-	// STOP2 OMIT
-}
diff --git a/content/2012/goforc/cat.go b/content/2012/goforc/cat.go
deleted file mode 100644
index 3979df1..0000000
--- a/content/2012/goforc/cat.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"flag"
-	"io"
-	"os"
-)
-
-func main() {
-	flag.Parse()
-	for _, arg := range flag.Args() {
-		f, err := os.Open(arg)
-		if err != nil {
-			panic(err)
-		}
-		defer f.Close()
-		_, err = io.Copy(os.Stdout, f) // HL
-		if err != nil {
-			panic(err)
-		}
-	}
-}
diff --git a/content/2012/goforc/celsius.go b/content/2012/goforc/celsius.go
deleted file mode 100644
index ffb4572..0000000
--- a/content/2012/goforc/celsius.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-type Celsius float32
-type Fahrenheit float32
-
-func (t Celsius) String() string           { return fmt.Sprintf("%g°C", t) }
-func (t Fahrenheit) String() string        { return fmt.Sprintf("%g°F", t) }
-func (t Celsius) ToFahrenheit() Fahrenheit { return Fahrenheit(t*9/5 + 32) }
-
-func main() {
-	var t Celsius = 21
-	fmt.Println(t.String())
-	fmt.Println(t)
-	fmt.Println(t.ToFahrenheit())
-}
diff --git a/content/2012/goforc/channels.go b/content/2012/goforc/channels.go
deleted file mode 100644
index a10c9cb..0000000
--- a/content/2012/goforc/channels.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-func main() {
-	var value int
-
-	// START1 OMIT
-	// Declaring and initializing.
-	var c chan int
-	c = make(chan int)
-	// or
-	c := make(chan int) // HL
-	// STOP1 OMIT
-
-	// START2 OMIT
-	// Sending on a channel.
-	c <- 1 // HL
-	// STOP2 OMIT
-
-	// START3 OMIT
-	// Receiving from a channel.
-	// The "arrow" indicates the direction of data flow.
-	value = <-c // HL
-	// STOP3 OMIT
-
-	_ = value
-}
diff --git a/content/2012/goforc/communication1.go b/content/2012/goforc/communication1.go
deleted file mode 100644
index 4825227..0000000
--- a/content/2012/goforc/communication1.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := make(chan string)
-	go f("three", 300*time.Millisecond, c)
-	for i := 0; i < 10; i++ {
-		fmt.Println("Received", <-c) // Receive expression is just a value. // HL
-	}
-	fmt.Println("Done.")
-}
-
-// STOP1 OMIT
-
-// START2 OMIT
-func f(msg string, delay time.Duration, c chan string) {
-	for i := 0; ; i++ {
-		c <- fmt.Sprintf("%s %d", msg, i) // Any suitable value can be sent. // HL
-		time.Sleep(delay)
-	}
-}
-
-// STOP2 OMIT
diff --git a/content/2012/goforc/communication2.go b/content/2012/goforc/communication2.go
deleted file mode 100644
index 20c815b..0000000
--- a/content/2012/goforc/communication2.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	c := make(chan string)
-	go f("three", 300*time.Millisecond, c) // HL
-	go f("six", 600*time.Millisecond, c)   // HL
-	go f("nine", 900*time.Millisecond, c)  // HL
-	for i := 0; i < 10; i++ {
-		fmt.Println("Received", <-c)
-	}
-	fmt.Println("Done.")
-}
-
-// STOP1 OMIT
-
-// START2 OMIT
-func f(msg string, delay time.Duration, c chan string) {
-	for i := 0; ; i++ {
-		c <- fmt.Sprintf("%s %d", msg, i) // Any suitable value can be sent. // HL
-		time.Sleep(delay)
-	}
-}
-
-// STOP2 OMIT
diff --git a/content/2012/goforc/consts.go b/content/2012/goforc/consts.go
deleted file mode 100644
index 33cf221..0000000
--- a/content/2012/goforc/consts.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-// START1 OMIT
-const (
-	MaxUInt = 1<<64 - 1
-	Pi      = 3.14159265358979323846264338327950288419716939937510582097494459
-	Pi2     = Pi * Pi
-	Delta   = 2.0
-)
-
-// STOP1 OMIT
-
-func main() {
-	// START2 OMIT
-	var x uint64 = MaxUInt
-	var pi2 float32 = Pi2
-	var delta int = Delta
-	// STOP2 OMIT
-	fmt.Println("x =", x)
-	fmt.Println("pi2 =", pi2)
-	fmt.Println("delta =", delta)
-}
diff --git a/content/2012/goforc/decls.go b/content/2012/goforc/decls.go
deleted file mode 100644
index b49dd4f..0000000
--- a/content/2012/goforc/decls.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-// START OMIT
-import "fmt"
-
-const digits = "0123456789abcdef"
-
-type Point struct {
-	x, y int
-	tag  string
-}
-
-var s [32]byte
-
-var msgs = []string{"Hello, 世界", "Ciao, Mondo"}
-
-func itoa(x, base int) string
-
-// STOP OMIT
-
-func main() {
-	fmt.Println() // use fmt
-}
diff --git a/content/2012/goforc/example0.go b/content/2012/goforc/example0.go
deleted file mode 100644
index fa1d0f7..0000000
--- a/content/2012/goforc/example0.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-// START1 OMIT
-func main() {
-	f("Hello, World", 500*time.Millisecond)
-}
-
-// STOP1 OMIT
-
-// START2 OMIT
-func f(msg string, delay time.Duration) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(delay)
-	}
-}
-
-// STOP2 OMIT
diff --git a/content/2012/goforc/example1.go b/content/2012/goforc/example1.go
deleted file mode 100644
index ced6d0e..0000000
--- a/content/2012/goforc/example1.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-// START OMIT
-func main() {
-	go f("three", 300*time.Millisecond)
-	go f("six", 600*time.Millisecond)
-	go f("nine", 900*time.Millisecond)
-}
-
-// STOP OMIT
-
-func f(msg string, delay time.Duration) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(delay)
-	}
-}
diff --git a/content/2012/goforc/example2.go b/content/2012/goforc/example2.go
deleted file mode 100644
index 3b8504f..0000000
--- a/content/2012/goforc/example2.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-// START OMIT
-func main() {
-	go f("three", 300*time.Millisecond)
-	go f("six", 600*time.Millisecond)
-	go f("nine", 900*time.Millisecond)
-	time.Sleep(3 * time.Second)
-	fmt.Println("Done.")
-}
-
-// STOP OMIT
-
-func f(msg string, delay time.Duration) {
-	for i := 0; ; i++ {
-		fmt.Println(msg, i)
-		time.Sleep(delay)
-	}
-}
diff --git a/content/2012/goforc/forloop.go b/content/2012/goforc/forloop.go
deleted file mode 100644
index 12975c4..0000000
--- a/content/2012/goforc/forloop.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-var primes = [...]int{2, 3, 5, 7, 11, 13, 17, 19}
-
-func _() {
-	// START1 OMIT
-	for i := 0; i < len(primes); i++ {
-		fmt.Println(i, primes[i])
-	}
-	// STOP1 OMIT
-
-	// START2 OMIT
-	var sum int
-	for _, x := range primes {
-		sum += x
-	}
-	// STOP2 OMIT
-}
-
-func main() {
-	// START3 OMIT
-	for i, x := range primes {
-		fmt.Println(i, x)
-	}
-	// STOP3 OMIT
-}
diff --git a/content/2012/goforc/hello.go b/content/2012/goforc/hello.go
deleted file mode 100644
index e4f48ab..0000000
--- a/content/2012/goforc/hello.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hello, 世界")
-}
diff --git a/content/2012/goforc/interface.go b/content/2012/goforc/interface.go
deleted file mode 100644
index 02bc0f6..0000000
--- a/content/2012/goforc/interface.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-type Point struct{ x, y int }
-
-func (p Point) String() string { return fmt.Sprintf("Point{%d, %d}", p.x, p.y) }
-
-type Celsius float32
-type Fahrenheit float32
-
-func (t Celsius) String() string           { return fmt.Sprintf("%g°C", t) }
-func (t Fahrenheit) String() string        { return fmt.Sprintf("%g°F", t) }
-func (t Celsius) ToFahrenheit() Fahrenheit { return Fahrenheit(t*9/5 + 32) }
-
-func main() {
-	// START OMIT
-	type Stringer interface {
-		String() string
-	}
-
-	var v Stringer // HL
-	var corner = Point{1, 1}
-	var boiling = Celsius(100)
-
-	v = corner
-	fmt.Println(v.String()) // dynamic dispatch
-	fmt.Println(v)
-
-	v = boiling.ToFahrenheit()
-	fmt.Println(v.String()) // dynamic dispatch
-	fmt.Println(v)
-	// STOP OMIT
-}
diff --git a/content/2012/goforc/point.go b/content/2012/goforc/point.go
deleted file mode 100644
index 2973d77..0000000
--- a/content/2012/goforc/point.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-type Point struct{ x, y int }
-
-func PointToString(p Point) string {
-	return fmt.Sprintf("Point{%d, %d}", p.x, p.y)
-}
-
-func (p Point) String() string { // HL
-	return fmt.Sprintf("Point{%d, %d}", p.x, p.y)
-}
-
-func main() {
-	p := Point{3, 5}
-	fmt.Println(PointToString(p)) // static dispatch // HL
-	fmt.Println(p.String())       // static dispatch // HL
-	fmt.Println(p)
-}
diff --git a/content/2012/goforc/stmts.go b/content/2012/goforc/stmts.go
deleted file mode 100644
index ae6a5c7..0000000
--- a/content/2012/goforc/stmts.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-const digits = "0123456789abcdef"
-
-func itoa(x, base int) string {
-	// START OMIT
-	t := x
-	switch {
-	case x == 0:
-		return "0"
-	case x < 0:
-		t = -x
-	}
-	var s [32]byte
-	i := len(s)
-	for t != 0 { // Look, ma, no ()'s!
-		i--
-		s[i] = digits[t%base]
-		t /= base
-	}
-	if x < 0 {
-		i--
-		s[i] = '-'
-	}
-	return string(s[i:])
-	// STOP OMIT
-}
-
-func main() {
-	fmt.Println(itoa(-42, 2))
-}
diff --git a/content/2012/goforc/vars.go b/content/2012/goforc/vars.go
deleted file mode 100644
index 101eaa7..0000000
--- a/content/2012/goforc/vars.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-// START1 OMIT
-var i int
-var p, q *Point
-var threshold float64 = 0.75
-
-// STOP1 OMIT
-
-// START2 OMIT
-var i = 42       // type of i is int
-var z = 1 + 2.3i // type of z is complex128
-// STOP2 OMIT
-
-func _() int {
-	i := 42 // type of i is int
-	return &i
-}
diff --git a/content/2012/goforc/worker1.go b/content/2012/goforc/worker1.go
deleted file mode 100644
index 585af16..0000000
--- a/content/2012/goforc/worker1.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-import "time"
-
-// START1 OMIT
-func main() {
-	start := time.Now()
-
-	in := make(chan int)    // Channel on which work orders are received.
-	out := make(chan []int) // Channel on which results are returned.
-	go producer(in)
-	go worker(in, out) // Launch one worker. // HL
-	consumer(out, 100)
-
-	fmt.Println(time.Since(start))
-}
-
-// STOP1 OMIT
-
-// START2 OMIT
-func worker(in chan int, out chan []int) {
-	for {
-		order := <-in           // Receive a work order. // HL
-		result := factor(order) // Do some work. // HL
-		out <- result           // Send the result back. // HL
-	}
-}
-
-// STOP2 OMIT
-
-// START3 OMIT
-func producer(out chan int) {
-	for order := 0; ; order++ {
-		out <- order // Produce a work order. // HL
-	}
-}
-
-func consumer(in chan []int, n int) {
-	for i := 0; i < n; i++ {
-		result := <-in // Consume a result. // HL
-		fmt.Println("Consumed", result)
-	}
-}
-
-// STOP3 OMIT
-
-// factor returns a list containing x and its prime factors.
-func factor(x int) (list []int) {
-	list = append(list, x)
-	for f := 2; x >= f; f++ {
-		for x%f == 0 {
-			x /= f
-			list = append(list, f)
-			// Slow down so we can see what happens.
-			time.Sleep(50 * time.Millisecond)
-		}
-	}
-	return
-}
diff --git a/content/2012/goforc/worker2.go b/content/2012/goforc/worker2.go
deleted file mode 100644
index f995e9b..0000000
--- a/content/2012/goforc/worker2.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-import "time"
-
-func main() {
-	start := time.Now()
-
-	// START1 OMIT
-	in := make(chan int)
-	out := make(chan []int)
-	go producer(in)
-	// Launch 10 workers. // HL
-	for i := 0; i < 10; i++ { // HL
-		go worker(in, out) // HL
-	} // HL
-	consumer(out, 100)
-	// STOP1 OMIT
-
-	fmt.Println(time.Since(start))
-}
-
-// START2 OMIT
-func worker(in chan int, out chan []int) {
-	for {
-		order := <-in           // Receive a work order. // HL
-		result := factor(order) // Do some work. // HL
-		out <- result           // Send the result back. // HL
-	}
-}
-
-// STOP2 OMIT
-
-// START3 OMIT
-func producer(out chan int) {
-	for order := 0; ; order++ {
-		out <- order // Produce a work order. // HL
-	}
-}
-
-func consumer(in chan []int, n int) {
-	for i := 0; i < n; i++ {
-		result := <-in // Consume a result. // HL
-		fmt.Println("Consumed", result)
-	}
-}
-
-// STOP3 OMIT
-
-// factor returns a list containing x and its prime factors.
-func factor(x int) (list []int) {
-	list = append(list, x)
-	for f := 2; x >= f; f++ {
-		for x%f == 0 {
-			x /= f
-			list = append(list, f)
-			// Slow down so we can see what happens.
-			time.Sleep(50 * time.Millisecond)
-		}
-	}
-	return
-}
diff --git a/content/2012/insidepresent.slide b/content/2012/insidepresent.slide
deleted file mode 100644
index 2e33886..0000000
--- a/content/2012/insidepresent.slide
+++ /dev/null
@@ -1,144 +0,0 @@
-Inside the "present" tool
-
-Andrew Gerrand
-Google
-@enneff
-adg@golang.org
-http://golang.org
-
-
-* The Playground API
-
-The API used by the Playground (and the Tour) is a simple HTTP POST request
-that returns a JSON-encoded response.
-
-Request:
-
-	POST /compile HTTP/1.1
-	Host:play.golang.org
-	Content-Length:113
-	Content-Type:application/x-www-form-urlencoded; charset=UTF-8
-	
-	body=package+main%0A%0Aimport+%22fmt%22%0A%0Afunc+main()+%7B%0A%09fmt.Println(%22Hello%2C+playground%22)%0A%7D%0A
-
-Response body:
-
-	{"compile_errors":"","output":"Hello, playground\n"}
-
-
-* Playground drawbacks
-
-The compile service has no concept of time. (Necessary to limit resource use.)
-
-The API reflects this; output is sent in one blob, not streamed.
-
-Even when running locally, the API is bad for demonstrating code that uses time.
-
-Rob needed to use time in his _Go_Concurrency_Patterns_ talk.
-
-
-* Enter WebSockets
-
-WebSockets are a bi-directional communication channel between a JavaScript program running in a web browser and a web server. They are part of HTML 5. 
-
-The `websocket` package in Go's `go.net` sub-repository provides a WebSocket client and server.
-
-I thought I could use WebSockets to stream program output to a running
-presentation.
-
-And thus the `present` tool was born.
-
-
-* Hello, WebSocket
-
-.code insidepresent/websocket.js
-.play insidepresent/websocket.go
-
-
-* Messages
-
-The client (browser) and server (present) communicate with JSON-encoded messages.
-
-.code insidepresent/socket.go /Message is/,/^}/
-
-Go's `encoding/json` format can convert these `Message` values to and from JSON.
-
-Go:
-
-	Message{Id: "0", Kind: "run", Body: `package main; func main() { print("hello"); }`}
-
-JSON:
-
-	{"Id":"0","Kind":"run","Body":"package main; func main() { print(\"hello\"); }"}
-
-
-* On the wire
-
-.play insidepresent/hello.go
-
-.html insidepresent/wire.html
-
-
-* Implementation
-
-* socketHandler (1/3)
-
-First, register the handler with the `net/http` package:
-
-	http.Handle("/socket", websocket.Handler(socketHandler))
-
-Implementation:
-
-.code insidepresent/socket.go /func socketHandler/,/errc/
-
-* socketHandler (2/3)
-
-.code insidepresent/socket.go /Decode messages/,/END/
-
-* socketHandler (3/3)
-
-.code insidepresent/socket-simple.go /Start and kill/,/^}/
-
-
-* Process
-
-.code insidepresent/socket.go /Process represents/,/^}/
-
-* StartProcess
-
-.code insidepresent/socket.go /StartProcess builds/,/^}/
-
-* Process.start (1/2)
-
-.code insidepresent/socket.go /start builds/,/END/
-
-* Process.start (2/2)
-
-.code insidepresent/socket.go /build x\.go/,/^}/
-
-* Process.cmd
-
-.code insidepresent/socket.go /cmd builds/,/^}/
-.code insidepresent/socket.go /messageWriter is/,/END/
-
-* Process.wait and Process.end
-
-.code insidepresent/socket.go /wait waits/,/^}/
-.code insidepresent/socket.go /end sends/,/^}/
-
-* Process.Kill
-
-.code insidepresent/socket.go /Kill stops/,/^}/
-
-
-* One more thing
-
-* Limiting output (1/2)
-
-.code insidepresent/socket.go /switch m\.Kind/,/^			}/
-
-* Limiting output (2/2)
-
-.code insidepresent/socket.go /limiter returns/,/^}/
-
-
diff --git a/content/2012/insidepresent/hello.go b/content/2012/insidepresent/hello.go
deleted file mode 100644
index b62da0a..0000000
--- a/content/2012/insidepresent/hello.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import ( "fmt"; "time" )
-
-func main() {
-	for {
-		fmt.Println("Hello, Gophers!")
-		time.Sleep(time.Second)
-	}
-}
diff --git a/content/2012/insidepresent/socket-simple.go b/content/2012/insidepresent/socket-simple.go
deleted file mode 100644
index 20d5dde..0000000
--- a/content/2012/insidepresent/socket-simple.go
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"log"
-	"net/http"
-	"os"
-	"os/exec"
-	"path/filepath"
-	"runtime"
-	"strconv"
-
-	"golang.org/x/net/websocket"
-)
-
-const socketPresent = true
-
-func HandleSocket(path string) {
-	http.Handle(path, websocket.Handler(socketHandler))
-}
-
-const msgLimit = 1000 // max number of messages to send per session
-
-var uniq = make(chan int) // a source of numbers for naming temporary files
-
-func init() {
-	go func() {
-		for i := 0; ; i++ {
-			uniq <- i
-		}
-	}()
-}
-
-// Message is the wire format for the websocket connection to the browser.
-// It is used for both sending output messages and receiving commands, as
-// distinguished by the Kind field.
-type Message struct {
-	Id   string // client-provided unique id for the process
-	Kind string // in: "run", "kill" out: "stdout", "stderr", "end"
-	Body string
-}
-
-// socketHandler handles the websocket connection for a given present session.
-// It handles transcoding Messages to and from JSON format, and starting
-// and killing Processes.
-func socketHandler(c *websocket.Conn) {
-	in, out := make(chan *Message), make(chan *Message)
-	errc := make(chan error, 1)
-
-	// Decode messages from client and send to the in channel.
-	go func() {
-		dec := json.NewDecoder(c)
-		for {
-			var m Message
-			if err := dec.Decode(&m); err != nil {
-				errc <- err
-				return
-			}
-			in <- &m
-		}
-	}()
-
-	// Receive messages from the out channel and encode to the client.
-	go func() {
-		enc := json.NewEncoder(c)
-		for m := range out {
-			if err := enc.Encode(m); err != nil {
-				errc <- err
-				return
-			}
-		}
-	}()
-	// END OMIT
-
-	// Start and kill Processes and handle errors.
-	proc := make(map[string]*Process)
-	for {
-		select {
-		case m := <-in:
-			switch m.Kind {
-			case "run":
-				proc[m.Id].Kill()
-				proc[m.Id] = StartProcess(m.Id, m.Body, out)
-			case "kill":
-				proc[m.Id].Kill()
-			}
-		case err := <-errc:
-			// A encode or decode has failed; bail.
-			log.Println(err)
-			// Shut down any running processes.
-			for _, p := range proc {
-				p.Kill()
-			}
-			return
-		}
-	}
-}
-
-// Process represents a running process.
-type Process struct {
-	id   string
-	out  chan<- *Message
-	done chan struct{} // closed when wait completes
-	run  *exec.Cmd
-}
-
-// StartProcess builds and runs the given program, sending its output
-// and end event as Messages on the provided channel.
-func StartProcess(id, body string, out chan<- *Message) *Process {
-	p := &Process{
-		id:   id,
-		out:  out,
-		done: make(chan struct{}),
-	}
-	cmd, err := p.start(body)
-	if err != nil {
-		p.end(err)
-		return nil
-	}
-	p.run = cmd
-	go p.wait(cmd)
-	return p
-}
-
-// Kill stops the process if it is running and waits for it to exit.
-func (p *Process) Kill() {
-	if p == nil {
-		return
-	}
-	if p.run != nil {
-		p.run.Process.Kill()
-	}
-	<-p.done
-}
-
-// start builds and starts the given program, sending its output to p.out,
-// and returns the associated *exec.Cmd.
-func (p *Process) start(body string) (*exec.Cmd, error) {
-	// x is the base name for .go and executable files
-	x := filepath.Join(tmpdir, "compile"+strconv.Itoa(<-uniq))
-	src := x + ".go"
-	bin := x
-	if runtime.GOOS == "windows" {
-		bin += ".exe"
-	}
-
-	// write body to x.go
-	defer os.Remove(src)
-	if err := ioutil.WriteFile(src, []byte(body), 0666); err != nil {
-		return nil, err
-	}
-	// END OMIT
-
-	// build x.go, creating x
-	dir, file := filepath.Split(src)
-	err := p.cmd(dir, "go", "build", "-o", bin, file).Run()
-	defer os.Remove(bin)
-	if err != nil {
-		return nil, err
-	}
-
-	// run x
-	cmd := p.cmd("", bin)
-	if err = cmd.Start(); err != nil {
-		return nil, err
-	}
-	return cmd, nil
-}
-
-// wait waits for the running process to complete and returns its error state.
-func (p *Process) wait(cmd *exec.Cmd) {
-	defer close(p.done)
-	p.end(cmd.Wait())
-}
-
-// end sends an "end" message to the client, containing the process id and the
-// given error value.
-func (p *Process) end(err error) {
-	m := &Message{Id: p.id, Kind: "end"}
-	if err != nil {
-		m.Body = err.Error()
-	}
-	p.out <- m
-}
-
-// cmd builds an *exec.Cmd that writes its standard output and error to the
-// Process' output channel.
-func (p *Process) cmd(dir string, args ...string) *exec.Cmd {
-	cmd := exec.Command(args[0], args[1:]...)
-	cmd.Dir = dir
-	cmd.Stdout = &messageWriter{p.id, "stdout", p.out}
-	cmd.Stderr = &messageWriter{p.id, "stderr", p.out}
-	return cmd
-}
-
-// messageWriter is an io.Writer that converts all writes to Message sends on
-// the out channel with the specified id and kind.
-type messageWriter struct {
-	id, kind string
-	out      chan<- *Message
-}
-
-func (w *messageWriter) Write(b []byte) (n int, err error) {
-	w.out <- &Message{Id: w.id, Kind: w.kind, Body: string(b)}
-	return len(b), nil
-}
-
-// END OMIT
-
-var tmpdir string
-
-func init() {
-	// find real path to temporary directory
-	var err error
-	tmpdir, err = filepath.EvalSymlinks(os.TempDir())
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/content/2012/insidepresent/socket.go b/content/2012/insidepresent/socket.go
deleted file mode 100644
index f53fa2a..0000000
--- a/content/2012/insidepresent/socket.go
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore,OMIT
-
-package main
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"log"
-	"net/http"
-	"os"
-	"os/exec"
-	"path/filepath"
-	"runtime"
-	"strconv"
-
-	"golang.org/x/net/websocket"
-)
-
-const socketPresent = true
-
-func HandleSocket(path string) {
-	http.Handle(path, websocket.Handler(socketHandler))
-}
-
-const msgLimit = 1000 // max number of messages to send per session
-
-var uniq = make(chan int) // a source of numbers for naming temporary files
-
-func init() {
-	go func() {
-		for i := 0; ; i++ {
-			uniq <- i
-		}
-	}()
-}
-
-// Message is the wire format for the websocket connection to the browser.
-// It is used for both sending output messages and receiving commands, as
-// distinguished by the Kind field.
-type Message struct {
-	Id   string // client-provided unique id for the process
-	Kind string // in: "run", "kill" out: "stdout", "stderr", "end"
-	Body string
-}
-
-// socketHandler handles the websocket connection for a given present session.
-// It handles transcoding Messages to and from JSON format, and starting
-// and killing Processes.
-func socketHandler(c *websocket.Conn) {
-	in, out := make(chan *Message), make(chan *Message)
-	errc := make(chan error, 1)
-
-	// Decode messages from client and send to the in channel.
-	go func() {
-		dec := json.NewDecoder(c)
-		for {
-			var m Message
-			if err := dec.Decode(&m); err != nil {
-				errc <- err
-				return
-			}
-			in <- &m
-		}
-	}()
-
-	// Receive messages from the out channel and encode to the client.
-	go func() {
-		enc := json.NewEncoder(c)
-		for m := range out {
-			if err := enc.Encode(m); err != nil {
-				errc <- err
-				return
-			}
-		}
-	}()
-	// END OMIT
-
-	// Start and kill Processes and handle errors.
-	proc := make(map[string]*Process)
-	for {
-		select {
-		case m := <-in:
-			switch m.Kind {
-			case "run":
-				proc[m.Id].Kill()
-				lOut := limiter(in, out)                      // HL
-				proc[m.Id] = StartProcess(m.Id, m.Body, lOut) // HL
-			case "kill":
-				proc[m.Id].Kill()
-			}
-		case err := <-errc:
-			// A encode or decode has failed; bail.
-			log.Println(err)
-			// Shut down any running processes.
-			for _, p := range proc {
-				p.Kill()
-			}
-			return
-		}
-	}
-}
-
-// Process represents a running process.
-type Process struct {
-	id   string
-	out  chan<- *Message
-	done chan struct{} // closed when wait completes
-	run  *exec.Cmd
-}
-
-// StartProcess builds and runs the given program, sending its output
-// and end event as Messages on the provided channel.
-func StartProcess(id, body string, out chan<- *Message) *Process {
-	p := &Process{
-		id:   id,
-		out:  out,
-		done: make(chan struct{}),
-	}
-	if err := p.start(body); err != nil {
-		p.end(err)
-		return nil
-	}
-	go p.wait()
-	return p
-}
-
-// Kill stops the process if it is running and waits for it to exit.
-func (p *Process) Kill() {
-	if p == nil {
-		return
-	}
-	p.run.Process.Kill()
-	<-p.done
-}
-
-// start builds and starts the given program, sends its output to p.out,
-// and stores the running *exec.Cmd in the run field.
-func (p *Process) start(body string) error {
-	// x is the base name for .go and executable files
-	x := filepath.Join(tmpdir, "compile"+strconv.Itoa(<-uniq))
-	src := x + ".go"
-	bin := x
-	if runtime.GOOS == "windows" {
-		bin += ".exe"
-	}
-
-	// write body to x.go
-	defer os.Remove(src)
-	if err := ioutil.WriteFile(src, []byte(body), 0666); err != nil {
-		return err
-	}
-	// END OMIT
-
-	// build x.go, creating x
-	dir, file := filepath.Split(src)
-	err := p.cmd(dir, "go", "build", "-o", bin, file).Run()
-	defer os.Remove(bin)
-	if err != nil {
-		return err
-	}
-
-	// run x
-	cmd := p.cmd("", bin)
-	if err = cmd.Start(); err != nil {
-		return err
-	}
-
-	p.run = cmd
-	return nil
-}
-
-// wait waits for the running process to complete
-// and sends its error state to the client.
-func (p *Process) wait() {
-	defer close(p.done)
-	p.end(p.run.Wait())
-}
-
-// end sends an "end" message to the client, containing the process id and the
-// given error value.
-func (p *Process) end(err error) {
-	m := &Message{Id: p.id, Kind: "end"}
-	if err != nil {
-		m.Body = err.Error()
-	}
-	p.out <- m
-}
-
-// cmd builds an *exec.Cmd that writes its standard output and error to the
-// Process' output channel.
-func (p *Process) cmd(dir string, args ...string) *exec.Cmd {
-	cmd := exec.Command(args[0], args[1:]...)
-	cmd.Dir = dir
-	cmd.Stdout = &messageWriter{p.id, "stdout", p.out}
-	cmd.Stderr = &messageWriter{p.id, "stderr", p.out}
-	return cmd
-}
-
-// messageWriter is an io.Writer that converts all writes to Message sends on
-// the out channel with the specified id and kind.
-type messageWriter struct {
-	id, kind string
-	out      chan<- *Message
-}
-
-func (w *messageWriter) Write(b []byte) (n int, err error) {
-	w.out <- &Message{Id: w.id, Kind: w.kind, Body: string(b)}
-	return len(b), nil
-}
-
-// END OMIT
-
-// limiter returns a channel that wraps dest. Messages sent to the channel are
-// sent to dest. After msgLimit Messages have been passed on, a "kill" Message
-// is sent to the kill channel, and only "end" messages are passed.
-func limiter(kill chan<- *Message, dest chan<- *Message) chan<- *Message {
-	ch := make(chan *Message)
-	go func() {
-		n := 0
-		for m := range ch {
-			switch {
-			case n < msgLimit || m.Kind == "end":
-				dest <- m
-				if m.Kind == "end" {
-					return
-				}
-			case n == msgLimit:
-				// Process produced too much output. Kill it.
-				kill <- &Message{Id: m.Id, Kind: "kill"}
-			}
-			n++
-		}
-	}()
-	return ch
-}
-
-var tmpdir string
-
-func init() {
-	// find real path to temporary directory
-	var err error
-	tmpdir, err = filepath.EvalSymlinks(os.TempDir())
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/content/2012/insidepresent/websocket.go b/content/2012/insidepresent/websocket.go
deleted file mode 100644
index 5b056ca..0000000
--- a/content/2012/insidepresent/websocket.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"golang.org/x/net/websocket"
-	"net/http"
-)
-
-func main() {
-	http.Handle("/", websocket.Handler(handler))
-	http.ListenAndServe("localhost:4000", nil)
-}
-
-func handler(c *websocket.Conn) {
-	var s string
-	fmt.Fscan(c, &s)
-	fmt.Println("Received:", s)
-	fmt.Fprint(c, "How do you do?")
-}
diff --git a/content/2012/insidepresent/websocket.js b/content/2012/insidepresent/websocket.js
deleted file mode 100644
index f9809d6..0000000
--- a/content/2012/insidepresent/websocket.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var sock = new WebSocket("ws://localhost:4000/");
-sock.onmessage = function(m) { console.log("Received:", m.data); }
-sock.send("Hello!\n")
diff --git a/content/2012/insidepresent/wire.html b/content/2012/insidepresent/wire.html
deleted file mode 100644
index 2a98a7d..0000000
--- a/content/2012/insidepresent/wire.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<style>
-#wire {
-	border: 1px solid #E0E0E0;
-	background: #F0F0F0;
-	height: 300px;
-	font-family: 'Droid Sans Mono', 'Courier New', monospace;
-	font-size: 18px;
-	line-height: 24px;
-	overflow: auto;
-}
-#wire div { margin-bottom: 10px; }
-#wire .send { color: #900; }
-#wire .recv { color: #009; }
-</style>
-<div id="wire"></div>
diff --git a/content/2012/simple.slide b/content/2012/simple.slide
deleted file mode 100644
index 3b49a7c..0000000
--- a/content/2012/simple.slide
+++ /dev/null
@@ -1,384 +0,0 @@
-Go: a simple programming environment
-
-9 Nov 2012
-
-# Go is a general-purpose language that bridges the gap between efficient
-# statically typed languages and productive dynamic language. But it’s not just
-# the language that makes Go special – Go has broad and consistent standard
-# libraries and powerful but simple tools.
-# 
-# This talk gives an introduction to Go, followed by a tour of some real
-# programs that demonstrate the power, scope, and simplicity of the Go
-# programming environment.
-
-Andrew Gerrand
-Google Inc.
-@enneff
-adg@golang.org
-http://golang.org
-
-* Video
-
-A video of this talk was recorded at Øredev in Malmö, Sweden in November 2012.
-
-.link http://vimeo.com/53221558 Watch the talk on Vimeo
-
-* Background
-
-* Why a new language?
-
-Motivated by our needs at Google.
-
-We need:
-
-- Efficiency
-- Safety
-- Concurrency
-- Scalability
-- Fast development cycle
-- No surprises
-- A cute mascot
-
-* Design
-
-"Consensus drove the design. Nothing went into the language until [Ken Thompson, Robert Griesemer, and myself] all agreed that it was right. Some features didn’t get resolved until after a year or more of discussion." - Rob Pike
-
-Go is:
-
-- Lightweight, avoids unnecessary repetition
-- Object Oriented, but not in the usual way
-- Concurrent, in a way that keeps you sane
-- Designed for working programmers
-
-* Go 1
-
-Released in March 2012
-
-A specification of the language and libraries that will be supported for years.
-
-The guarantee: code written for Go 1.0 will build and run with Go 1.x.
-
-Best thing we ever did.
-
-* The gopher
-
-.image simple/gopher.jpg
-
-* Hello, go
-
-.play simple/hello.go
-
-* Standard library
-
-* Packages
-
-Go code lives in packages.
-
-Packages contain type, function, variable, and constant declarations.
-
-Packages can be very small (package `errors` has just one declaration) or very large (package `net/http` has >100 declarations). Most are somewhere in between.
-
-Case determines visibility: `Foo` is exported, `foo` is not
-
-* io
-
-The `io` package provides fundamental I/O interfaces that are used throughout most Go code.
-
-The most ubiquitous are the `Reader` and `Writer` types, which describe streams of data.
-
-.code simple/io/io.go
-
-`Reader` and `Writer` implementations include files, sockets, (de)compressors, image and JSON codecs, and many more.
-
-* Chaining io.Readers
-
-.play simple/reader.go
-
-* net/http
-
-The `net/http` package implements an HTTP server and client.
-
-.play simple/hello-web.go
-
-* encoding/json
-
-The `encoding/json` package converts JSON-encoded data to and from native Go data structures.
-
-.play simple/json.go /const/,$
-
-* time
-
-The `time` package provides a representation of time and duration, and other time-related functions.
-
-.play simple/time.go /START/,/END/
-.play simple/time2.go /START/,/END/
-
-`time.Time` values also contain a `time.Location` (for display only):
-
-.play simple/time3.go /START/,/END/
-
-* flag
-
-The `flag` package provides a simple API for parsing command-line flags.
-
-.play simple/flag.go
-
-	$ flag -message 'Hold on...' -delay 5m
-
-* Tools
-
-* The go tool
-
-The `go` tool is the de facto standard for building and installing Go code.
-
-Compile and run a single-file program:
-
-	$ go run hello.go
-
-Build and install the package in the current directory (and its dependencies):
-
-	$ go install
-
-Build and install the `fmt` package (and its dependencies):
-
-	$ go install fmt
-
-This tool also acts as an interface for most of the Go tools.
-
-* Import paths
-
-The `go` tool is a "zero configuration" tool. No Makefiles or scripts. Just Go code.
-Your build schema and code are always in sync; they are one and the same.
-
-Package import paths mirror the code's location in the file system:
-
-  src/
-    github.com/nf/
-      gosynth/
-        main.go
-        note.go
-        osc.go
-      wav/
-        writer.go
-
-The `gosynth` program imports the `wav` package:
-
-  import "github.com/nf/wav"
-
-Installing `gosynth` will automatically install the `wav` package:
-
-  $ go install github.com/nf/gosynth
-
-* Remote dependencies
-
-The `go` tool also fetches Go code from remote repositories.
-
-Import paths can be URLs:
-
-	import "golang.org/x/net/websocket"
-
-To fetch, build and install a package:
-
-	$ go get code.google.com/p/go.net/websocket
-
-To fetch, build, and install `gosynth` and its dependencies:
-
-	$ go get github.com/nf/gosynth
-
-This simple design leads to other cool tools:
-
-.link http://go.pkgdoc.org
-
-* Godoc
-
-Godoc extracts documentation from Go code and presents it in a variety of forms.
-
-Comments need no special format, they just need to precede what they document.
-
-	// Split slices s into all substrings separated by sep and returns a slice of
-	// the substrings between those separators.
-	// If sep is empty, Split splits after each UTF-8 sequence.
-	// It is equivalent to SplitN with a count of -1.
-	func Split(s, sep string) []string {
-
-.image simple/split.png
-
-Documentation that lives with code is easy to keep up-to-date.
-
-* Gofmt
-
-The `gofmt` tool is a pretty-printer for Go source code.
-
-All Go code in the core is gofmt'd, as is ~70% of open source Go code.
-
-Ends boring formatting discussions.
-
-Improves readability. Improves writability.
-
-Saves a _huge_ amount of time.
-
-* Tests: writing
-
-The `go` tool and the `testing` package provide a lightweight test framework.
-
-.code simple/test/string_test.go /func TestIndex/,/^}/
-
-* Tests: running
-
-The go tool runs tests.
-
-	$ go test
-	PASS
-
-	$ go test -v
-	=== RUN TestIndex
-	--- PASS: TestIndex (0.00 seconds)
-	PASS
-
-To run the tests for all my projects:
-
-	$ go test github.com/nf/...
-
-* Tests: benchmarks
-
-The `testing` package also supports benchmarks.
-	
-A sample benchmark function:
-
-.code simple/test/string_test.go /func BenchmarkIndex/,/^}/
- 
-The benchmark package will vary `b.N` until the benchmark function lasts long enough to be timed reliably.
-
-	$ go test -test.bench=Index
-	PASS
-	BenchmarkIndex	50000000	        37.3 ns/op
-
-* Tests: doc examples
-
-The `testing` package also supports testable examples.
-
-.code simple/test/string_test.go /func ExampleIndex/,/^}/
-
-Examples and built and run as part of the normal test suite:
-
-	$ go test -v
-	=== RUN: ExampleIndex
-	--- PASS: ExampleIndex (0.00 seconds)
-	PASS
-
-The example is displayed in `godoc` alongside the thing it demonstrates:
-
-.link http://golang.org/pkg/strings/#Index
-
-* And there's more
-
-- `vet`: checks code for common programmer mistakes
-- `pprof`: CPU and memory profiling
-- `fix`: automatically migrate code as APIs change
-- GDB support
-- Editor support: Vim, Emacs, Eclipse, Sublime Text
-
-* An example
-
-* Webfront
-
-`Webfront` is an HTTP server and reverse proxy.
-
-It reads a JSON-formatted rule file like this:
-
-.code simple/webfront/main.go /^\[/,/\]/
-
-For all requests to the host `example.com` (or any name ending in `".example.com"`) it serves files from the `/var/www` directory.
-
-For requests to `example.org`, it forwards the request to the HTTP server listening on localhost port 8080.
-
-* The Rule type
-
-A `Rule` value specifies what to do for a request to a specific host.
-
-.code simple/webfront/main.go /Rule represents/,/^}/
-
-It corresponds directly with the entries in the JSON configuration file.
-
-.code simple/webfront/main.go /^\[/,/\]/
-
-* Rule methods
-
-.code simple/webfront/main.go /Match returns/,/^}/
-.code simple/webfront/main.go /Handler returns/,/^}/
-
-* The Server type
-
-The `Server` type is responsible for loading (and refreshing) the rules from the rule file and serving HTTP requests with the appropriate handler.
-
-.code simple/webfront/main.go /Server implements/,/^}/
-.code simple/webfront/main.go /ServeHTTP matches/,/^}/
-
-* The handler method
-
-.code simple/webfront/main.go /handler returns/,/^}/
-
-* Parsing rules
-
-The `parseRules` function uses the `encoding/json` package to read the rule file into a Go data structure.
-
-.code simple/webfront/main.go /parseRules reads/,/^}/
-
-* The loadRules method
-
-.code simple/webfront/main.go /loadRules tests/,/^}/
-
-* Constructing the server
-
-.code simple/webfront/main.go /NewServer constructs/,/^}/
-
-This constructor function launches a goroutine running the `refreshRules` method.
-
-* Refreshing the rules
-
-.code simple/webfront/main.go /refreshRules polls/,/^}/
-
-* Bringing it all together
-
-The main function parses command-line flags, constructs a `Server`, and launches an HTTP server that serves all requests with the `Server`.
-
-.code simple/webfront/main.go /^var/,/^}/
-
-* Demo
-
-* Testing (1/3)
-
-The `Server` integration test uses the `httptest` package to construct a dummy HTTP server, synthesizes a set of rules, and constructs a `Server` instance that uses those rules.
-
-.code simple/webfront/server_test.go /^func testHandler/,/STOP/
-
-* Testing (2/3)
-
-Each test case in the table specifies a request URL and the expected response code and body.
-
-.code simple/webfront/server_test.go /TESTS START/,/STOP/
-
-* Testing (3/3)
-
-For each test case, construct an `http.Request` for the url and an `httptest.ResponseRecorder` to capture the response, and pass them to the `Server.ServeHTTP` method. Then check that the response matches the test case.
-
-.code simple/webfront/server_test.go /RANGE START/,/^}/
-
-* Demo
-
-* Conclusions
-
-* Further reading
-
-All about Go:
-
-.link http://golang.org
-
-The slides for this talk:
-
-.link http://talks.golang.org/2012/simple.slide
-
-webfront:
-
-.link https://github.com/nf/webfront
-
diff --git a/content/2012/simple/flag.go b/content/2012/simple/flag.go
deleted file mode 100644
index 2606af3..0000000
--- a/content/2012/simple/flag.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"time"
-)
-
-var (
-	message = flag.String("message", "Hello!", "what to say")
-	delay   = flag.Duration("delay", 2*time.Second, "how long to wait")
-)
-
-func main() {
-	flag.Parse()
-	fmt.Println(*message)
-	time.Sleep(*delay)
-}
diff --git a/content/2012/simple/gopher.jpg b/content/2012/simple/gopher.jpg
deleted file mode 100644
index 0e886e4..0000000
--- a/content/2012/simple/gopher.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/simple/hello-web.go b/content/2012/simple/hello-web.go
deleted file mode 100644
index 05d1439..0000000
--- a/content/2012/simple/hello-web.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-)
-
-type Greeting string
-
-func (g Greeting) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	fmt.Fprint(w, g)
-}
-
-func main() {
-	err := http.ListenAndServe("localhost:4000", Greeting("Hello, go"))
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/content/2012/simple/hello.go b/content/2012/simple/hello.go
deleted file mode 100644
index 0757c53..0000000
--- a/content/2012/simple/hello.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hello, go")
-}
diff --git a/content/2012/simple/io/io.go b/content/2012/simple/io/io.go
deleted file mode 100644
index d0d975a..0000000
--- a/content/2012/simple/io/io.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// +build ignore,OMIT
-
-package io
-
-type Writer interface {
-	Write(p []byte) (n int, err error)
-}
-
-type Reader interface {
-	Read(p []byte) (n int, err error)
-}
diff --git a/content/2012/simple/json.go b/content/2012/simple/json.go
deleted file mode 100644
index aa91a92..0000000
--- a/content/2012/simple/json.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"encoding/json"
-	"fmt"
-	"strings"
-)
-
-const blob = `[
-	{"Title":"Øredev", "URL":"http://oredev.org"},
-	{"Title":"Strange Loop", "URL":"http://thestrangeloop.com"}
-]`
-
-type Item struct {
-	Title string
-	URL   string
-}
-
-func main() {
-	var items []*Item
-	json.NewDecoder(strings.NewReader(blob)).Decode(&items)
-	for _, item := range items {
-		fmt.Printf("Title: %v URL: %v\n", item.Title, item.URL)
-	}
-}
diff --git a/content/2012/simple/reader.go b/content/2012/simple/reader.go
deleted file mode 100644
index 1aa4415..0000000
--- a/content/2012/simple/reader.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"compress/gzip"
-	"encoding/base64"
-	"io"
-	"os"
-	"strings"
-)
-
-func main() {
-	var r io.Reader
-	r = strings.NewReader(data)
-	r = base64.NewDecoder(base64.StdEncoding, r)
-	r, _ = gzip.NewReader(r)
-	io.Copy(os.Stdout, r)
-}
-
-const data = `
-H4sIAAAJbogA/1SOO5KDQAxE8zlFZ5tQXGCjjfYIjoURoPKgcY0E57f4VZlQXf2e+r8yOYbMZJhoZWRxz3wkCVjeReETS0VHz5fBCzpxxg/PbfrT/gacCjbjeiRNOChaVkA9RAdR8eVEw4vxa0Dcs3Fe2ZqowpeqG79L995l3VaMBUV/02OS+B6kMWikwG51c8n5GnEPr11F2/QJAAD//z9IppsHAQAA
-`
diff --git a/content/2012/simple/split.png b/content/2012/simple/split.png
deleted file mode 100644
index 5140229..0000000
--- a/content/2012/simple/split.png
+++ /dev/null
Binary files differ
diff --git a/content/2012/simple/test.go b/content/2012/simple/test.go
deleted file mode 100644
index 1e67361..0000000
--- a/content/2012/simple/test.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import "strings"
-
-import "testing"
-
-func TestToUpper(t *testing.T) {
-	in := "loud noises"
-	want := "LOUD NOISES"
-	got := strings.ToUpper(in)
-	if got != want {
-		t.Errorf("ToUpper(%v) = %v, want %v", in, got, want)
-	}
-}
-
-func TestContains(t *testing.T) {
-	var tests = []struct {
-		str, substr string
-		expected    bool
-	}{
-		{"abc", "bc", true},
-		{"abc", "bcd", false},
-		{"abc", "", true},
-		{"", "a", false},
-	}
-	for _, ct := range tests {
-		if strings.Contains(ct.str, ct.substr) != ct.expected {
-			t.Errorf("Contains(%s, %s) = %v, want %v",
-				ct.str, ct.substr, !ct.expected, ct.expected)
-		}
-	}
-}
diff --git a/content/2012/simple/test/string_test.go b/content/2012/simple/test/string_test.go
deleted file mode 100644
index a65ff9d..0000000
--- a/content/2012/simple/test/string_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build ignore,OMIT
-
-package string_test
-
-import (
-	"fmt"
-	"strings"
-	"testing"
-)
-
-func TestIndex(t *testing.T) {
-	var tests = []struct {
-		s   string
-		sep string
-		out int
-	}{
-		{"", "", 0},
-		{"", "a", -1},
-		{"fo", "foo", -1},
-		{"foo", "foo", 0},
-		{"oofofoofooo", "f", 2},
-		// etc
-	}
-	for _, test := range tests {
-		actual := strings.Index(test.s, test.sep)
-		if actual != test.out {
-			t.Errorf("Index(%q,%q) = %v; want %v", test.s, test.sep, actual, test.out)
-		}
-	}
-}
-
-func BenchmarkIndex(b *testing.B) {
-	const s = "some_text=some☺value"
-	for i := 0; i < b.N; i++ {
-		strings.Index(s, "v")
-	}
-}
-
-func ExampleIndex() {
-	fmt.Println(strings.Index("chicken", "ken"))
-	fmt.Println(strings.Index("chicken", "dmr"))
-	// Output:
-	// 4
-	// -1
-}
diff --git a/content/2012/simple/time.go b/content/2012/simple/time.go
deleted file mode 100644
index c73963f..0000000
--- a/content/2012/simple/time.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	// START OMIT
-	if time.Now().Hour() < 12 {
-		fmt.Println("Good morning.")
-	} else {
-		fmt.Println("Good afternoon (or evening).")
-	}
-	// END OMIT
-}
diff --git a/content/2012/simple/time2.go b/content/2012/simple/time2.go
deleted file mode 100644
index bd7273c..0000000
--- a/content/2012/simple/time2.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	// START OMIT
-	birthday, _ := time.Parse("Jan 2 2006", "Nov 10 2009") // time.Time
-	age := time.Since(birthday)                            // time.Duration
-	fmt.Printf("Go is %d days old\n", age/(time.Hour*24))
-	// END OMIT
-}
diff --git a/content/2012/simple/time3.go b/content/2012/simple/time3.go
deleted file mode 100644
index d0e1ba3..0000000
--- a/content/2012/simple/time3.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	// START OMIT
-	t := time.Now()
-	fmt.Println(t.In(time.UTC))
-	home, _ := time.LoadLocation("Australia/Sydney")
-	fmt.Println(t.In(home))
-	// END OMIT
-}
diff --git a/content/2012/simple/webfront/main.go b/content/2012/simple/webfront/main.go
deleted file mode 100644
index bf28dec..0000000
--- a/content/2012/simple/webfront/main.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// +build ignore,OMIT
-
-// This is a somewhat cut back version of webfront, available at
-// http://github.com/nf/webfront
-
-/*
-Copyright 2011 Google Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/*
-webfront is an HTTP server and reverse proxy.
-
-It reads a JSON-formatted rule file like this:
-
-[
-	{"Host": "example.com", "Serve": "/var/www"},
-	{"Host": "example.org", "Forward": "localhost:8080"}
-]
-
-For all requests to the host example.com (or any name ending in
-".example.com") it serves files from the /var/www directory.
-
-For requests to example.org, it forwards the request to the HTTP
-server listening on localhost port 8080.
-
-Usage of webfront:
-  -http=":80": HTTP listen address
-  -poll=10s: file poll interval
-  -rules="": rule definition file
-
-webfront was written by Andrew Gerrand <adg@golang.org>
-*/
-package main
-
-import (
-	"encoding/json"
-	"flag"
-	"fmt"
-	"log"
-	"net/http"
-	"net/http/httputil"
-	"os"
-	"strings"
-	"sync"
-	"time"
-)
-
-var (
-	httpAddr     = flag.String("http", ":80", "HTTP listen address")
-	ruleFile     = flag.String("rules", "", "rule definition file")
-	pollInterval = flag.Duration("poll", time.Second*10, "file poll interval")
-)
-
-func main() {
-	flag.Parse()
-
-	s, err := NewServer(*ruleFile, *pollInterval)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	err = http.ListenAndServe(*httpAddr, s)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-// Server implements an http.Handler that acts as either a reverse proxy or
-// a simple file server, as determined by a rule set.
-type Server struct {
-	mu    sync.RWMutex // guards the fields below
-	mtime time.Time    // when the rule file was last modified
-	rules []*Rule
-}
-
-// Rule represents a rule in a configuration file.
-type Rule struct {
-	Host    string // to match against request Host header
-	Forward string // non-empty if reverse proxy
-	Serve   string // non-empty if file server
-}
-
-// Match returns true if the Rule matches the given Request.
-func (r *Rule) Match(req *http.Request) bool {
-	return req.Host == r.Host || strings.HasSuffix(req.Host, "."+r.Host)
-}
-
-// Handler returns the appropriate Handler for the Rule.
-func (r *Rule) Handler() http.Handler {
-	if h := r.Forward; h != "" {
-		return &httputil.ReverseProxy{
-			Director: func(req *http.Request) {
-				req.URL.Scheme = "http"
-				req.URL.Host = h
-			},
-		}
-	}
-	if d := r.Serve; d != "" {
-		return http.FileServer(http.Dir(d))
-	}
-	return nil
-}
-
-// NewServer constructs a Server that reads rules from file with a period
-// specified by poll.
-func NewServer(file string, poll time.Duration) (*Server, error) {
-	s := new(Server)
-	if err := s.loadRules(file); err != nil {
-		return nil, err
-	}
-	go s.refreshRules(file, poll)
-	return s, nil
-}
-
-// ServeHTTP matches the Request with a Rule and, if found, serves the
-// request with the Rule's handler.
-func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	if h := s.handler(r); h != nil {
-		h.ServeHTTP(w, r)
-		return
-	}
-	http.Error(w, "Not found.", http.StatusNotFound)
-}
-
-// handler returns the appropriate Handler for the given Request,
-// or nil if none found.
-func (s *Server) handler(req *http.Request) http.Handler {
-	s.mu.RLock()
-	defer s.mu.RUnlock()
-	for _, r := range s.rules {
-		if r.Match(req) {
-			return r.Handler()
-		}
-	}
-	return nil
-}
-
-// refreshRules polls file periodically and refreshes the Server's rule
-// set if the file has been modified.
-func (s *Server) refreshRules(file string, poll time.Duration) {
-	for {
-		if err := s.loadRules(file); err != nil {
-			log.Println(err)
-		}
-		time.Sleep(poll)
-	}
-}
-
-// loadRules tests whether file has been modified
-// and, if so, loads the rule set from file.
-func (s *Server) loadRules(file string) error {
-	fi, err := os.Stat(file)
-	if err != nil {
-		return err
-	}
-	mtime := fi.ModTime()
-	if mtime.Before(s.mtime) && s.rules != nil {
-		return nil // no change
-	}
-	rules, err := parseRules(file)
-	if err != nil {
-		return fmt.Errorf("parsing %s: %v", file, err)
-	}
-	s.mu.Lock()
-	s.mtime = mtime
-	s.rules = rules
-	s.mu.Unlock()
-	return nil
-}
-
-// parseRules reads rule definitions from file returns the resultant Rules.
-func parseRules(file string) ([]*Rule, error) {
-	f, err := os.Open(file)
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	var rules []*Rule
-	err = json.NewDecoder(f).Decode(&rules)
-	if err != nil {
-		return nil, err
-	}
-	return rules, nil
-}
diff --git a/content/2012/simple/webfront/server_test.go b/content/2012/simple/webfront/server_test.go
deleted file mode 100644
index 5fe9a78..0000000
--- a/content/2012/simple/webfront/server_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// +build ignore,OMIT
-
-/*
-Copyright 2011 Google Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"bytes"
-	"encoding/json"
-	"io/ioutil"
-	"net/http"
-	"net/http/httptest"
-	"os"
-	"testing"
-	"time"
-)
-
-func testHandler(w http.ResponseWriter, r *http.Request) {
-	w.Write([]byte("OK"))
-}
-
-func TestServer(t *testing.T) {
-	dummy := httptest.NewServer(http.HandlerFunc(testHandler))
-	defer dummy.Close()
-
-	ruleFile := writeRules([]*Rule{
-		{Host: "example.com", Forward: dummy.Listener.Addr().String()},
-		{Host: "example.org", Serve: "testdata"},
-	})
-	defer os.Remove(ruleFile)
-
-	s, err := NewServer(ruleFile, time.Hour)
-	if err != nil {
-		t.Fatal(err)
-	}
-	// continued next slide
-	// STOP OMIT
-
-	// TESTS START OMIT
-	// continued from previous slide
-
-	var tests = []struct {
-		url  string
-		code int
-		body string
-	}{
-		{"http://example.com/", 200, "OK"},
-		{"http://foo.example.com/", 200, "OK"},
-		{"http://example.org/", 200, "contents of index.html\n"},
-		{"http://example.net/", 404, "Not found.\n"},
-		{"http://fooexample.com/", 404, "Not found.\n"},
-	}
-
-	// continued next slide
-	// STOP OMIT
-
-	// RANGE START OMIT
-	// continued from previous slide
-
-	for _, test := range tests {
-		req, _ := http.NewRequest("GET", test.url, nil)
-		rw := httptest.NewRecorder()
-		rw.Body = new(bytes.Buffer)
-		s.ServeHTTP(rw, req)
-		if g, w := rw.Code, test.code; g != w {
-			t.Errorf("%s: code = %d, want %d", test.url, g, w)
-		}
-		if g, w := rw.Body.String(), test.body; g != w {
-			t.Errorf("%s: body = %q, want %q", test.url, g, w)
-		}
-	}
-}
-
-func writeRules(rules []*Rule) (name string) {
-	f, err := ioutil.TempFile("", "webfront-rules")
-	if err != nil {
-		panic(err)
-	}
-	defer f.Close()
-	err = json.NewEncoder(f).Encode(rules)
-	if err != nil {
-		panic(err)
-	}
-	return f.Name()
-}
diff --git a/content/2012/simple/webfront/testdata/index.html b/content/2012/simple/webfront/testdata/index.html
deleted file mode 100644
index 583e54d..0000000
--- a/content/2012/simple/webfront/testdata/index.html
+++ /dev/null
@@ -1 +0,0 @@
-contents of index.html
diff --git a/content/2012/splash.article b/content/2012/splash.article
deleted file mode 100644
index 39b9104..0000000
--- a/content/2012/splash.article
+++ /dev/null
@@ -1,1180 +0,0 @@
-Go at Google: Language Design in the Service of Software Engineering
-
-Rob Pike
-Google, Inc.
-@rob_pike
-http://golang.org/s/plusrob
-http://golang.org
-
-* Abstract
-
-(This is a modified version of the keynote talk given by Rob Pike
-at the SPLASH 2012 conference in Tucson, Arizona, on October 25, 2012.)
-
-The Go programming language was conceived in late 2007 as an answer to
-some of the problems we were seeing developing software infrastructure
-at Google.
-The computing landscape today is almost unrelated to the environment
-in which the languages being used, mostly C++, Java, and Python, had
-been created.
-The problems introduced by multicore processors, networked systems,
-massive computation clusters, and the web programming model were being
-worked around rather than addressed head-on.
-Moreover, the scale has changed: today's server programs comprise tens
-of millions of lines of code, are worked on by hundreds or even
-thousands of programmers, and are updated literally every day.
-To make matters worse, build times, even on large compilation
-clusters, have stretched to many minutes, even hours.
-
-Go was designed and developed to make working in this environment more
-productive.
-Besides its better-known aspects such as built-in concurrency and
-garbage collection, Go's design considerations include rigorous
-dependency management, the adaptability of software architecture as
-systems grow, and robustness across the boundaries between components.
-
-This article explains how these issues were addressed while building
-an efficient, compiled programming language that feels lightweight and
-pleasant.
-Examples and explanations will be taken from the real-world problems
-faced at Google.
-
-* Introduction
-
-Go is a compiled, concurrent, garbage-collected, statically typed language
-developed at Google.
-It is an open source project: Google
-imports the public repository rather than the other way around.
-
-Go is efficient, scalable, and productive. Some programmers find it fun
-to work in; others find it unimaginative, even boring.
-In this article we
-will explain why those are not contradictory positions.
-Go was designed to address the problems faced in software development
-at Google, which led to a language that is not a breakthrough research language
-but is nonetheless an excellent tool for engineering large software projects.
-
-* Go at Google
-
-Go is a programming language designed by Google to help solve Google's problems, and Google has big problems.
-
-The hardware is big and the software is big.
-There are many millions of lines of software, with servers mostly in C++
-and lots of Java and Python for the other pieces.
-Thousands of engineers work on the code,
-at the "head" of a single tree comprising all the software,
-so from day to day there are significant changes to all levels of the tree.
-A large
-[[http://google-engtools.blogspot.com/2011/06/build-in-cloud-accessing-source-code.html][custom-designed distributed build system]]
-makes development at this scale feasible, but it's still big.
-
-And of course, all this software runs on zillions of machines, which are treated as a modest number of independent, networked compute clusters.
-
-.image splash/datacenter.jpg
-
-In short, development at Google is big, can be slow, and is often clumsy. But it _is_ effective.
-
-The goals of the Go project were to eliminate the slowness and clumsiness of software development at Google,
-and thereby to make the process more productive and scalable.
-The language was designed by and for people who write—and read and debug and maintain—large software systems.
-
-Go's purpose is therefore _not_ to do research into programming language design;
-it is to improve the working environment for its designers and their coworkers.
-Go is more about software engineering than programming language research.
-Or to rephrase, it is about language design in the service of software engineering.
-
-But how can a language help software engineering?
-The rest of this article is an answer to that question.
-
-* Pain points
-
-When Go launched, some claimed it was missing particular features or methodologies that were regarded as _de_rigueur_ for a modern language.
-How could Go be worthwhile in the absence of these facilities?
-Our answer to that is that the properties Go _does_ have address the issues that make large-scale software development difficult.
-These issues include:
-
-- slow builds
-- uncontrolled dependencies
-- each programmer using a different subset of the language
-- poor program understanding (code hard to read, poorly documented, and so on)
-- duplication of effort
-- cost of updates
-- version skew
-- difficulty of writing automatic tools
-- cross-language builds
-
-Individual features of a language don't address these issues.
-A larger view of software engineering is required, and
-in the design of Go we tried to focus on solutions to _these_ problems.
-
-As a simple, self-contained example, consider the representation of program structure.
-Some observers objected to Go's C-like block structure with braces, preferring the use of spaces for indentation, in the style of Python or Haskell.
-However, we have had extensive experience tracking down build and test failures caused by cross-language builds where a Python snippet embedded in another language,
-for instance through a SWIG invocation,
-is subtly and _invisibly_ broken by a change in the indentation of the surrounding code.
-Our position is therefore that, although spaces for indentation is nice for small programs, it doesn't scale well,
-and the bigger and more heterogeneous the code base, the more trouble it can cause.
-It is better to forgo convenience for safety and dependability, so Go has brace-bounded blocks.
-
-* Dependencies in C and C++
-
-A more substantial illustration of scaling and other issues arises in the handling of package dependencies.
-We begin the discussion with a review of how they work in C and C++.
-
-ANSI C, first standardized in 1989, promoted the idea of  `#ifndef` "guards" in the standard header files.
-The idea, which is ubiquitous now, is that each header file be bracketed with a conditional compilation clause so that the file may be included multiple times without error.
-For instance, the Unix header file `<sys/stat.h>` looks schematically like this:
-
-	/* Large copyright and licensing notice */
-	#ifndef _SYS_STAT_H_
-	#define _SYS_STAT_H_
-	/* Types and other definitions */
-	#endif
-
-The intent is that the C preprocessor reads in the file but disregards the contents on
-the second and subsequent
-readings of the file.
-The symbol `_SYS_STAT_H_`, defined the first time the file is read, "guards" the invocations that follow.
-
-This design has some nice properties, most important that each header file can safely `#include`
-all its dependencies, even if other header files will also include them.
-If that rule is followed, it permits orderly code that, for instance, sorts the `#include`
-clauses alphabetically.
-
-But it scales very badly.
-
-In 1984, a compilation of `ps.c`, the source to the Unix `ps` command, was observed
-to `#include` `<sys/stat.h>` 37 times by the time all the preprocessing had been done.
-Even though the contents are discarded 36 times while doing so, most C
-implementations would open the file, read it, and scan it all 37 times.
-Without great cleverness, in fact, that behavior is required by the potentially
-complex macro semantics of the C preprocessor.
-
-The effect on software is the gradual accumulation of `#include` clauses in C programs.
-It won't break a program to add them, and it's very hard to know when they are no
-longer needed.
-Deleting a `#include` and compiling the program again isn't even sufficient to test that,
-since another `#include` might itself contain a `#include` that pulls it in anyway.
-
-Technically speaking, it does not have to be like that.
-Realizing the long-term problems with the use of `#ifndef` guards, the designers
-of the Plan 9 libraries took a different, non-ANSI-standard approach.
-In Plan 9, header files were forbidden from containing further `#include` clauses; all
-`#includes` were required to be in the top-level C file.
-This required some discipline, of course—the programmer was required to list
-the necessary dependencies exactly once, in the correct order—but documentation
-helped and in practice it worked very well.
-The result was that, no matter how many dependencies a C source file had,
-each `#include` file was read exactly once when compiling that file.
-And, of course, it was also easy to see if an `#include` was necessary by taking
-it out: the edited program would compile if and only if the dependency was unnecessary.
-
-The most important result of the Plan 9 approach was much faster compilation: the amount of
-I/O the compilation requires can be dramatically less than when compiling a program
-using libraries with `#ifndef` guards.
-
-Outside of Plan 9, though, the "guarded" approach is accepted practice for C and C++.
-In fact, C++ exacerbates the problem by using the same approach at finer granularity.
-By convention, C++ programs are usually structured with one header file per class, or perhaps
-small set of related classes, a grouping much smaller than, say, `<stdio.h>`.
-The dependency tree is therefore much more intricate, reflecting not library dependencies but the full type hierarchy.
-Moreover, C++ header files usually contain real code—type, method, and template
-declarations—not just the simple constants and function signatures typical of a C header file.
-Thus not only does C++ push more to the compiler, what it pushes is harder to compile,
-and each invocation of the compiler must reprocess this information.
-When building a large C++ binary, the compiler might be taught thousands of times how to
-represent a string by processing the header file `<string>`.
-(For the record, around 1984 Tom Cargill observed that the use of the
-C preprocessor for dependency management would be a long-term liability for C++ and
-should be addressed.)
-
-The construction of a single C++ binary at Google can open and read hundreds of individual header files
-tens of thousands of times.
-In 2007, build engineers at Google instrumented the compilation of a major Google binary.
-The file contained about two thousand files that, if simply concatenated together, totaled 4.2 megabytes.
-By the time the `#includes` had been expanded, over 8 gigabytes were being delivered to the input of the compiler, a blow-up of 2000 bytes for every C++ source byte.
-
-As another data point, in 2003 Google's build system was moved from a single Makefile to a per-directory design
-with better-managed, more explicit dependencies.
-A typical binary shrank about 40% in file size, just from having more accurate dependencies recorded.
-Even so, the properties of C++ (or C for that matter) make it impractical to verify those dependencies automatically,
-and today we still do not have an accurate understanding of the dependency requirements
-of large Google C++ binaries.
-
-The consequence of these uncontrolled dependencies and massive scale is that it is
-impractical to build Google server binaries on a single computer, so
-a large distributed compilation system was created.
-With this system, involving many machines, much caching, and
-much complexity (the build system is a large program in its own right), builds at
-Google are practical, if still cumbersome.
-
-Even with the distributed build system, a large Google build can still take many minutes.
-That 2007 binary took 45 minutes using a precursor distributed build system; today's
-version of the same program takes 27 minutes, but of course the program and its
-dependencies have grown in the interim.
-The engineering effort required to scale up the build system has barely been able
-to stay ahead of the growth of the software it is constructing.
-
-* Enter Go
-
-When builds are slow, there is time to think.
-The origin myth for Go states that it was during one of those 45 minute builds
-that Go was conceived. It was believed to be worth trying to design a new language
-suitable for writing large Google programs such as web servers,
-with software engineering considerations that would improve the quality
-of life of Google programmers.
-
-Although the discussion so far has focused on dependencies,
-there are many other issues that need attention.
-The primary considerations for any language to succeed in this context are:
-
-- It must work at scale, for large programs with large numbers of dependencies, with large teams of programmers working on them.
-
-- It must be familiar, roughly C-like. Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical.
-
-- It must be modern. C, C++, and to some extent Java are quite old, designed before the advent of multicore machines, networking, and web application development. There are features of the modern world that are better met by newer approaches, such as built-in concurrency.
-
-With that background, then, let us look at the design of Go from a software engineering perspective.
-
-* Dependencies in Go
-
-Since we've taken a detailed look at dependencies in C and C++, a good place to start
-our tour is to see how Go handles them.
-Dependencies are defined, syntactically and semantically, by the language.
-They are explicit, clear, and "computable", which is to say, easy to write tools to analyze.
-
-The syntax is that, after the `package` clause (the subject of the next section),
-each source file may have one or more import statements, comprising the
-`import` keyword and a string constant identifying the package to be imported
-into this source file (only):
-
-	import "encoding/json"
-
-The first step to making Go scale, dependency-wise, is that the _language_ defines
-that unused dependencies are a compile-time error (not a warning, an _error_).
-If the source file imports a package it does not use, the program will not compile.
-This guarantees by construction that the dependency tree for any Go program
-is precise, that it has no extraneous edges. That, in turn, guarantees that no
-extra code will be compiled when building the program, which minimizes
-compilation time.
-
-There's another step, this time in the implementation of the compilers, that
-goes even further to guarantee efficiency.
-Consider a Go program with three packages and this dependency graph:
-
--  package `A` imports package `B`;
--  package `B` imports package `C`;
--  package `A` does _not_ import package `C`
-
-This means that package `A` uses `C` only transitively through its use of `B`;
-that is, no identifiers from `C` are mentioned in the source code to `A`,
-even if some of the items `A` is using from `B` do mention `C`.
-For instance, package `A` might reference a  `struct` type defined in `B` that has a field with
-a type defined in `C` but that `A` does not reference itself.
-As a motivating example, imagine that `A` imports a formatted I/O package
-`B` that uses a buffered I/O implementation provided by `C`, but that `A` does
-not itself invoke buffered I/O.
-
-To build this program, first, `C` is compiled;
-dependent packages must be built before the packages that depend on them.
-Then `B` is compiled; finally `A` is compiled, and then the program can be linked.
-
-When `A` is compiled, the compiler reads the object file for `B`, not its source code.
-That object file for `B` contains all the type information necessary for the compiler
-to execute the
-
-	import "B"
-
-clause in the source code for `A`. That information includes whatever information
-about `C` that clients of `B` will need at compile time.
-In other words, when `B` is compiled, the generated object file includes type
-information for all dependencies of `B` that affect the public interface of `B`.
-
-This design has the important
-effect that when the compiler executes an import clause,
-_it_opens_exactly_one_file_, the object file identified by the string in the import clause.
-This is, of course, reminiscent of the Plan 9 C (as opposed to ANSI C)
-approach to dependency management, except that, in effect, the compiler
-writes the header file when the Go source file is compiled.
-The process is more automatic and even
-more efficient than in Plan 9 C, though: the data being read when evaluating the import is just
-"exported" data, not general program source code. The effect on overall
-compilation time can be huge, and scales well as
-the code base grows. The time to execute the dependency graph, and
-hence to compile, can be exponentially less than in the "include of
-include file" model of C and C++.
-
-It's worth mentioning that this general approach to dependency management
-is not original; the ideas go back to the 1970s and flow through languages like
-Modula-2 and Ada. In the C family Java has elements of this approach.
-
-To make compilation even more efficient, the object file is arranged so the export
-data is the first thing in the file, so the compiler can stop reading as soon
-as it reaches the end of that section.
-
-This approach to dependency management is the single biggest reason
-why Go compilations are faster than C or C++ compilations.
-Another factor is that Go places the export data in the object file; some
-languages require the author to write or the compiler to
-generate a second file with that information. That's twice as many files
-to open. In Go there is only one file to open to import a package.
-Also, the single file approach means that the export data (or header
-file, in C/C++) can never go out of date relative to the object file.
-
-For the record, we measured the compilation of a large Google program
-written in Go to see how the source code fanout compared to the C++
-analysis done earlier. We found it was about 40X, which is
-fifty times better than C++ (as well as being simpler and hence faster
-to process), but it's still bigger than we expected. There are two reasons for
-this. First, we found a bug: the Go compiler was generating a substantial
-amount of data in the export section that did not need to be there. Second,
-the export data uses a verbose encoding that could be improved.
-We plan to address these issues.
-
-Nonetheless, a factor of fifty less to do turns minutes into seconds,
-coffee breaks into interactive builds.
-
-Another feature of the Go dependency graph is that it has no cycles.
-The language defines that there can be no circular imports in the graph,
-and the compiler and linker both check that they do not exist.
-Although they are occasionally useful, circular imports introduce
-significant problems at scale.
-They require the compiler to deal with larger sets of source files
-all at once, which slows down incremental builds.
-More important, when allowed, in our experience such imports end up
-entangling huge swaths of the source tree into large subpieces that are
-difficult to manage independently, bloating binaries and complicating
-initialization, testing, refactoring, releasing, and other tasks of
-software development.
-
-The lack of circular imports causes occasional annoyance but keeps the tree clean,
-forcing a clear demarcation between packages. As with many of the
-design decisions in Go, it forces the programmer to think earlier about a
-larger-scale issue (in this case, package boundaries) that if left until
-later may never be addressed satisfactorily.
-
-Through the design of the standard library, great effort was spent on controlling
-dependencies. It can be better to copy a little code than to pull in a big
-library for one function. (A test in the system build complains if new core
-dependencies arise.) Dependency hygiene trumps code reuse.
-One example of this in practice is that
-the (low-level) `net` package has its own integer-to-decimal conversion routine
-to avoid depending on the bigger and dependency-heavy formatted I/O package.
-Another is that the string conversion package `strconv` has a private implementation
-of the definition of 'printable' characters rather than pull in the large Unicode
-character class tables; that `strconv` honors the Unicode standard is verified by the
-package's tests.
-
-* Packages
-
-The design of Go's package system combines some of the properties of libraries,
-name spaces, and modules into a single construct.
-
-Every Go source file, for instance `"encoding/json/json.go"`, starts with a package clause, like this:
-
-	package json
-
-where `json` is the "package name", a simple identifier.
-Package names are usually concise.
-
-To use a package, the importing source file identifies it by its _package_path_
-in the import clause.
-The meaning of "path" is not specified by the language, but in
-practice and by convention it is the slash-separated directory path of the
-source package in the repository, here:
-
-	import "encoding/json"
-
-Then the package name (as distinct from path) is used to qualify items from
-the package in the importing source file:
-
-	var dec = json.NewDecoder(reader)
-
-This design provides clarity.
-One may always tell whether a name is local to package from its syntax: `Name` vs. `pkg.Name`.
-(More on this later.)
-
-For our example, the package path is `"encoding/json"` while the package name is `json`.
-Outside the standard repository, the convention is to place the 
-project or company name at the root of the name space:
-
-	import "google/base/go/log"
-
-It's important to recognize that package _paths_ are unique,
-but there is no such requirement for package _names_.
-The path must uniquely identify the package to be imported, while the
-name is just a convention for how clients of the package can refer to its
-contents.
-The package name need not be unique and can be overridden
-in each importing source file by providing a local identifier in the
-import clause. These two imports both reference packages that
-call themselves `package` `log`, but to import them in a single source
-file one must be (locally) renamed:
-
-	import "log"                          // Standard package
-	import googlelog "google/base/go/log" // Google-specific package
-
-Every company might have its own `log` package but
-there is no need to make the package name unique.
-Quite the opposite: Go style suggests keeping package names short and clear
-and obvious in preference to worrying about collisions.
-
-Another example: there are many `server` packages in Google's code base.
-
-* Remote packages
-
-An important property of Go's package system is that the package path,
-being in general an arbitrary string, can be co-opted to refer to remote
-repositories by having it identify the URL of the site serving the repository.
-
-Here is how to use the `doozer` package from `github`. The `go` `get` command
-uses the `go` build tool to fetch the repository from the site and install it.
-Once installed, it can be imported and used like any regular package.
-
-	$ go get github.com/4ad/doozer // Shell command to fetch package
-
-	import "github.com/4ad/doozer" // Doozer client's import statement
-
-	var client doozer.Conn         // Client's use of package
-
-It's worth noting that the `go` `get` command downloads dependencies
-recursively, a property made possible only because the dependencies are
-explicit.
-Also, the allocation of the space of import paths is delegated to URLs,
-which makes the naming of packages decentralized and therefore scalable,
-in contrast to centralized registries used by other languages.
-
-* Syntax
-
-Syntax is the user interface of a programming language. Although it has
-limited effect on the semantics of the language, which is arguably the
-more important component, syntax determines the readability and hence
-clarity of the language. Also, syntax is critical to tooling: if the language
-is hard to parse, automated tools are hard to write.
-
-Go was therefore designed with clarity and tooling in mind, and has
-a clean syntax.
-Compared to other languages in the C family, its
-grammar is modest in size, with only 25 keywords (C99 has
-37; C++11 has 84; the numbers continue to grow).
-More important,
-the grammar is regular and therefore easy to parse (mostly; there
-are a couple of quirks we might have fixed but didn't discover early
-enough).
-Unlike C and Java and especially C++, Go can be parsed without
-type information or a symbol table;
-there is no type-specific context. The grammar is
-easy to reason about and therefore tools are easy to write.
-
-One of the details of Go's syntax that surprises C programmers is that
-the declaration syntax is closer to Pascal's than to C's.
-The declared name appears before the type and there are more keywords:
-
-	var fn func([]int) int
-	type T struct { a, b int }
-
-as compared to C's
-
-	int (*fn)(int[]);
-	struct T { int a, b; }
-
-Declarations introduced by keyword are easier to parse both for people and
-for computers, and having the type syntax not be the expression syntax
-as it is in C has a significant effect on parsing: it adds grammar
-but eliminates ambiguity.
-But there is a nice side effect, too: for initializing declarations,
-one can drop the `var` keyword and just take the type of the variable
-from that of the expression. These two declarations are equivalent;
-the second is shorter and idiomatic:
-
-	var buf *bytes.Buffer = bytes.NewBuffer(x) // explicit
-	buf := bytes.NewBuffer(x)                  // derived
-
-There is a blog post at [[http://golang.org/s/decl-syntax][golang.org/s/decl-syntax]] with more detail about the syntax of declarations in Go and
-why it is so different from C.
-
-Function syntax is straightforward for simple functions.
-This example declares the function  `Abs`, which accepts a single
-variable `x` of type `T` and returns a single `float64` value:
-
-	func Abs(x T) float64
-
-A method is just a function with a special parameter, its _receiver_,
-which can be passed to the function using the standard "dot" notation.
-Method declaration syntax places the receiver in parentheses before the
-function name. Here is the same function, now as a method of type `T`:
-
-	func (x T) Abs() float64
-
-And here is a variable (closure) with a type `T` argument; Go has first-class
-functions and closures:
-
-	negAbs := func(x T) float64 { return -Abs(x) }
-	
-Finally, in Go functions can return multiple values. A common case is to
-return the function result and an `error` value as a pair, like this:
-
-	func ReadByte() (c byte, err error)
-
-	c, err := ReadByte()
-	if err != nil { ... }
-
-We'll talk more about errors later.
-
-One feature missing from Go is that it
-does not support default function arguments. This was a deliberate
-simplification. Experience tells us that defaulted arguments make it
-too easy to patch over API design flaws by adding more arguments,
-resulting in too many arguments with interactions that are
-difficult to disentangle or even understand.
-The lack of default arguments requires more functions or methods to be defined,
-as one function cannot hold the entire interface,
-but that leads to a clearer API that is easier to understand.
-Those functions all need separate names, too, which makes it clear
-which combinations exist, as well as encouraging more
-thought about naming, a critical aspect of clarity and readability.
-
-One mitigating factor for the lack of default arguments is that Go
-has easy-to-use, type-safe support for variadic functions.
-
-* Naming
-
-Go takes an unusual approach to defining the _visibility_ of an identifier,
-the ability for a client of a package to use the item named by the identifier.
-Unlike, for instance, `private` and `public` keywords, in Go the name itself
-carries the information: the case of the initial letter of the identifier
-determines the visibility. If the initial character is an upper case letter,
-the identifier is _exported_ (public); otherwise it is not:
-
-- upper case initial letter: `Name` is visible to clients of package
-- otherwise: `name` (or `_Name`) is not visible to clients of package
-
-This rule applies to variables, types, functions, methods, constants, fields...
-everything. That's all there is to it.
-
-This was not an easy design decision.
-We spent over a year struggling to
-define the notation to specify an identifier's visibility.
-Once we settled on using the case of the name, we soon realized it had
-become one of the most important properties about the language.
-The name is, after all, what clients of the package use; putting
-the visibility in the name rather than its type means that it's always
-clear when looking at an identifier whether it is part of the public API.
-After using Go for a while, it feels burdensome when going back to
-other languages that require looking up the declaration to discover
-this information.
-
-The result is, again, clarity: the program source text expresses the
-programmer's meaning simply.
-
-Another simplification is that Go has a very compact scope hierarchy:
-
-- universe (predeclared identifiers such as `int` and `string`)
-- package (all the source files of a package live at the same scope)
-- file (for package import renames only; not very important in practice)
-- function (the usual)
-- block (the usual)
-
-There is no scope for name space or class or other wrapping
-construct. Names come from very few places in Go, and all names
-follow the same scope hierarchy: at any given location in the source,
-an identifier denotes exactly one language object, independent of how
-it is used. (The only exception is statement labels, the targets of `break`
-statements and the like; they always have function scope.)
-
-This has consequences for clarity. Notice for instance that methods
-declare an explicit receiver and that it must be used to access fields and
-methods of the type. There is no implicit `this`. That is, one always
-writes
-
-	rcvr.Field
-
-(where rcvr is whatever name is chosen for the receiver variable)
-so all the elements of the type always appear lexically bound to
-a value of the receiver type. Similarly, a package qualifier is always present
-for imported names; one writes `io.Reader` not `Reader`.
-Not only is this clear, it frees up the identifier `Reader` as a useful
-name to be used in any package. There are in fact multiple exported
-identifiers in the standard library with name `Reader`, or `Printf`
-for that matter, yet which one is being referred to is always unambiguous.
-
-Finally, these rules combine to guarantee that, other than the top-level
-predefined names such as `int`, (the first component of) every name is
-always declared in the current package.
-
-In short, names are local. In C, C++, or Java the name `y` could refer to anything.
-In Go, `y` (or even `Y`) is always defined within the package,
-while the interpretation of `x.Y` is clear: find `x` locally, `Y` belongs to it.
-
-These rules provide an important property for scaling because they guarantee
-that adding an exported name to a package can never break a client
-of that package. The naming rules decouple packages, providing
-scaling, clarity, and robustness.
-
-There is one more aspect of naming to be mentioned: method lookup
-is always by name only, not by signature (type) of the method.
-In other words, a single type can never have two methods with the same name.
-Given a method `x.M`, there's only ever one `M` associated with `x`.
-Again, this makes it easy to identify which method is referred to given
-only the name.
-It also makes the implementation of method invocation simple.
-
-* Semantics
-
-The semantics of Go statements is generally C-like. It is a compiled, statically typed,
-procedural language with pointers and so on. By design, it should feel
-familiar to programmers accustomed to languages in the C family.
-When launching a new language
-it is important that the target audience be able to learn it quickly; rooting Go
-in the C family helps make sure that young programmers, most of whom
-know Java, JavaScript, and maybe C, should find Go easy to learn.
-
-That said, Go makes many small changes to C semantics, mostly in the
-service of robustness. These include:
-
-- there is no pointer arithmetic
-- there are no implicit numeric conversions
-- array bounds are always checked
-- there are no type aliases (after `type`X`int`, `X` and `int` are distinct types not aliases)
-- `++` and `--` are statements not expressions
-- assignment is not an expression
-- it is legal (encouraged even) to take the address of a stack variable
-- and many more
-
-There are some much bigger changes too, stepping far from the traditional
-C, C++, and even Java models. These include linguistic support for:
-
-- concurrency
-- garbage collection
-- interface types
-- reflection
-- type switches
-
-The following sections provide brief discussions of two of these topics in Go,
-concurrency and garbage collection,
-mostly from a software engineering perspective.
-For a full discussion of the language semantics and uses see the many
-resources on the [[http://golang.org]] web site.
-
-* Concurrency
-
-Concurrency is important to the modern computing environment with its
-multicore machines running web servers with multiple clients,
-what might be called the typical Google program.
-This kind of software is not especially well served by C++ or Java,
-which lack sufficient concurrency support at the language level.
-
-Go embodies a variant of CSP with first-class channels.
-CSP was chosen partly due to familiarity (one of us had worked on
-predecessor languages that built on CSP's ideas), but also because
-CSP has the property that it is easy to add to a procedural programming
-model without profound changes to that model.
-That is, given a C-like language, CSP can be added to the language
-in a mostly orthogonal way, providing extra expressive power without
-constraining the language's other uses. In short, the rest of the
-language can remain "ordinary".
-
-The approach is thus the composition of independently executing
-functions of otherwise regular procedural code.
-
-The resulting language allows us to couple concurrency with computation
-smoothly. Consider a web server that must verify security certificates for
-each incoming client call; in Go it is easy to construct the software using
-CSP to manage the clients as independently executing procedures but
-to have the full power of an efficient compiled language available for
-the expensive cryptographic calculations.
-
-In summary, CSP is practical for Go and for Google. When writing
-a web server, the canonical Go program, the model is a great fit.
-
-There is one important caveat: Go is not purely memory safe in the presence
-of concurrency. Sharing is legal and passing a pointer over a channel is idiomatic
-(and efficient).
-
-Some concurrency and functional programming experts are disappointed
-that Go does not take a write-once approach to value semantics
-in the context of concurrent computation, that Go is not more like
-Erlang for example.
-Again, the reason is largely about familiarity and suitability for the
-problem domain. Go's concurrent features work well in a context
-familiar to most programmers.
-Go _enables_ simple, safe concurrent
-programming but does not _forbid_ bad programming.
-We compensate by convention, training programmers to think
-about message passing as a version of ownership control. The motto is,
-"Don't communicate by sharing memory, share memory by communicating."
-
-Our limited experience with programmers new to both Go and concurrent
-programming shows that this is a practical approach. Programmers
-enjoy the simplicity that support for concurrency brings to network
-software, and simplicity engenders robustness.
-
-* Garbage collection
-
-For a systems language, garbage collection can be a controversial feature,
-yet we spent very little time deciding that Go would be a
-garbage-collected language.
-Go has no explicit memory-freeing operation: the only way allocated
-memory returns to the pool is through the garbage collector.
-
-It was an easy decision to make because memory management
-has a profound effect on the way a language works in practice. 
-In C and C++, too much programming effort is spent on memory allocation
-and freeing.
-The resulting designs tend to expose details of memory management
-that could well be hidden; conversely memory considerations
-limit how they can be used. By contrast, garbage collection makes interfaces
-easier to specify.
-
-Moreover, in a concurrent object-oriented language it's almost essential
-to have automatic memory management because the ownership of a piece
-of memory can be tricky to manage as it is passed around among concurrent
-executions. It's important to separate behavior from resource management.
-
-The language is much easier to use because of garbage collection.
-
-Of course, garbage collection brings significant costs: general overhead,
-latency, and complexity of the implementation. Nonetheless, we believe
-that the benefits, which are mostly felt by the programmer, outweigh
-the costs, which are largely borne by the language implementer.
-
-Experience with Java in particular as a server language has made some
-people nervous about garbage collection in a user-facing system.
-The overheads are uncontrollable, latencies can be large, and much
-parameter tuning is required for good performance.
-Go, however, is different. Properties of the language mitigate some of these
-concerns. Not all of them of course, but some.
-
-The key point is that Go gives the programmer tools to limit allocation
-by controlling the layout of data structures. Consider this simple
-type definition of a data structure containing a buffer (array) of bytes:
-
-	type X struct {
-		a, b, c int
-		buf [256]byte
-	}
-
-In Java, the `buf` field would require a second allocation and accesses
-to it a second level of indirection. In Go, however, the buffer is allocated
-in a single block of memory along with the containing struct and no
-indirection is required. For systems programming, this design can have a
-better performance as well as reducing the number
-of items known to the collector. At scale it can make a significant
-difference.
-
-As a more direct example, in Go it is easy and efficient to provide
-second-order allocators, for instance an arena allocator that allocates
-a large array of structs and links them together with a free list.
-Libraries that repeatedly use many small structures like this can,
-with modest prearrangement, generate no garbage yet
-be efficient and responsive.
-
-Although Go is a garbage collected language, therefore, a knowledgeable
-programmer can limit the pressure placed on the collector and thereby
-improve performance. (Also, the Go installation comes with good tools
-for studying the dynamic memory performance of a running program.)
-
-To give the programmer this flexibility, Go must support
-what we call _interior_pointers_ to objects
-allocated in the heap. The `X.buf` field in the example above lives
-within the struct but it is legal to capture the address of this inner field,
-for instance to pass it to an I/O routine. In Java, as in many garbage-collected
-languages, it is not possible to construct an interior pointer like this,
-but in Go it is idiomatic.
-This design point affects which collection algorithms can be used,
-and may make them more difficult, but after careful thought we decided
-that it was necessary to allow interior pointers because of the benefits
-to the programmer and the ability to reduce pressure on the (perhaps
-harder to implement) collector.
-So far, our experience comparing similar Go and Java programs shows
-that use of interior pointers can have a significant effect on total arena size,
-latency, and collection times.
-
-In summary, Go is garbage collected but gives the programmer
-some tools to control collection overhead.
-
-The garbage collector remains an active area of development.
-The current design is a parallel mark-and-sweep collector and there remain
-opportunities to improve its performance or perhaps even its design.
-(The language specification does not mandate any particular implementation
-of the collector.)
-Still, if the programmer takes care to use memory wisely,
-the current implementation works well for production use.
-
-* Composition not inheritance
-
-Go takes an unusual approach to object-oriented programming, allowing
-methods on any type, not just classes, but without any form of type-based inheritance
-like subclassing.
-This means there is no type hierarchy.
-This was an intentional design choice.
-Although type hierarchies have been used to build much successful
-software, it is our opinion that the model has been overused and that it
-is worth taking a step back.
-
-Instead, Go has _interfaces_, an idea that has been discussed at length elsewhere (see
-[[http://research.swtch.com/interfaces]]
-for example), but here is a brief summary.
-
-In Go an interface is _just_ a set of methods. For instance, here is the definition
-of the `Hash` interface from the standard library.
-
-	type Hash interface {
-		Write(p []byte) (n int, err error)
-		Sum(b []byte) []byte
-		Reset()
-		Size() int
-		BlockSize() int
-	}
-
-All data types that implement these methods satisfy this interface implicitly;
-there is no `implements` declaration.
-That said, interface satisfaction is statically checked at compile time
-so despite this decoupling interfaces are type-safe.
-
-A type will usually satisfy many interfaces, each corresponding
-to a subset of its methods. For example, any type that satisfies the `Hash`
-interface also satisfies the `Writer` interface:
-
-	type Writer interface {
-		Write(p []byte) (n int, err error)
-	}
-
-This fluidity of interface satisfaction encourages a different approach
-to software construction. But before explaining that, we should explain
-why Go does not have subclassing.
-
-Object-oriented programming provides a powerful insight: that the
-_behavior_ of data can be generalized independently of the
-_representation_ of that data.
-The model works best when the behavior (method set) is fixed,
-but once you subclass a type and add a method,
-_the_behaviors_are_no_longer_identical_.
-If instead the set of behaviors is fixed, such as in Go's statically
-defined interfaces, the uniformity of behavior enables data and
-programs to be composed uniformly, orthogonally, and safely.
-
-One extreme example is the Plan 9 kernel, in which all system data items
-implemented exactly the same interface, a file system API defined
-by 14 methods.
-This uniformity permitted a level of object composition seldom
-achieved in other systems, even today.
-Examples abound. Here's one: A system could import (in Plan 9 terminology) a TCP
-stack to a computer that didn't have TCP or even Ethernet, and over that network
-connect to a machine with a different CPU architecture, import its `/proc` tree,
-and run a local debugger to do breakpoint debugging of the remote process.
-This sort of operation was workaday on Plan 9, nothing special at all.
-The ability to do such things fell out of the design; it required no special
-arrangement (and was all done in plain C).
-
-We argue that this compositional style of system construction has been
-neglected by the languages that push for design by type hierarchy.
-Type hierarchies result in brittle code.
-The hierarchy must be designed early, often as the first step of
-designing the program, and early decisions can be difficult to change once
-the program is written.
-As a consequence, the model encourages early overdesign as the
-programmer tries to predict every possible use the software might
-require, adding layers of type and abstraction just in case.
-This is upside down.
-The way pieces of a system interact should adapt as it grows,
-not be fixed at the dawn of time.
-
-Go therefore encourages _composition_ over inheritance, using
-simple, often one-method interfaces to define trivial behaviors
-that serve as clean, comprehensible boundaries between components.
-
-Consider the `Writer` interface shown above, which is defined in
-package `io`: Any item that has a `Write` method with this
-signature works well with the complementary `Reader` interface:
-
-	type Reader interface {
-		Read(p []byte) (n int, err error)
-	}
-
-These two complementary methods allow type-safe chaining
-with rich behaviors, like generalized Unix pipes.
-Files, buffers, networks,
-encryptors, compressors, image encoders, and so on can all be
-connected together.
-The `Fprintf` formatted I/O routine takes an `io.Writer` rather than,
-as in C, a `FILE*`.
-The formatted printer has no knowledge of what it is writing to; it may
-be a image encoder that is in turn writing to a compressor that
-is in turn writing to an encryptor that is in turn writing to a network
-connection.
-
-Interface composition is a different style of programming, and
-people accustomed to type hierarchies need to adjust their thinking to
-do it well, but the result is an adaptability of
-design that is harder to achieve through type hierarchies.
-
-Note too that the elimination of the type hierarchy also eliminates
-a form of dependency hierarchy.
-Interface satisfaction allows the program to grow organically without
-predetermined contracts.
-And it is a linear form of growth; a change to an interface affects
-only the immediate clients of that interface; there is no subtree to update.
-The lack of `implements` declarations disturbs some people but
-it enables programs to grow naturally, gracefully, and safely.
-
-Go's interfaces have a major effect on program design.
-One place we see this is in the use of functions that take interface
-arguments. These are _not_ methods, they are functions.
-Some examples should illustrate their power.
-`ReadAll` returns a byte slice (array) holding all the data that can
-be read from an `io.Reader`:
-
-	func ReadAll(r io.Reader) ([]byte, error)
-
-Wrappers—functions that take an interface and return an interface—are
-also widespread.
-Here are some prototypes.
-`LoggingReader` logs every `Read` call on the incoming `Reader`.
-`LimitingReader` stops reading after `n` bytes.
-`ErrorInjector` aids testing by simulating I/O errors.
-And there are many more.
-
-	func LoggingReader(r io.Reader) io.Reader
-	func LimitingReader(r io.Reader, n int64) io.Reader
-	func ErrorInjector(r io.Reader) io.Reader
-
-The designs are nothing like hierarchical, subtype-inherited methods.
-They are looser (even _ad_hoc_), organic, decoupled, independent, and therefore scalable.
-
-* Errors
-
-Go does not have an exception facility in the conventional sense,
-that is, there is no control structure associated with error handling.
-(Go does provide mechanisms for handling exceptional situations
-such as division by zero. A pair of built-in functions
-called `panic` and `recover` allow the programmer to protect
-against such things. However, these functions
-are intentionally clumsy, rarely used, and not integrated
-into the library the way, say, Java libraries use exceptions.)
-
-The key language feature for error handling is a pre-defined
-interface type called `error` that represents a value that has an
-`Error` method returning a string:
-
-	type error interface {
-		Error() string
-	}
-
-Libraries use the `error` type to return a description of the error.
-Combined with the ability for functions to return multiple
-values, it's easy to return the computed result along with an
-error value, if any.
-For instance, the equivalent
-to C's `getchar` does not return an out-of-band value at EOF,
-nor does it throw an exception; it just returns an `error` value
-alongside the character, with a `nil` `error` value signifying success.
-Here is the signature of the `ReadByte` method of the buffered
-I/O package's `bufio.Reader` type:
-
-	func (b *Reader) ReadByte() (c byte, err error)
-
-This is a clear and simple design, easily understood.
-Errors are just values and programs compute with
-them as they would compute with values of any other type.
-
-It was a deliberate choice not to incorporate exceptions in Go.
-Although a number of critics disagree with this decision, there
-are several reasons we believe it makes for better software.
-
-First, there is nothing truly exceptional about errors in computer programs.
-For instance, the inability to open a file is a common issue that
-does not deserve special linguistic constructs; `if` and `return` are fine.
-
-	f, err := os.Open(fileName)
-	if err != nil {
-		return err
-	}
-
-Also, if errors use special control structures, error handling distorts
-the control flow for a program that handles errors.
-The Java-like style of `try-catch-finally` blocks interlaces multiple overlapping flows
-of control that interact in complex ways.
-Although in contrast Go makes it more
-verbose to check errors, the explicit design keeps the flow of control
-straightforward—literally.
-
-There is no question the resulting code can be longer,
-but the clarity and simplicity of such code offsets its verbosity.
-Explicit error checking forces the programmer to think about
-errors—and deal with them—when they arise. Exceptions make
-it too easy to _ignore_ them rather than _handle_ them, passing
-the buck up the call stack until it is too late to fix the problem or
-diagnose it well.
-
-* Tools
-
-Software engineering requires tools.
-Every language operates in an environment with other languages
-and myriad tools to compile, edit, debug, profile, test, and run programs.
-
-Go's syntax, package system, naming conventions, and other features
-were designed to make tools easy to write, and the library
-includes a lexer, parser, and type checker for the language.
-
-Tools to manipulate Go programs are so easy to write that
-many such tools have been created,
-some with interesting consequences for software engineering.
-
-The best known of these is `gofmt`, the Go source code formatter.
-From the beginning of the project, we  intended Go programs
-to be formatted by machine, eliminating an entire class of argument
-between programmers: how do I lay out my code?
-`Gofmt` is run on all Go programs we write, and most of the open
-source community uses it too.
-It is run as a "presubmit" check for the code repositories to
-make sure that all checked-in Go programs are formatted the same.
-
-`Gofmt` is often cited by users as one of Go's best features even
-though it is not part of the language.
-The existence and use of `gofmt` means that
-from the beginning, the community has always
-seen Go code as `gofmt` formats it, so Go programs have a single
-style that is now familiar to everyone. Uniform presentation
-makes code easier to read and therefore faster to work on.
-Time not spent on formatting is time saved.
-`Gofmt` also affects scalability: since all code looks the same,
-teams find it easier to work together or with others' code.
-
-`Gofmt` enabled another class of tools that we did not foresee as clearly.
-The program works by parsing the source code and reformatting it
-from the parse tree itself.
-This makes it possible to _edit_ the parse tree before formatting it,
-so a suite of automatic refactoring tools sprang up.
-These are easy to write, can be semantically rich because they work
-directly on the parse tree, and automatically produce canonically
-formatted code.
-
-The first example was a `-r` (rewrite) flag on `gofmt` itself, which
-uses a simple pattern-matching language to enable expression-level
-rewrites. For instance, one day we introduced a default value for the
-right-hand side of a slice expression: the length itself. The entire
-Go source tree was updated to use this default with the single
-command:
-
-	gofmt -r 'a[b:len(a)] -> a[b:]'
-
-A key point about this transformation is that, because the input and
-output are both in the canonical format, the only changes made to
-the source code are semantic ones.
-
-A similar but more intricate process allowed `gofmt` to be used to
-update the tree when the language no longer required semicolons
-as statement terminators if the statement ended at a newline.
-
-Another important tool is `gofix`, which runs tree-rewriting modules
-written in Go itself that are therefore are capable of more advanced
-refactorings.
-The `gofix` tool allowed us to make sweeping changes to APIs and language
-features leading up to the release of Go 1, including a change to the syntax
-for deleting entries from a map, a radically different API for manipulating
-time values, and many more.
-As these changes rolled out, users could update all their code by running
-the simple command
-
-	gofix
-
-Note that these tools allow us to _update_ code even if the old code still
-works.
-As a result, Go repositories are easy to keep up to date as libraries evolve.
-Old APIs can be deprecated quickly and automatically so only one version
-of the API needs to be maintained.
-For example, we recently changed Go's protocol buffer implementation to use
-"getter" functions, which were not in the interface before.
-We ran `gofix` on _all_ of Google's Go code to update all programs that
-use protocol buffers, and now there is only one version of the API in use.
-Similar sweeping changes to the C++ or Java libraries are almost infeasible
-at the scale of Google's code base.
-
-The existence of a parsing package in the standard Go library has enabled
-a number of other tools as well. Examples include the `go` tool, which
-manages program construction including acquiring packages from
-remote repositories;
-the `godoc` document extractor,
-a program to verify that the API compatibility contract is maintained as
-the library is updated, and many more.
-
-Although tools like these are rarely mentioned in the context of language
-design, they are an integral part of a language's ecosystem and the fact
-that Go was designed with tooling in mind has a huge effect on the
-development of the language, its libraries, and its community.
-
-* Conclusion
-
-Go's use is growing inside Google.
-
-Several big user-facing services use it, including `youtube.com` and `dl.google.com`
-(the download server that delivers Chrome, Android and other downloads),
-as well as our own [[http://golang.org][golang.org]].
-And of course many small ones do, mostly
-built using Google App Engine's native support for Go.
-
-Many other companies use Go as well; the list is very long, but a few of the
-better known are:
-
-- BBC Worldwide
-- Canonical
-- Heroku
-- Nokia
-- SoundCloud
-
-It looks like Go is meeting its goals. Still, it's too early to declare it a success.
-We don't have enough experience yet, especially with big programs (millions
-of lines of code) to know whether the attempts to build a scalable language
-have paid off. All the indicators are positive though.
-
-On a smaller scale, some minor things aren't quite right and might get
-tweaked in a later (Go 2?) version of the language. For instance, there are
-too many forms of variable declaration syntax, programmers are
-easily confused by the behavior of nil values inside non-nil interfaces,
-and there are many library and interface details that could use another
-round of design.
-
-It's worth noting, though, that `gofix` and `gofmt` gave us the opportunity to
-fix many other problems during the leadup to Go version 1.
-Go as it is today is therefore much closer to what the designers wanted
-than it would have been without these tools, which were themselves
-enabled by the language's design.
-
-Not everything was fixed, though. We're still learning (but the language
-is frozen for now).
-
-A significant weakness of the language is that the implementation still
-needs work. The compilers' generated code and the performance of the
-runtime in particular should be better, and work continues on them.
-There is progress already; in fact some benchmarks show a
-doubling of performance with the development version today compared
-to the first release of Go version 1 early in 2012.
-
-* Summary
-
-Software engineering guided the design of Go.
-More than most general-purpose
-programming languages, Go was designed to address a set of software engineering
-issues that we had been exposed to in the construction of large server software.
-Offhand, that might make Go sound rather dull and industrial, but in fact
-the focus on clarity, simplicity and composability throughout the design
-instead resulted in a productive, fun language that many programmers
-find expressive and powerful.
-
-The properties that led to that include:
-
-- Clear dependencies
-- Clear syntax
-- Clear semantics
-- Composition over inheritance
-- Simplicity provided by the programming model (garbage collection, concurrency)
-- Easy tooling (the `go` tool, `gofmt`, `godoc`, `gofix`)
-
-If you haven't tried Go already, we suggest you do.
-
-
-.link http://golang.org http://golang.org
-
-.image splash/appenginegophercolor.jpg
-
diff --git a/content/2012/splash.slide b/content/2012/splash.slide
deleted file mode 100644
index 039edcd..0000000
--- a/content/2012/splash.slide
+++ /dev/null
@@ -1,832 +0,0 @@
-Go at Google
-SPLASH, Tucson, Oct 25, 2012
-
-Rob Pike
-Google, Inc.
-@rob_pike
-http://golang.org/s/plusrob
-http://golang.org
-
-* Preamble
-
-* What is Go?
-
-Go is:
-
-- open source
-- concurrent
-- garbage-collected
-- efficient
-- scalable
-- simple
-- fun
-- boring (to some)
-
-.link http://golang.org http://golang.org
-
-* History
-
-Design began in late 2007.
-
-Key players:
-
-- Robert Griesemer, Rob Pike, Ken Thompson
-- Later: Ian Lance Taylor, Russ Cox
-
-Became open source in November 2009.
-
-Developed entirely in the open; very active community.
-Language stable as of Go 1, early 2012.
-
-* Go at Google
-
-Go is a programming language designed by Google to help solve Google's problems.
-
-Google has big problems.
-
-* Big hardware
-
-.image splash/datacenter.jpg
-
-* Big software
-
-- C++ (mostly) for servers, plus lots of Java and Python
-- thousands of engineers
-- gazillions of lines of code
-- distributed build system
-- one tree
-
-And of course:
-
-- zillions of machines, which we treat as a modest number of compute clusters
-
-Development at Google can be slow, often clumsy.
-
-But it _is_ effective.
-
-* The reason for Go
-
-Goals:
-
-- eliminate slowness
-- eliminate clumsiness
-- improve effectiveness
-- maintain (even improve) scale
-
-Go was designed by and for people who write—and read and debug and maintain—large software systems.
-
-Go's purpose is _not_ research into programming language design.
-
-Go's purpose is to make its designers' programming lives better.
-
-* Today's theme
-
-A talk about software engineering more than language design.
-
-To be more accurate:
-
-- Language design in the service of software engineering.
-
-In short:
-
-- How does a language help software engineering?
-
-* Features?
-
-Reaction upon launch:
-My favorite feature isn't in Go! Go Sucks!
-
-This misses the point.
-
-* Pain
-
-What makes large-scale development hard with C++ or Java (at least):
-
-- slow builds
-- uncontrolled dependencies
-- each programmer using a different subset of the language
-- poor program understanding (documentation, etc.)
-- duplication of effort
-- cost of updates
-- version skew
-- difficulty of automation (auto rewriters etc.): tooling
-- cross-language builds
-
-Language _features_ don't usually address these.
-
-* Focus
-
-In the design of Go, we tried to focus on solutions to _these_ problems.
-
-Example: indentation for structure vs. C-like braces
-
-* Dependencies in C and C++
-
-* A personal history of dependencies in C
-
-`#ifdef`
-
-`#ifndef` "guards":
-
-	#ifndef _SYS_STAT_H_
-
-1984: `<sys/stat.h>` times 37
-
-ANSI C and `#ifndef` guards:
-
-- dependencies accumulate
-- throw includes at the program until it compiles
-- no way to know what can be removed
-
-* A personal history of dependencies in Plan 9's C
-
-Plan 9, another take:
-
-- no `#ifdefs` (or `#ifndefs`)
-- documentation and topological sort
-- easy to find out what can be removed
-
-Need to document dependencies, but much faster compilation.
-
-In short:
-
-- _ANSI_C_made_a_costly_mistake_ in requiring `#ifndef` guards.
-
-* A personal history of dependencies in C++
-
-C++ exacerbated the problem:
-
-- one `#include` file per class
-- code (not just declarations) in `#include` files
-- `#ifndef` guards persist
-
-2004: Mike Burrows and Chubby: `<xxx>` times 37,000
-
-1984: Tom Cargill and pi
-
-* A personal history of dependencies at Google
-
-Plan 9 demo: a story
-
-Early Google: one `Makefile`
-
-2003: `Makefile` generated from per-directory `BUILD` files
-
-- explicit dependencies
-- 40% smaller binaries
-
-Dependencies still not checkable!
-
-* Result
-
-To build a large Google binary on a single computer is impractical.
-
-In 2007, instrumented the build of a major Google binary:
-
-- 2000 files
-- 4.2 megabytes 
-- 8 gigabytes delivered to compiler
-- 2000 bytes sent to compiler for every C++ source byte
-- it's real work too: `<string>` for example
-- hours to build
-
-* Tools can help
-
-New distributed build system:
-
-- no more `Makefile` (still uses `BUILD` files)
-- many buildbots
-- much caching
-- much complexity (a large program in its own right)
-
-Even with Google's massive distributed build system, a large build still takes minutes.
-(In 2007 that binary took 45 minutes; today, 27 minutes.)
-
-Poor quality of life.
-
-* Enter Go
-
-While that build runs, we have time to think.
-
-Want a language to improve the quality of life.
-
-And dependencies are only one such problem....
-
-* Primary considerations
-
-Must work at scale:
-
-- large programs
-- large teams
-- large number of dependencies
-
-Must be familiar, roughly C-like
-
-* Modernize
-
-The old ways are _old_.
-
-Go should be:
-
-- suitable for multicore machines
-- suitable for networked machines
-- suitable for web stuff
-
-* The design of Go
-
-From a software engineering perspective.
-
-* Dependencies in Go
-
-* Dependencies
-
-Dependencies are defined (syntactically) in the language.
-
-Explicit, clear, computable.
-
-	import "encoding/json"
-
-Unused dependencies cause error at compile time.
-
-Efficient: dependencies traversed once per source file...
-
-* Hoisting dependencies
-
-Consider:
-`A` imports `B` imports `C` but `A` does not directly import `C`.
-
-The object code for `B` includes all the information about `C` needed to import `B`.
-Therefore in `A` the line
-
-	import "B"
-
-does not require the compiler to read `C` when compiling `A`.
-
-Also, the object files are designed so the "export" information comes first; compiler doing import does not need to read whole file.
-
-Exponentially less data read than with `#include` files.
-
-With Go in Google, about 40X fanout (recall C++ was 2000x)
-Plus in C++ it's general code that must be parsed; in Go it's just export data.
-
-* No circular imports
-
-Circular imports are illegal in Go.
-
-The big picture in a nutshell:
-
-- occasional minor pain,
-- but great reduction in annoyance overall 
-- structural typing makes it less important than with type hierarchies
-- keeps us honest!
-
-Forces clear demarcation between packages.
-
-Simplifies compilation, linking, initialization.
-
-* API design
-
-Through the design of the standard library, great effort spent on controlling dependencies.
-
-It can be better to copy a little code than to pull in a big library for one function.
-(A test in the system build complains if new core dependencies arise.)
-
-Dependency hygiene trumps code reuse.
-
-Example:
-The (low-level) `net` package has own `itoa` to avoid dependency on the big formatted I/O package.
-
-* Packages
-
-* Packages
-
-Every Go source file, e.g. `"encoding/json/json.go"`, starts
-
-	package json
-
-where `json` is the "package name", an identifier.
-Package names are usually concise.
-
-To use a package, need to identify it by path:
-
-	import "encoding/json"
-
-And then the package name is used to qualify items from package:
-
-	var dec = json.NewDecoder(reader)
-
-Clarity: can always tell if name is local to package from its syntax: `Name` vs. `pkg.Name`.
-(More on this later.)
-
-Package combines properties of library, name space, and module.
-
-* Package paths are unique, not package names
-
-The path is `"encoding/json"` but the package name is `json`.
-The path identifies the package and must be unique.
-Project or company name at root of name space.
-
-		import "google/base/go/log"
-
-Package name might not be unique; can be overridden. These are both `package`log`:
-
-	import "log"                          // Standard package
-	import googlelog "google/base/go/log" // Google-specific package
-
-Every company might have its own `log` package; no need to make the package name unique.
-
-Another: there are many `server` packages in Google's code base.
-
-* Remote packages
-
-Package path syntax works with remote repositories.
-The import path is just a string.
-
-Can be a file, can be a URL:
-
-	go get github.com/4ad/doozer   // Command to fetch package
-
-	import "github.com/4ad/doozer" // Doozer client's import statement
-
-	var client doozer.Conn         // Client's use of package
-
-* Go's Syntax
-
-* Syntax
-
-Syntax is not important...
-
-- unless you're programming
-- or writing tools
-
-Tooling is essential, so Go has a clean syntax.
-Not super small, just clean:
-
-- regular (mostly)
-- only 25 keywords
-- straightforward to parse (no type-specific context required)
-- easy to predict, reason about
-
-* Declarations
-
-Uses Pascal/Modula-style syntax: name before type, more type keywords.
-
-	var fn func([]int) int
-	type T struct { a, b int }
-
-not
-
-	int (*fn)(int[]);
-	struct T { int a, b; }
-
-Easier to parse—no symbol table needed.  Tools become easier to write.
-
-One nice effect: can drop `var` and derive type of variable from expression:
-
-	var buf *bytes.Buffer = bytes.NewBuffer(x) // explicit
-	buf := bytes.NewBuffer(x)                  // derived
-
-For more information:
-
-.link http://golang.org/s/decl-syntax
-
-* Function syntax
-
-Function on type `T`:
-
-	func Abs(t T) float64
-
-Method of type `T`:
-
-	func (t T) Abs() float64
-
-Variable (closure) of type `T`:
-
-	negAbs := func(t T) float64 { return -Abs(t) }
-	
-In Go, functions can return multiple values. Common case: `error`.
-
-	func ReadByte() (c byte, err error)
-
-	c, err := ReadByte()
-	if err != nil { ... }
-
-More about errors later.
-
-* No default arguments
-
-Go does not support default function arguments.
-
-Why not?
-
-- too easy to throw in defaulted args to fix design problems
-- encourages too many args
-- too hard to understand the effect of the fn for different combinations of args
-
-Extra verbosity may happen but that encourages extra thought about names.
-
-Related: Go has easy-to-use, type-safe support for variadic functions.
-
-* Naming
-
-* Export syntax
-
-Simple rule:
-
-- upper case initial letter: `Name` is visible to clients of package
-- otherwise: `name` (or `_Name`) is not visible to clients of package
-
-Applies to variables, types, functions, methods, constants, fields....
-
-That Is It.
-
-Not an easy decision.
-One of the most important things about the language.
-
-Can see the visibility of an identifier without discovering the declaration.
-
-Clarity.
-
-* Scope
-
-Go has very simple scope hierarchy:
-
-- universe
-- package
-- file (for imports only)
-- function
-- block
-
-* Locality of naming
-
-Nuances:
-
-- no implicit `this` in methods (receiver is explicit); always see `rcvr.Field`
-- package qualifier always present for imported names
-- (first component of) every name is always declared in current package
-
-No surprises when importing:
-
-- adding an exported name to my package cannot break your package!
-
-Names do not leak across boundaries.
-
-In C, C++, Java the name `y` could refer to anything
-In Go, `y` (or even `Y`) is always defined within the package.
-In Go, `x.Y` is clear: find `x` locally, `Y` belongs to it.
-
-* Function and method lookup
-
-Method lookup by name only, not type.
-A type cannot have two methods with the same name, ever.
-Easy to identify which function/method is referred to.
-Simple implementation, simpler program, fewer surprises.
-
-Given a method `x.M`, there's only ever one `M` associated with `x`.
-
-* Semantics
-
-* Basics
-
-Generally C-like:
-
-- statically typed
-- procedural
-- compiled
-- pointers etc.
-
-Should feel familiar to programmers from the C family.
-
-* But...
-
-Many small changes in the aid of robustness:
-
-- no pointer arithmetic
-- no implicit numeric conversions
-- array bounds checking
-- no type aliases
-- `++` and `--` as statements not expressions
-- assignment not an expression
-- legal (encouraged even) to take address of stack variable
-- many more
-
-Plus some big ones...
-
-* Bigger things
-
-Some elements of Go step farther from C, even C++ and Java:
-
-- concurrency
-- garbage collection
-- interface types
-- reflection
-- type switches
-
-* Concurrency
-
-* Concurrency
-
-Important to modern computing environment.
-Not well served by C++ or even Java.
-
-Go embodies a variant of CSP with first-class channels.
-
-Why CSP?
-
-- The rest of the language can be ordinary and familiar.
-
-Must be able to couple concurrency with computation.
-
-Example: concurrency and cryptography.
-
-* CSP is practical
-
-For a web server, the canonical Go program, the model is a great fit.
-
-Go _enables_ simple, safe concurrent programming.
-It doesn't _forbid_ bad programming.
-
-Focus on _composition_ of regular code.
-
-Caveat: not purely memory safe; sharing is legal.
-Passing a pointer over a channel is idiomatic.
-
-Experience shows this is a practical design.
-
-* Garbage collection
-
-* The need for garbage collection
-
-Too much programming in C and C++ is about memory allocation.
-But also the design revolves too much about memory management.
-Leaky abstractions, leaky dependencies.
-
-Go has garbage collection, only.
-
-Needed for concurrency: tracking ownership too hard otherwise.
-Important for abstraction: separate behavior from resource management.
-A key part of scalability: APIs remain local.
-
-Use of the language is much simpler because of GC.
-Adds run-time cost, latency, complexity to the implementation.
-
-Day 1 design decision.
-
-* Garbage collection in Go
-
-A garbage-collected systems language is heresy!
-Experience with Java: Uncontrollable cost, too much tuning.
-
-But Go is different.
-Go lets you limit allocation by controlling memory layout.
-
-Example:
-
-	type X struct {
-		a, b, c int
-		buf [256]byte
-	}
-
-Example: Custom arena allocator with free list.
-
-* Interior pointers
-
-Early decision: allow interior pointers such as `X.buf` from previous slide.
-
-Tradeoff: Affects which GC algorithms that can be used, but in return reduces pressure on the collector.
-
-Gives the _programmer_ tools to control GC overhead.
-
-Experience, compared to Java, shows it has significant effect on memory pressure.
-
-GC remains an active subject.
-Current design: parallel mark-and-sweep.
-With care to use memory wisely, works well in production.
-
-* Interfaces
-
-Composition not inheritance
-
-* Object orientation and big software
-
-Go is object-oriented.
-Go does not have classes or subtype inheritance.
-
-What does this mean?
-
-* No type hierarchy
-
-O-O is important because it provides uniformity of interface.
-Outrageous example: the Plan 9 kernel.
-
-Problem:  subtype inheritance encourages _non-uniform_ interfaces.
-
-* O-O and program evolution
-
-Design by type inheritance oversold.
-Generates brittle code.
-Early decisions hard to change, often poorly informed.
-Makes every programmer an interface designer.
-(Plan 9 was built around a single interface everything needed to satisfy.)
-
-Therefore encourages overdesign early on: predict every eventuality.
-Exacerbates the problem, complicates designs.
-
-* Go: interface composition
-
-In Go an interface is _just_ a set of methods:
-
-	type Hash interface {
-		Write(p []byte) (n int, err error)
-		Sum(b []byte) []byte
-		Reset()
-		Size() int
-		BlockSize() int
-	}
-
-No `implements` declaration.
-All hash implementations satisfy this implicitly. (Statically checked.)
-
-* Interfaces in practice: composition
-
-Tend to be small: one or two methods are common.
-
-Composition falls out trivially. Easy example, from package `io`:
-
-	type Reader interface {
-		Read(p []byte) (n int, err error)
-	}
-
-`Reader` (plus the complementary `Writer`) makes it easy to chain:
-
-- files, buffers, networks, encryptors, compressors, GIF, JPEG, PNG, ...
-
-Dependency structure is not a hierarchy; these also implement other interfaces.
-
-Growth through composition is _natural_, does not need to be pre-declared.
-
-And that growth can be _ad_hoc_ and linear.
-
-* Compose with functions, not methods
-
-Hard to overstate the effect that Go's interfaces have on program design.
-
-One big effect: functions with interface arguments.
-
-	func ReadAll(r io.Reader) ([]byte, error)
-
-Wrappers:
-
-	func LoggingReader(r io.Reader) io.Reader
-	func LimitingReader(r io.Reader, n int64) io.Reader
-	func ErrorInjector(r io.Reader) io.Reader
-
-The designs are nothing like hierarchical, subtype-inherited methods.
-Much looser, organic, decoupled, independent.
-
-* Errors
-
-* Error handling
-
-Multiple function return values inform the design for handling errors.
-
-Go has no `try-catch` control structures for exceptions.
-Return `error` instead: built-in interface type that can "stringify" itself:
-
-	type error interface { Error() string }
-
-Clear and simple.
-
-Philosophy:
-
-Forces you think about errors—and deal with them—when they arise.
-Errors are _normal_. Errors are _not_exceptional_.
-Use the existing language to compute based on them.
-Don't need a sublanguage that treats them as exceptional.
-
-Result is better code (if more verbose).
-
-* (OK, not all errors are normal. But most are.)
-
-.image splash/fire.jpg
-
-* Tools
-
-* Tools
-
-Software engineering requires tools.
-
-Go's syntax, package design, naming, etc. make tools easy to write.
-
-Standard library includes lexer and parser; type checker nearly done.
-
-* Gofmt
-
-Always intended to do automatic code formatting.
-Eliminates an entire class of argument.
-Runs as a "presubmit" to the code repositories.
-
-Training:
-
-- The community has always seen `gofmt` output.
-
-Sharing:
-
-- Uniformity of presentation simplifies sharing.
-
-Scaling:
-
-- Less time spent on formatting, more on content.
-
-Often cited as one of Go's best features.
-
-* Gofmt and other tools
-
-Surprise: The existence of `gofmt` enabled _semantic_ tools:
-Can rewrite the tree; `gofmt` will clean up output.
-
-Examples:
-
-- `gofmt`-r`'a[b:len(a)]`->`a[b:]'`
-- `gofix`
-
-And good front-end libraries enable ancillary tools:
-
-- `godoc`
-- `go`get`, `go`build`, etc.
-- `api`
-
-* Gofix
-
-The `gofix` tool allowed us to make sweeping changes to APIs and language features leading up to the release of Go 1.
-
-- change to map deletion syntax
-- new time API
-- many more
-
-Also allows us to _update_ code even if the old code still works.
-
-Recent example:
-
-Changed Go's protocol buffer implementation to use getter functions; updated _all_ Google Go code to use them with `gofix`.
-
-* Conclusion
-
-* Go at Google
-
-Go's use is growing inside Google.
-
-Several big services use it:
-
-- golang.org
-- youtube.com
-- dl.google.com
-
-Many small ones do, many using Google App Engine.
-
-* Go outside Google
-
-Many outside companies use it, including:
-
-- BBC Worldwide
-- Canonical
-- Heroku
-- Nokia
-- SoundCloud
-
-* What's wrong?
-
-Not enough experience yet to know if Go is truly successful.
-Not enough big programs.
-
-Some minor details wrong. Examples:
-
-- declarations still too fussy
-- `nil` is overloaded
-- lots of library details
-
-`Gofix` and `gofmt` gave us the opportunity to fix many problems, ranging from eliminating semicolons to redesigning the `time` package.
-But we're still learning (and the language is frozen for now).
-
-The implementation still needs work, the run-time system in particular.
-
-But all indicators are positive.
-
-* Summary
-
-Software engineering guided the design.
-But a productive, fun language resulted because that design enabled productivity.
-
-Clear dependencies
-Clear syntax
-Clear semantics
-Composition not inheritance
-Simplicity of model (GC, concurrency)
-Easy tooling (the `go` tool, `gofmt`, `godoc`, `gofix`)
-
-* Try it!
-
-.link http://golang.org http://golang.org
-
-.image splash/appenginegophercolor.jpg
-
diff --git a/content/2012/splash/appenginegophercolor.jpg b/content/2012/splash/appenginegophercolor.jpg
deleted file mode 100644
index 43e84fd..0000000
--- a/content/2012/splash/appenginegophercolor.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/splash/datacenter.jpg b/content/2012/splash/datacenter.jpg
deleted file mode 100644
index c2de0f3..0000000
--- a/content/2012/splash/datacenter.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/splash/fire.jpg b/content/2012/splash/fire.jpg
deleted file mode 100644
index 4cdbd6b..0000000
--- a/content/2012/splash/fire.jpg
+++ /dev/null
Binary files differ
diff --git a/content/2012/tutorial.slide b/content/2012/tutorial.slide
deleted file mode 100644
index 48cbecb..0000000
--- a/content/2012/tutorial.slide
+++ /dev/null
@@ -1,642 +0,0 @@
-Get started with Go
-
-Andrew Gerrand
-Google
-https://plus.google.com/106356964679457436995
-@enneff
-http://golang.org
-
-* Background
-
-# In this tutorial I'll show you how to install and use the Go Programming Language.
-
-* What is Go?
-
-Go is a new, general-purpose programming language.
-
-- Compiled
-- Statically typed
-- Concurrent
-- Simple
-- Productive
-
-"Go is a wise, clean, insightful, fresh thinking approach to the greatest-hits subset of the well understood."
-- Michael T. Jones
-
-
-* History
-
-- Project starts at Google in 2007 (by Griesemer, Pike, Thompson)
-- Open source release in November 2009
-- More than 250 contributors join the project
-- Version 1.0 release in March 2012
-
-# Go was originally built by a team at Google, led by Robert Griesemer, Rob Pike, and Ken Thompson. In November 2010, Go was launched publically as an open source project. Since then, a team at Google and more than 250 contributors from the open source community continued to improve the Go language, libraries, and tools.
-
-# In March 2012, we announced Go 1, a version of the language and libraries that will be supported for years to come. 
-
-* Getting started
-
-* Install Go
-
-.link http://golang.org/doc/install
-
-- Install from binary distributions or build from source
-- 32- and 64-bit x86 and ARM processors
-- Windows, Mac OS X, Linux, and FreeBSD
-- Other platforms may be supported by `gccgo`
-
-# Go is available in binary form for Windows, Mac OS X, Linux, and FreeBSD running under 32 and 64-bit x86 processor architectures. To install Go on these systems, download the appropriate file from golang.org and either open the package installer (Windows or OS X) or extract the archive to /usr/local/go (Linux and FreeBSD).  
-
-# If you use a different operating system or processor architecture, you may still be able to use Go by building it from source or using gccgo (an alternate Go compiler based on the GNU C Compiler). See the installation instructions on golang.org for how to do this.
-
-* Test your Go installation
-
-# Let's build and run a simple Go program to check that we have a valid Go install. Create a file named hello.go somewhere convenient and populate it with this Go source code:
-
-Put this code into `hello.go`:
-
-.code tutorial/hello.go
-
-# Now, from a command prompt, run `go run hello.go`. This will build your program, storing the executable binary in a temporary location, and run it. You should see the greeting printed to the console.
-
-Run the program:
-
-  $ go run hello.go
-
-
-* The go tool
-
-The `go` tool is the standard tool for building, testing, and installing Go programs.
-
-Compile and run `hello.go`:
-
-  $ go run hello.go
-
-Run `zip` tests:
-
-  $ go test archive/zip
-
-Build and format the files in the current directory:
-
-  $ go build
-  $ go fmt
-
-Fetch and install `websocket`:
-
-  $ go get code.google.com/p/go.net/websocket 
-
-
-* Workspaces
-
-The `go` tool derives build instructions from Go source code.
-
-There's no need to write and maintain build scripts.
-
-For this to work, some prescribed directory structure, known as a workspace, is required.
-
-  workspace/
-    bin # executable binaries
-    pkg # compiled object files
-    src # source code
-
-* Create a workspace
-
-Create your workspace now.
-
-#I prefer to use the name "gocode", but you can use whatever you like.
-
-  $ mkdir -p $HOME/gocode/src
-
-(The `bin` and `pkg` sub-directories will be created by the `go` tool.)
-
-Tell the `go` tool where your workspace is by setting the `GOPATH` environment variable:
-# You can do this on OS X, Linux, and FreeBSD by adding this line to the `$HOME/.profile` and re-starting any running shells:
-
-  export GOPATH=$HOME/gocode
-
-# See the installation instructions at golang.org for how to set `GOPATH` under Windows.
-
-You may also want to add the `bin` sub-directory of your workspace to your `PATH`:
-
-  export PATH=$PATH:$GOPATH/bin
-
-This lets you run your Go programs without specifying their full path.
-
-(You may want to put these `export` commands in the `.bash_profile` file in your home directory.)
-
-* Choose a namespace
-
-Choose a special place for your Go code.
-
-I use `"github.com/nf"`, the root of my GitHub account (useful with `go get`).
-
-# Once you have chosen a namespace, create the required paths inside the `src` directory of your workspace:
-
-  $ mkdir -p $GOPATH/src/github.com/nf
-
-Create a `hello` directory in your namespace and copy `hello.go` there:
-  
-  $ mkdir $GOPATH/src/github.com/nf/hello
-  $ cp hello.go $GOPATH/src/github.com/nf/hello
-
-Now you can build install the hello program with the `go` tool:
-
-  $ go install github.com/nf/hello
-
-This builds an executable named `hello`, and installs it to the `bin` directory of your workspace.
-
-  $ $GOPATH/bin/hello
-  Hello, fellow gopher
-
-
-* Our project
-
-* Our project
-
-A command-line program that fetches and displays the latest headlines from the `golang` page on Reddit.
-# (Reddit is a huge link aggregation site where people submit links and other people vote on and have discussions about them.)
-
-The program will:
-- make an HTTP request to the Reddit API,
-- decode the JSON response into a Go data structure, and
-- print each link's title, URL, and number of comments.
-
-To get started, create directory inside your namespace called `reddit`:
-
-  $ mkdir $GOPATH/src/github.com/nf/reddit
-  
-This is where you will put your Go source files.
-
-
-* Make an HTTP request
-
-This program makes an HTTP request to the Reddit API and copies its response to standard output.  Put this in a file named `main.go` inside your `reddit` directory.
-
-.code tutorial/1get.go
-
-# If you run it you should see a blob of JSON data, or an error message if something goes wrong.
-
-# There's a lot going on here, so let's break it down. 
-
-
-* Make an HTTP request: package statement
-
-All Go code belongs to a package.
-
-.code tutorial/1get.go /package/
-
-Go programs begin with function `main` inside package `main`.
-
-
-* Make an HTTP request: import statement
-
-The import declaration specifies the file's dependencies.
-
-.code tutorial/1get.go /import/,/\)/
-
-Each string is an import path. It tells the Go tools where to find the package.
-
-These packages are all from the Go standard library.
-
-
-* Make an HTTP request: function declaration
-
-.code tutorial/1get.go /func.main/,/^}/ HLfunc
-
-This is a function declaration. The main function takes no arguments and has no return values.
-
-* Make an HTTP request: http.Get
-
-.code tutorial/1get.go /func.main/,/^}/ HLget
-
-Call the `Get` function from the `http` package, passing the URL of the Reddit API as its only argument.
-
-Declare two variables (`resp` and `err`) and give them the return values of the function call. (Yes, Go functions can return multiple values.) The `Get` function returns `*http.Response` and an `error` values.
-
-
-* Make an HTTP request: error handling
-
-.code tutorial/1get.go /func.main/,/^}/ HLerr
-
-Compare `err` against `nil`, the zero-value for the built-in `error` type.
-
-The `err` variable will be nil if the request was successful.
-
-If not, call the `log.Fatal` function to print the error message and exit the program.
-
-# I cannot overstate the importance of error checking. Disregard error values at your peril!
-
-
-* Make an HTTP request: check status
-
-.code tutorial/1get.go /func.main/,/^}/ HLstatus
-
-Test that the HTTP server returned a "200 OK" response.
-
-If not, bail, printing the HTTP status message ("500 Internal Server Error", for example).
-
-
-* Make an HTTP request: copy
-
-.code tutorial/1get.go /func.main/,/^}/ HLcopy
-
-Use `io.Copy` to copy the HTTP response body  to standard output (`os.Stdout`).
-
-#On the left is a variable assignment that stores the error return value of the Copy in err. Note that this is different to the previous assignment which was also a declaration. This simple assignment - distinguished by the absence of a colon - assigns the second return value of the Copy to the err variable. The first return value, which appears to be assigned to an underscore, is thrown away. The underscore can be thought of as a "write only variable".
-
-  package io
-
-  func Copy(dst Writer, src Reader) (written int64, err error)
-
-The `resp.Body` type implements `io.Reader` and `os.Stdout` implements `io.Writer`.
-
-
-* Decoding the JSON response
-
-* Data structures
-
-The Reddit API returns JSON data like this:
-
-  {"data": {"children": [
-    {"data": {
-      "title": "The Go homepage",
-      "url": "http://golang.org/",
-      ...
-    }},
-    ...
-  ]}}
-
-Go's `json` package decodes JSON-encoded data into native Go data structures. To decode the API response, declare some types that reflect the structure of the JSON data:
-
-.code tutorial/2json.go /type.Item/,$
-
-
-* Decode the response
-
-Instead of copying the HTTP response body to standard output
-
-.code tutorial/1get.go /io.Copy/
-
-we use the json package to decode the response into our Response data structure.
-
-.code tutorial/2json.go /new.Response/,/json.NewDecoder/
-
-Initialize a new `Response` value, store a pointer to it in the new variable `r`.
-
-Create a new `json.Decoder` object and decode the response body into `r`.
-
-As the decoder parses the JSON data it looks for corresponding fields of the same names in the `Response` struct. The `"data"` field of the top-level JSON object is decoded into the `Response` struct's `Data` field, and JSON array `"children"` is decoded into the `Children` slice, and so on.
-
-
-* Print the data
-
-    for _, child := range r.Data.Children {
-      fmt.Println(child.Data.Title)
-    }
-
-Iterate over the `Children` slice, assigning the slice value to `child` on each iteration.
-
-The `Println` call prints the item's `Title` followed by a newline.
-
-
-* Tidying up
-
-* Separation of concerns
-
-So far, all the action happens in the main function.
-
-As the program grows, structure and modularity become important.
-
-What if we want to check several subreddits? Or share this functionality with another program?
-
-Create a function named `Get` that takes the name of subreddit, makes the API call, and returns the items from that subreddit.
-
-.code tutorial/3func.go /func.Get/
-
-`Get` takes a string, `reddit`, and returns a slice of `Item` and an `error` value.
-
-* Get: construct the URL
-
-.code tutorial/3func.go /func.Get/,/^}/ HLurl
-
-Use `fmt.Sprintf` to construct the request URL from the provided `reddit` string.
-
-* Get: return
-
-.code tutorial/3func.go /func.Get/,/^}/ HLreturn
-
-Exiting the function, return a nil slice and a non-nil error value, or vice versa.
-
-* Get: making an error
-
-.code tutorial/3func.go /func.Get/,/^}/ HLerrors
-
-The response's `Status` field is just a string; use the `errors.New` function to convert it to an `error` value.
-
-* Get: defer clean-up work
-
-.code tutorial/3func.go /func.Get/,/^}/ HLclose
-
-Defer a call to the response body's `Close` method, to guarantee that we clean up after the HTTP request. The call will be executed after the function returns.
-
-# It's important to Close the response Body, because it tells the http package that you have finished reading, freeing up the HTTP connection to for re-used (the Go http package uses Keep-Alive and connection pooling by default). If we want to use our Get function in the context of a larger program, it must clean up properly.
-
-# TODO(adg): about defer
-
-* Get: prepare the response
-
-.code tutorial/3func.go /func.Get/,/^}/ HLprepare
-
-Use the make function to allocate an `Item` slice big enough to store the response data.
-
-* Get: convert the response
-
-.code tutorial/3func.go /func.Get/,/^}/ HLconvert
-
-Iterate over the response's `Children` slice, assigning each child's `Data` element to the corresponding element in the items slice.
-
-* Use Get in main
-
-In the `main` function, replace the http request and JSON decoding code with a single call to `Get`.
-
-.code tutorial/3func.go /func.main/,/^}/
-
-The print loop becomes clearer, too.
-
-However, it's not very useful to print only the title of the items. Let's address that.
-
-
-* Formatted output
-
-* The Stringer interface
-
-The `fmt` package knows how to format the built-in types, but it can be told how to format user-defined types, too.
-
-When you pass a value to the `fmt.Print` functions, it checks to see if it implements the `fmt.Stringer` interface:
-
-  type Stringer interface {
-    String() string
-  }
-
-Any type that implements a `String() string` method is a `Stringer`, and the `fmt` package will use that method to format values of that type.
-
-
-* Formatting Items
-
-A method declaration is just like a function declaration, but the receiver comes first.
-
-Here's a `String` method for the `Item` type that returns the title, a newline, and the URL:
-
-  func (i Item) String() string {
-    return fmt.Sprintf("%s\n%s", i.Title, i.URL)
-  }
-
-To print the item we just pass it to Println, which uses the provided `String` method to format the `Item`.
-
-  fmt.Println(item)
-
-
-* Richer formatting (1/2)
-
-Let's go a step further. One way to judge how interesting a link might be is by the discussion surrounding it. Let's display the number of comments for each `Item` as well.
-
-  { "title": "The Go homepage",
-    "url": "http://golang.org/",
-    "num_comments": 10 }
-
-Update the `Item` type to include a `Comments` field:
-
-.code tutorial/4method.go /type.Item/,/^}/
-
-The new `Comments` field has a "struct tag", a string that annotates the field. Go code can use the `reflect` package to inspect this information at runtime.
-
-This tag, `json:"num_comments"`, tells the `json` package to decode the `"num_comments"` field of the JSON object into the `Comments` field (and the reverse, when encoding).
-
-* Richer formatting (2/2)
-
-Now the `String` method can be a little more complex:
-
-.code tutorial/4method.go /func..i.Item..String/,/^}/
-
-Observe that, unlike some languages, Go's switch statements do not fall through by default.
-
-Now when we run our program we should see a nicely formatted list of links.
-
-
-* Packages
-
-* A new package (1/3)
-
-This is useful code. Let's organize it to make it more accessible to others by putting it in an importable package.
-
-Create a new directory inside your `reddit` directory named `geddit`, and copy your `main.go` file there.
-
-`reddit` is the name of the library and `geddit` as that of the command-line client.
-
-  $ cd $GOPATH/src/github.com/nf/reddit
-  $ mkdir geddit
-  $ cp main.go geddit/
-
-Rename the `main.go` inside the `reddit` directory to `reddit.go`. (Not necessary; just a convention.)
-
-  $ mv main.go reddit.go
-
-
-* A new package (2/3)
-
-Change the package statement at the top of `reddit.go` from `package main` to `package reddit`.
-
-It is convention that the package name be the same as the last element of the import path.
-
-The convention makes packages predictable to use:
-
-  import "github.com/nf/reddit"
-
-  func foo() {
-    r, err := reddit.Get("golang") // "reddit" here is the package name
-    // ...
-  }
-
-The only strict requirement is that it must not be `package main`.
-
-Also remove the `main` function from `reddit.go`, and any unused package imports. (The compiler will tell you which packages are unused.)
-
-
-* A new package (3/3)
-
-The `reddit.go` file now looks like this:
-
-  package reddit
-  
-  import (
-    // omitted
-  )
-  
-  type Response struct {
-    // omitted
-  }
-  
-  type Item struct {
-    // omitted
-  }
-  
-  func (i Item) String() string {
-    // omitted
-  }
-  
-  func Get(reddit string) ([]Item, error) {
-    // omitted
-  }
-
-
-* Using the reddit package
-
-Edit the `geddit/main.go` file to remove the `Get`, `Item`, and `Response` declarations, import the `reddit` package, and use the `reddit.` prefix before the `Get` invocation:
-
-.code tutorial/main.go
-
-
-* Documentation
-
-* Documentation (1/3)
-
-`Godoc` is the Go documentation tool. It reads documentation directly from Go source files. It's easy to keep documentation and code in sync when they live together in the same place.
-
-Here's our reddit package when viewed from `godoc`:
-
-  $ godoc github.com/nf/reddit
-  PACKAGE
-  
-  package reddit
-      import "github.com/nf/reddit"
-  
-  FUNCTIONS
-  
-  func Get(reddit string) ([]Item, error)
-  
-  TYPES
-  
-  type Item struct {
-      Title    string
-      URL      string
-      Comments int `json:"num_comments"`
-  }
-  
-  func (i Item) String() string
-
-  type Response struct {
-  	// etc
-
-# Here we see all our top-level declarations. This is our package's user interface (not to be confused with an interface type). Despite the lack of documentation, the one thing that jumps out at me is the Response type. This is an implementation detail, and not something that a user of this package should need to see.
-
-# In Go, top-level declarations beginning with an uppercase letter are "exported", and therefore visible outside the package. All other names are private and inaccessible to code outside the package. We can hide the Response type by simply renaming it to "response".
-
-* Documentation (2/3)
-
-First, hide the `Response` type by renaming it to `response`.
-
-In Go, top-level declarations beginning with an uppercase letter are "exported" (visible outside the package). All other names are private and inaccessible to code outside the package.
-
-To document the remaining visible names, add a comment directly above their declarations:
-
-.code tutorial/reddit/reddit.go /Item.describes/,/type/
-
-.code tutorial/reddit/reddit.go /Get.fetches/,/func/
-
-# It is the convention to begin godoc comments with the noun they describe. This allows the text to be displayed in a variety of contexts, not necessarily alongside the declaration itself.
-
-Most importantly, document the package itself by adding a comment to the package clause:
-
-.code tutorial/reddit/reddit.go /Package.reddit/,/package.reddit/
-
-Don't worry about documenting the `String` method, as all Go programmers should be familiar with it and its purpose.
-
-* Documentation (3/3)
-
-The `godoc` output for our revised package:
-
-  PACKAGE
-  
-  package reddit
-      import "github.com/nf/reddit"
-  
-      Package reddit implements a basic client for the Reddit API.
-  
-  FUNCTIONS
-  
-  func Get(reddit string) ([]Item, error)
-      Get fetches the most recent Items posted to the specified subreddit.
-  
-  TYPES
-  
-  type Item struct {
-      Title    string
-      URL      string
-      Comments int `json:"num_comments"`
-  }
-      Item describes a Reddit item.
-  
-  func (i Item) String() string
-
-# You can also see how it will look on the web by running a local godoc instance
-
-#   $ godoc -http=localhost:8080
-
-# and loading http://localhost:8080/ in your browser.
-
-
-* Sharing your work
-
-* Publish the reddit library
-
-- Add a copyright notice to each file
-- Choose your preferred license
-- Initialize the source control repo
-- Make your first commit
-- Push it to the remote repository
-
-
-* Install with go get
-
-Use the go tool to automatically check out and install Go code:
-
-  $ go get github.com/nf/reddit/geddit
-
-This checks out the repository to `$GOPATH/src/github.com/nf/reddit` and installs the binary to `$GOPATH/bin/geddit`. The `bin` directory is in my PATH, so I can now run:
-
-  $ geddit
-
-The `go get` command can fetch code from
-
-- Bitbucket
-- GitHub
-- Google Code
-- Launchpad
-
-as well as arbitrary Git, Mercurial, Subversion, and Bazaar repositories.
-
-
-* Homework
-
-Some ideas:
-
-- Implement a command-line interface to specify the subreddit(s) to query.
-- Expand the reddit package to support more of the Reddit API.
-- Learn about Go's concurrency primitives and perform multiple requests in parallel.
-
-
-* Where to go from here
-
-Learn Go:
-
-.link http://tour.golang.org 
-
-Documentation and articles:
-
-.link http://golang.org/doc
-
-Standard library reference:
-
-.link http://golang.org/pkg
-
diff --git a/content/2012/tutorial/1get.go b/content/2012/tutorial/1get.go
deleted file mode 100644
index 98b914b..0000000
--- a/content/2012/tutorial/1get.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"io"
-	"log"
-	"net/http"
-	"os"
-)
-
-func main() { // HLfunc
-	resp, err := http.Get("http://reddit.com/r/golang.json") // HLget
-	if err != nil {                                          // HLerr
-		log.Fatal(err) // HLerr
-	} // HLerr
-	if resp.StatusCode != http.StatusOK { // HLstatus
-		log.Fatal(resp.Status) // HLstatus
-	} // HLstatus
-	_, err = io.Copy(os.Stdout, resp.Body) // HLcopy
-	if err != nil {                        // HLerr
-		log.Fatal(err) // HLerr
-	} // HLerr
-} // HLfunc
diff --git a/content/2012/tutorial/2json.go b/content/2012/tutorial/2json.go
deleted file mode 100644
index 0e0bf8f..0000000
--- a/content/2012/tutorial/2json.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// +build ignore,OMIT
-
-package main
-
-import (
-	"encoding/json"
-	"fmt"
-	"log"
-	"net/http"
-)
-
-func main() {
-	resp, err := http.Get("http://reddit.com/r/golang.json")
-	if err != nil {
-		log.Fatal(err)
-	}
-	if resp.StatusCode != http.StatusOK {
-		log.Fatal(resp.Status)
-	}
-	r := new(Response)
-	err = json.NewDecoder(resp.Body).Decode(r)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for _, child := range r.Data.Children {
-		fmt.Println(child.Data.Title)
-	}
-}
-
-type Item struct {
-	Title string
-	URL   string
-}
-
-type Response struct {
-	Data struct {
-		Children []struct {
-			Data Item
-		}
-	}
-}
diff --git a/conten