From baf22e84e7e5b331572d761bdde78f210e7f7380 Mon Sep 17 00:00:00 2001
From: Eli Bendersky for play.golang.org to separate line in the
template
This will make future diffs easier to read because code changes modify the
hash/link, but the image data stays the same.
Note that there are whitespace diffs in the generated files where there
is no image. This is because there was a stray tab in the template before,
and now it's replaced by spaces.
Fixes #235
---
public/arrays | 24 ++++++-----
public/atomic-counters | 26 ++++++------
public/base64-encoding | 22 +++++-----
public/channel-buffering | 18 ++++----
public/channel-directions | 16 +++----
public/channel-synchronization | 22 +++++-----
public/channels | 20 +++++----
public/closing-channels | 20 +++++----
public/closures | 22 +++++-----
public/collection-functions | 44 +++++++++----------
public/command-line-arguments | 20 +++++----
public/command-line-flags | 36 ++++++++--------
public/command-line-subcommands | 28 +++++++------
public/constants | 22 +++++-----
public/defer | 22 +++++-----
public/environment-variables | 20 +++++----
public/epoch | 20 +++++----
public/errors | 34 ++++++++-------
public/execing-processes | 22 +++++-----
public/exit | 22 +++++-----
public/for | 22 +++++-----
public/functions | 24 ++++++-----
public/goroutines | 24 ++++++-----
public/hello-world | 16 +++----
public/http-clients | 18 ++++----
public/http-servers | 24 ++++++-----
public/if-else | 22 +++++-----
public/interfaces | 26 ++++++------
public/json | 46 ++++++++++----------
public/line-filters | 24 ++++++-----
public/maps | 28 +++++++------
public/methods | 24 ++++++-----
public/multiple-return-values | 20 +++++----
public/mutexes | 34 ++++++++-------
public/non-blocking-channel-operations | 18 ++++----
public/number-parsing | 26 ++++++------
public/panic | 20 +++++----
public/pointers | 22 +++++-----
public/random-numbers | 26 ++++++------
public/range | 22 +++++-----
public/range-over-channels | 18 ++++----
public/rate-limiting | 28 +++++++------
public/reading-files | 32 +++++++-------
public/recursion | 14 ++++---
public/regular-expressions | 42 ++++++++++---------
public/select | 20 +++++----
public/sha1-hashes | 24 ++++++-----
public/signals | 20 +++++----
public/slices | 36 ++++++++--------
public/sorting | 18 ++++----
public/sorting-by-functions | 18 ++++----
public/spawning-processes | 28 +++++++------
public/stateful-goroutines | 30 ++++++-------
public/string-formatting | 58 +++++++++++++-------------
public/string-functions | 22 +++++-----
public/structs | 28 +++++++------
public/switch | 20 +++++----
public/tickers | 16 +++----
public/time | 30 ++++++-------
public/time-formatting-parsing | 22 +++++-----
public/timeouts | 20 +++++----
public/timers | 18 ++++----
public/url-parsing | 26 ++++++------
public/values | 18 ++++----
public/variables | 22 +++++-----
public/variadic-functions | 20 +++++----
public/waitgroups | 26 ++++++------
public/worker-pools | 24 ++++++-----
public/writing-files | 36 ++++++++--------
templates/example.tmpl | 4 +-
70 files changed, 922 insertions(+), 782 deletions(-)
diff --git a/public/arrays b/public/arrays
index e4e2d88..9f12e9d 100644
--- a/public/arrays
+++ b/public/arrays
@@ -18,7 +18,7 @@ specific length.
package main
import "fmt"
func main() {
int
s means 0
s.
var a [5]int
fmt.Println("emp:", a)
int
s means 0
s.
a[4] = 100
fmt.Println("set:", a)
fmt.Println("get:", a[4])
@@ -99,7 +101,7 @@ zero-valued, which for int
s means 0
s.
fmt.Println("len:", len(a))
b := [5]int{1, 2, 3, 4, 5}
fmt.Println("dcl:", b)
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
@@ -154,7 +156,7 @@ when printed with fmt.Println
.
$ go run arrays.go
emp: [0 0 0 0 0]
set: [0 0 0 0 100]
@@ -174,7 +176,7 @@ typical Go. We’ll look at slices next.
package main
import "fmt"
import "time"
import "sync/atomic"
@@ -58,7 +60,7 @@ counters accessed by multiple goroutines.
func main() {
var ops uint64
for i := 0; i < 50; i++ {
go func() {
for {
@@ -105,7 +107,7 @@ address of our ops
counter with the
atomic.AddUint64(&ops, 1)
ops
counter with the
time.Sleep(time.Millisecond)
}
}()
@@ -134,7 +136,7 @@ address of our ops
counter with the
time.Sleep(time.Second)
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}
@@ -172,7 +174,7 @@ fetch the value.
$ go run atomic-counters.go
ops: 41419
package main
import b64 "encoding/base64"
import "fmt"
func main() {
data := "abc123!?$*&()'-=@~"
string
to that type.
sEnc := b64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
sDec, _ := b64.StdEncoding.DecodeString(sEnc)
fmt.Println(string(sDec))
fmt.Println()
@@ -117,7 +119,7 @@ format.
uEnc := b64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(uEnc)
uDec, _ := b64.URLEncoding.DecodeString(uEnc)
@@ -140,7 +142,7 @@ but they both decode to the original string as desired.
$ go run base64-encoding.go
YWJjMTIzIT8kKiYoKSctPUB+
abc123!?$*&()'-=@~
@@ -154,7 +156,7 @@ but they both decode to the original string as desired.
YWJjMTIzIT8kKiYoKSctPUB-
abc123!?$*&()'-=@~
package main
import "fmt"
func main() {
messages := make(chan string, 2)
messages <- "buffered"
messages <- "channel"
fmt.Println(<-messages)
fmt.Println(<-messages)
}
@@ -117,7 +119,7 @@ concurrent receive.
$ go run channel-buffering.go
buffered
channel
diff --git a/public/channel-directions b/public/channel-directions
index 5b0150f..02c7c0a 100644
--- a/public/channel-directions
+++ b/public/channel-directions
@@ -20,7 +20,7 @@ the program.
package main
import "fmt"
func ping(pings chan<- string, msg string) {
pings <- msg
}
@@ -73,7 +75,7 @@ receive on this channel.
func pong(pings <-chan string, pongs chan<- string) {
msg := <-pings
pongs <- msg
@@ -88,7 +90,7 @@ receive on this channel.
func main() {
pings := make(chan string, 1)
pongs := make(chan string, 1)
@@ -110,7 +112,7 @@ receive on this channel.
$ go run channel-directions.go
passed message
package main
import "fmt"
import "time"
func worker(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
@@ -75,7 +77,7 @@ goroutine that this function’s work is done.
done <- true
}
func main() {
done := make(chan bool, 1)
go worker(done)
<-done
}
$ go run channel-synchronization.go
working...done
package main
import "fmt"
func main() {
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
@@ -119,7 +121,7 @@ our channel.
$ go run channels.go
ping
package main
import "fmt"
close
the jobs
channel.
func main() {
jobs := make(chan int, 5)
done := make(chan bool)
@@ -78,7 +80,7 @@ all our jobs.
go func() {
for {
j, more := <-jobs
@@ -103,7 +105,7 @@ channel, then closes it.
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("sent job", j)
@@ -123,7 +125,7 @@ we saw earlier.
<-done
}
$ go run closing-channels.go
sent job 1
received job 1
@@ -162,7 +164,7 @@ example: range
over channels.
package main
import "fmt"
func intSeq() func() int {
i := 0
return func() int {
@@ -76,7 +78,7 @@ form a closure.
func main() {
nextInt
.
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
@@ -122,7 +124,7 @@ particular function, create and test a new one.
newInts := intSeq()
fmt.Println(newInts())
}
@@ -140,7 +142,7 @@ particular function, create and test a new one.
$ go run closures.go
1
2
@@ -158,7 +160,7 @@ recursion.
package main
import "strings"
import "fmt"
func Index(vs []string, t string) int {
for i, v := range vs {
if v == t {
@@ -109,7 +111,7 @@ slice.
func Include(vs []string, t string) bool {
return Index(vs, t) >= 0
}
@@ -125,7 +127,7 @@ satisfies the predicate f
.
func Any(vs []string, f func(string) bool) bool {
for _, v := range vs {
if f(v) {
@@ -146,7 +148,7 @@ satisfy the predicate f
.
func All(vs []string, f func(string) bool) bool {
for _, v := range vs {
if !f(v) {
@@ -167,7 +169,7 @@ slice that satisfy the predicate f
.
func Filter(vs []string, f func(string) bool) []string {
vsf := make([]string, 0)
for _, v := range vs {
@@ -189,7 +191,7 @@ the function f
to each string in the original slice.
func Map(vs []string, f func(string) string) []string {
vsm := make([]string, len(vs))
for i, v := range vs {
@@ -207,7 +209,7 @@ the function f
to each string in the original slice.
func main() {
f
to each string in the original slice.
var strs = []string{"peach", "apple", "pear", "plum"}
f
to each string in the original slice.
fmt.Println(Index(strs, "pear"))
f
to each string in the original slice.
fmt.Println(Include(strs, "grape"))
f
to each string in the original slice.
fmt.Println(Any(strs, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
@@ -270,7 +272,7 @@ the function f
to each string in the original slice.
fmt.Println(All(strs, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
@@ -284,7 +286,7 @@ the function f
to each string in the original slice.
fmt.Println(Filter(strs, func(v string) bool {
return strings.Contains(v, "e")
}))
@@ -301,7 +303,7 @@ type.
fmt.Println(Map(strs, strings.ToUpper))
}
$ go run collection-functions.go
2
false
diff --git a/public/command-line-arguments b/public/command-line-arguments
index 5943299..b649bd2 100644
--- a/public/command-line-arguments
+++ b/public/command-line-arguments
@@ -20,7 +20,7 @@ For example, go run hello.go
uses run
and
go run hello.go
uses run
and
package main
go run hello.go
uses run
and
import "os"
import "fmt"
go run hello.go
uses run
and
func main() {
argsWithProg := os.Args
argsWithoutProg := os.Args[1:]
arg := os.Args[3]
fmt.Println(argsWithProg)
fmt.Println(argsWithoutProg)
fmt.Println(arg)
@@ -118,7 +120,7 @@ build a binary with go build
first.
$ go build command-line-arguments.go
$ ./command-line-arguments a b c d
[./command-line-arguments a b c d]
@@ -136,7 +138,7 @@ with flags.
package main
import "flag"
import "fmt"
func main() {
wordPtr := flag.String("word", "foo", "a string")
word
flag.
numbPtr := flag.Int("numb", 42, "an int")
boolPtr := flag.Bool("fork", false, "a bool")
var svar string
flag.StringVar(&svar, "svar", "bar", "a string var")
flag.Parse()
fmt.Println("word:", *wordPtr)
fmt.Println("numb:", *numbPtr)
fmt.Println("fork:", *boolPtr)
@@ -162,7 +164,7 @@ binary directly.
$ go build command-line-flags.go
$ ./command-line-flags -word=opt -numb=7 -fork -svar=flag
word: opt
numb: 7
@@ -195,7 +197,7 @@ their default values.
$ ./command-line-flags -word=opt
word: opt
numb: 42
@@ -214,7 +216,7 @@ any flags.
$ ./command-line-flags -word=opt a1 a2 a3
word: opt
...
@@ -232,7 +234,7 @@ will be interpreted as positional arguments).
$ ./command-line-flags -word=opt a1 a2 a3 -numb=7
word: opt
numb: 42
@@ -251,7 +253,7 @@ generated help text for the command-line program.
$ ./command-line-flags -h
Usage of ./command-line-flags:
-fork=false: a bool
@@ -271,7 +273,7 @@ and show the help text again.
$ ./command-line-flags -wat
flag provided but not defined: -wat
Usage of ./command-line-flags:
@@ -288,7 +290,7 @@ way to parameterize programs.
package main
import (
"flag"
"fmt"
@@ -60,7 +62,7 @@ subcommands that have their own flags.
func main() {
fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
fooEnable := fooCmd.Bool("enable", false, "enable")
fooName := fooCmd.String("name", "", "name")
@@ -91,7 +93,7 @@ supported flags.
barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
barLevel := barCmd.Int("level", 0, "level")
if len(os.Args) < 2 {
fmt.Println("expected 'foo' or 'bar' subcommands")
os.Exit(1)
@@ -122,7 +124,7 @@ to the program.
switch os.Args[1] {
case "foo":
fooCmd.Parse(os.Args[2:])
fmt.Println("subcommand 'foo'")
@@ -167,7 +169,7 @@ have access to trailing positional arguments.
$ go build command-line-subcommands.go
$ ./command-line-subcommands foo -enable -name=joe a1 a2
subcommand 'foo'
enable: true
@@ -197,7 +199,7 @@ have access to trailing positional arguments.
$ ./command-line-subcommands bar -level 8 a1
subcommand 'bar'
level: 8
@@ -213,7 +215,7 @@ have access to trailing positional arguments.
$ ./command-line-subcommands bar -enable a1
flag provided but not defined: -enable
Usage of bar:
diff --git a/public/constants b/public/constants
index bdf3a2f..c564424 100644
--- a/public/constants
+++ b/public/constants
@@ -18,7 +18,7 @@ and numeric values.
package main
import "fmt"
import "math"
const s string = "constant"
func main() {
fmt.Println(s)
const n = 500000000
const d = 3e20 / n
fmt.Println(d)
fmt.Println(int64(d))
fmt.Println(math.Sin(n))
}
$ go run constant.go
constant
6e+11
diff --git a/public/defer b/public/defer
index eeff3b8..43445ec 100644
--- a/public/defer
+++ b/public/defer
@@ -20,7 +20,7 @@ purposes of cleanup. defer
is often used where e.g.
defer
is often used where e.g.
package main
defer
is often used where e.g.
import "fmt"
import "os"
defer
.
func main() {
main
), after
f := createFile("/tmp/defer.txt")
defer closeFile(f)
writeFile(f)
@@ -90,7 +92,7 @@ of the enclosing function (main
), after
func createFile(p string) *os.File {
fmt.Println("creating")
f, err := os.Create(p)
@@ -109,7 +111,7 @@ of the enclosing function (main
), after
func writeFile(f *os.File) {
fmt.Println("writing")
fmt.Fprintln(f, "data")
@@ -123,7 +125,7 @@ of the enclosing function (main
), after
}
main
), after
func closeFile(f *os.File) {
fmt.Println("closing")
f.Close()
@@ -156,7 +158,7 @@ after being written.
$ go run defer.go
creating
writing
diff --git a/public/environment-variables b/public/environment-variables
index e0b7c26..3d2e54c 100644
--- a/public/environment-variables
+++ b/public/environment-variables
@@ -20,7 +20,7 @@ Let’s look at how to set, get, and list environment variables.
package main
import "os"
import "strings"
import "fmt"
@@ -56,7 +58,7 @@ Let’s look at how to set, get, and list environment variables.
func main() {
os.Setenv("FOO", "1")
fmt.Println("FOO:", os.Getenv("FOO"))
fmt.Println("BAR:", os.Getenv("BAR"))
@@ -90,7 +92,7 @@ get the key and value. Here we print all the keys.
fmt.Println()
for _, e := range os.Environ() {
pair := strings.Split(e, "=")
@@ -114,7 +116,7 @@ for FOO
that we set in the program, but that
$ go run environment-variables.go
FOO: 1
BAR:
@@ -130,7 +132,7 @@ particular machine.
TERM_PROGRAM
PATH
SHELL
@@ -147,7 +149,7 @@ program picks that value up.
$ BAR=2 go run environment-variables.go
FOO: 1
BAR: 2
diff --git a/public/epoch b/public/epoch
index 0ae0cf2..46d62e7 100644
--- a/public/epoch
+++ b/public/epoch
@@ -20,7 +20,7 @@ Here’s how to do it in Go.
package main
import "fmt"
import "time"
func main() {
now := time.Now()
secs := now.Unix()
nanos := now.UnixNano()
@@ -88,7 +90,7 @@ divide from nanoseconds.
millis := nanos / 1000000
fmt.Println(secs)
fmt.Println(millis)
@@ -105,7 +107,7 @@ since the epoch into the corresponding time
.
fmt.Println(time.Unix(secs, 0))
fmt.Println(time.Unix(0, nanos))
}
@@ -123,7 +125,7 @@ since the epoch into the corresponding time
.
$ go run epoch.go
2012-10-31 16:13:58.292387 +0000 UTC
1351700038
@@ -143,7 +145,7 @@ parsing and formatting.
package main
import "errors"
import "fmt"
error
, a built-in interface.
func f1(arg int) (int, error) {
if arg == 42 {
return -1, errors.New("can't work with 42")
}
return arg + 3, nil
}
type argError struct {
arg int
prob string
@@ -134,7 +136,7 @@ to explicitly represent an argument error.
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
@@ -148,7 +150,7 @@ to explicitly represent an argument error.
func f2(arg int) (int, error) {
if arg == 42 {
arg
and prob
.
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
@@ -179,7 +181,7 @@ fields arg
and prob
.
func main() {
for _, i := range []int{7, 42} {
if r, e := f1(i); e != nil {
fmt.Println("f1 failed:", e)
@@ -224,7 +226,7 @@ assertion.
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
@@ -245,7 +247,7 @@ assertion.
$ go run errors.go
f1 worked: 10
f1 failed: can't work with 42
@@ -265,7 +267,7 @@ on the Go blog for more on error handling.
package main
import "syscall"
import "os"
import "os/exec"
@@ -61,7 +63,7 @@ function.
func main() {
exec.LookPath
to find it (probably
binary, lookErr := exec.LookPath("ls")
if lookErr != nil {
panic(lookErr)
@@ -96,7 +98,7 @@ be the program name.
args := []string{"ls", "-a", "-l", "-h"}
env := os.Environ()
execErr := syscall.Exec(binary, args, env)
if execErr != nil {
panic(execErr)
@@ -149,7 +151,7 @@ value.
$ go run execing-processes.go
total 16
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
@@ -169,7 +171,7 @@ processes covers most use cases for fork
.
package main
import "fmt"
import "os"
func main() {
fmt.Println
will never be called.
defer fmt.Println("!")
fmt.Println
will never be called.
os.Exit(3)
}
os.Exit
.
go
and printed.
$ go run exit.go
exit status 3
$ go build exit.go
$ ./exit
$ echo $?
@@ -144,7 +146,7 @@ the status in the terminal.
for
loops.
for
loops.
package main
for
loops.
import "fmt"
for
loops.
func main() {
for
loops.
i := 1
for i <= 3 {
fmt.Println(i)
@@ -82,7 +84,7 @@ three basic types of for
loops.
for j := 7; j <= 9; j++ {
fmt.Println(j)
}
@@ -99,7 +101,7 @@ the enclosing function.
for {
fmt.Println("loop")
break
@@ -116,7 +118,7 @@ the loop.
for n := 0; n <= 5; n++ {
if n%2 == 0 {
continue
@@ -138,7 +140,7 @@ the loop.
$ go run for.go
1
2
@@ -163,7 +165,7 @@ structures.
package main
import "fmt"
int
.
func plus(a int, b int) int {
return a + b
}
func plusPlus(a, b, c int) int {
return a + b + c
}
@@ -100,7 +102,7 @@ declares the type.
func main() {
res := plus(1, 2)
fmt.Println("1+2 =", res)
res = plusPlus(1, 2, 3)
fmt.Println("1+2+3 =", res)
}
@@ -145,7 +147,7 @@ declares the type.
$ go run functions.go
1+2 = 3
1+2+3 = 6
@@ -161,7 +163,7 @@ multiple return values, which we’ll look at next.
package main
import "fmt"
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
@@ -67,7 +69,7 @@
func main() {
f("direct")
go f("goroutine")
go func(msg string) {
fmt.Println(msg)
}("going")
@@ -129,7 +131,7 @@ before the program exits.
fmt.Scanln()
fmt.Println("done")
}
@@ -151,7 +153,7 @@ goroutines being run concurrently by the Go runtime.
$ go run goroutines.go
direct : 0
direct : 1
@@ -174,7 +176,7 @@ concurrent Go programs: channels.
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
@@ -62,7 +64,7 @@ use go run
.
$ go run hello-world.go
hello world
go build
.
$ go build hello-world.go
$ ls
hello-world hello-world.go
@@ -92,7 +94,7 @@ binaries. We can do this using go build
.
$ ./hello-world
hello world
package main
import (
"bufio"
"fmt"
@@ -48,7 +50,7 @@ HTTP requests.
func main() {
resp, err := http.Get("http://gobyexample.com")
if err != nil {
panic(err)
@@ -82,7 +84,7 @@ settings.
fmt.Println("Response status:", resp.Status)
scanner := bufio.NewScanner(resp.Body)
for i := 0; scanner.Scan() && i < 5; i++ {
fmt.Println(scanner.Text())
@@ -110,7 +112,7 @@ settings.
if err := scanner.Err(); err != nil {
panic(err)
}
@@ -129,7 +131,7 @@ settings.
$ go run http-clients.go
Response status: 200 OK
<!DOCTYPE html>
diff --git a/public/http-servers b/public/http-servers
index 958ddc3..2dedf1a 100644
--- a/public/http-servers
+++ b/public/http-servers
@@ -18,7 +18,9 @@
package main
import (
"fmt"
"net/http"
@@ -50,7 +52,7 @@ on functions with the appropriate signature.
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
func headers(w http.ResponseWriter, req *http.Request) {
for name, headers := range req.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
@@ -112,7 +114,7 @@ headers and echoing them into the response body.
func main() {
http.HandleFunc("/hello", hello)
http.HandleFunc("/headers", headers)
http.ListenAndServe(":8090", nil)
}
$ go run http-servers.go &
$ curl localhost:8090/hello
hello
package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
@@ -82,7 +84,7 @@ straight-forward.
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
@@ -99,7 +101,7 @@ branches.
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
@@ -120,7 +122,7 @@ in Go, but that the braces are required.
$ go run if-else.go
7 is odd
8 is divisible by 4
@@ -152,7 +154,7 @@ for basic conditions.
package main
import "fmt"
import "math"
type geometry interface {
area() float64
perim() float64
@@ -71,7 +73,7 @@ signatures.
type rect struct {
width, height float64
}
@@ -91,7 +93,7 @@ implement geometry
on rect
s.
func (r rect) area() float64 {
return r.width * r.height
}
@@ -109,7 +111,7 @@ implement geometry
on rect
s.
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
@@ -130,7 +132,7 @@ to work on any geometry
.
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
@@ -146,7 +148,7 @@ to work on any geometry
.
func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}
@@ -164,7 +166,7 @@ these structs as arguments to measure
.
measure(r)
measure(c)
}
@@ -182,7 +184,7 @@ these structs as arguments to measure
.
$ go run interfaces.go
{3 4}
12
@@ -202,7 +204,7 @@ these structs as arguments to measure
.
package main
import "encoding/json"
import "fmt"
import "os"
@@ -57,7 +59,7 @@ decoding of custom types below.
type response1 struct {
Page int
Fruits []string
@@ -76,7 +78,7 @@ decoding of custom types below.
func main() {
bolB, _ := json.Marshal(true)
fmt.Println(string(bolB))
intB, _ := json.Marshal(1)
fmt.Println(string(intB))
fltB, _ := json.Marshal(2.34)
fmt.Println(string(fltB))
strB, _ := json.Marshal("gopher")
fmt.Println(string(strB))
slcD := []string{"apple", "peach", "pear"}
slcB, _ := json.Marshal(slcD)
fmt.Println(string(slcB))
@@ -159,7 +161,7 @@ to JSON arrays and objects as you’d expect.
mapD := map[string]int{"apple": 5, "lettuce": 7}
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
@@ -177,7 +179,7 @@ use those names as the JSON keys.
res1D := &response1{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
@@ -197,7 +199,7 @@ of such tags.
res2D := &response2{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
@@ -216,7 +218,7 @@ structure.
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
var dat map[string]interface{}
if err := json.Unmarshal(byt, &dat); err != nil {
panic(err)
}
@@ -265,7 +267,7 @@ the expected float64
type.
num := dat["num"].(float64)
fmt.Println(num)
strs := dat["strs"].([]interface{})
str1 := strs[0].(string)
fmt.Println(str1)
@@ -299,7 +301,7 @@ data.
str := `{"page": 1, "fruits": ["apple", "peach"]}`
res := response2{}
json.Unmarshal([]byte(str), &res)
@@ -320,7 +322,7 @@ stream JSON encodings directly to os.Writer
s like
enc := json.NewEncoder(os.Stdout)
d := map[string]int{"apple": 5, "lettuce": 7}
enc.Encode(d)
@@ -339,7 +341,7 @@ stream JSON encodings directly to os.Writer
s like
$ go run json.go
true
1
@@ -369,7 +371,7 @@ for more.
package main
import (
"bufio"
"fmt"
@@ -62,7 +64,7 @@ pattern to write your own Go line filters.
func main() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
ucl := strings.ToUpper(scanner.Text())
fmt.Println(ucl)
}
Scan
as an error.
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
@@ -154,7 +156,7 @@ lowercase lines.
$ echo 'hello' > /tmp/lines
$ echo 'filter' >> /tmp/lines
$ cat /tmp/lines | go run line-filters.go
HELLO
FILTER
diff --git a/public/maps b/public/maps
index afa0567..bf31208 100644
--- a/public/maps
+++ b/public/maps
@@ -18,7 +18,7 @@
package main
import "fmt"
func main() {
m := make(map[string]int)
m["k1"] = 7
m["k2"] = 13
fmt.Println("map:", m)
v1 := m["k1"]
fmt.Println("v1: ", v1)
fmt.Println("len:", len(m))
delete(m, "k2")
fmt.Println("map:", m)
_, prs := m["k2"]
fmt.Println("prs:", prs)
n := map[string]int{"foo": 1, "bar": 2}
fmt.Println("map:", n)
}
@@ -192,7 +194,7 @@ printed with fmt.Println
.
$ go run maps.go
map: map[k1:7 k2:13]
v1: 7
diff --git a/public/methods b/public/methods
index 2638234..c1ae6d0 100644
--- a/public/methods
+++ b/public/methods
@@ -17,7 +17,7 @@
package main
import "fmt"
type rect struct {
width, height int
}
@@ -66,7 +68,7 @@
func (r *rect) area() int {
return r.width * r.height
}
@@ -82,7 +84,7 @@ receiver types. Here’s an example of a value receiver.
func (r rect) perim() int {
return 2*r.width + 2*r.height
}
@@ -96,7 +98,7 @@ receiver types. Here’s an example of a value receiver.
func main() {
r := rect{width: 10, height: 5}
fmt.Println("area: ", r.area())
fmt.Println("perim:", r.perim())
rp := &r
fmt.Println("area: ", rp.area())
fmt.Println("perim:", rp.perim())
@@ -147,7 +149,7 @@ receiving struct.
$ go run methods.go
area: 50
perim: 30
@@ -165,7 +167,7 @@ naming related sets of methods: interfaces.
package main
import "fmt"
int
s.
func vals() (int, int) {
return 3, 7
}
@@ -69,7 +71,7 @@ the function returns 2 int
s.
func main() {
a, b := vals()
fmt.Println(a)
fmt.Println(b)
@@ -99,7 +101,7 @@ use the blank identifier _
.
_, c := vals()
fmt.Println(c)
}
@@ -117,7 +119,7 @@ use the blank identifier _
.
$ go run multiple-return-values.go
3
7
@@ -134,7 +136,7 @@ feature of Go functions; we’ll look at this next.
package main
import (
"fmt"
"math/rand"
@@ -60,7 +62,7 @@ to safely access data across multiple goroutines.
func main() {
var state = make(map[int]int)
var mutex = &sync.Mutex{}
var readOps uint64
var writeOps uint64
for r := 0; r < 100; r++ {
go func() {
total := 0
@@ -137,7 +139,7 @@ the readOps
count.
key := rand.Intn(5)
mutex.Lock()
total += state[key]
@@ -154,7 +156,7 @@ the readOps
count.
time.Sleep(time.Millisecond)
}
}()
@@ -171,7 +173,7 @@ using the same pattern we did for reads.
for w := 0; w < 10; w++ {
go func() {
for {
@@ -197,7 +199,7 @@ using the same pattern we did for reads.
time.Sleep(time.Second)
readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps)
@@ -226,7 +228,7 @@ using the same pattern we did for reads.
mutex.Lock()
fmt.Println("state:", state)
mutex.Unlock()
@@ -248,7 +250,7 @@ using the same pattern we did for reads.
$ go run mutexes.go
readOps: 83285
writeOps: 8320
@@ -265,7 +267,7 @@ management task using only goroutines and channels.
select
s.
select
s.
package main
select
s.
import "fmt"
select
s.
func main() {
messages := make(chan string)
signals := make(chan bool)
@@ -72,7 +74,7 @@ it will immediately take the default
case.
select {
case msg := <-messages:
fmt.Println("received message", msg)
@@ -93,7 +95,7 @@ Therefore the default
case is selected.
msg := "hi"
select {
case messages <- msg:
@@ -115,7 +117,7 @@ on both messages
and signals
.
select {
case msg := <-messages:
fmt.Println("received message", msg)
@@ -139,7 +141,7 @@ on both messages
and signals
.
$ go run non-blocking-channel-operations.go
no message received
no message sent
diff --git a/public/number-parsing b/public/number-parsing
index 0e509da..35e768e 100644
--- a/public/number-parsing
+++ b/public/number-parsing
@@ -18,7 +18,7 @@ in many programs; here’s how to do it in Go.
package main
import "strconv"
import "fmt"
func main() {
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f)
i, _ := strconv.ParseInt("123", 0, 64)
fmt.Println(i)
d, _ := strconv.ParseInt("0x1c8", 0, 64)
fmt.Println(d)
u, _ := strconv.ParseUint("789", 0, 64)
fmt.Println(u)
k, _ := strconv.Atoi("135")
fmt.Println(k)
_, e := strconv.Atoi("wat")
fmt.Println(e)
}
@@ -160,7 +162,7 @@ bits.
$ go run number-parsing.go
1.234
123
@@ -179,7 +181,7 @@ bits.
package main
import "os"
func main() {
panic("a problem")
_, err := os.Create("/tmp/file")
if err != nil {
panic(err)
@@ -108,7 +110,7 @@ a non-zero status.
$ go run panic.go
panic: a problem
goroutine 1 [running]:
main.main()
/.../panic.go:12 +0x47
@@ -140,7 +142,7 @@ to use error-indicating return values wherever possible.
package main
import "fmt"
func zeroval(ival int) {
ival = 0
}
@@ -78,7 +80,7 @@ value at the referenced address.
func zeroptr(iptr *int) {
*iptr = 0
}
@@ -92,7 +94,7 @@ value at the referenced address.
func main() {
i := 1
fmt.Println("initial:", i)
@@ -106,7 +108,7 @@ value at the referenced address.
zeroval(i)
fmt.Println("zeroval:", i)
i
.
zeroptr(&i)
fmt.Println("zeroptr:", i)
i
.
fmt.Println("pointer:", &i)
}
$ go run pointers.go
initial: 1
zeroval: 1
diff --git a/public/random-numbers b/public/random-numbers
index 393d10c..5de950f 100644
--- a/public/random-numbers
+++ b/public/random-numbers
@@ -19,7 +19,7 @@ generation.
package main
import "time"
import "fmt"
import "math/rand"
@@ -55,7 +57,7 @@ generation.
func main() {
fmt.Print(rand.Intn(100), ",")
fmt.Print(rand.Intn(100))
fmt.Println()
@@ -85,7 +87,7 @@ generation.
fmt.Println(rand.Float64())
5.0 <= f' < 10.0
.
fmt.Print((rand.Float64()*5)+5, ",")
fmt.Print((rand.Float64() * 5) + 5)
fmt.Println()
@@ -118,7 +120,7 @@ intend to be secret, use crypto/rand
for those.
s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
rand
package.
fmt.Print(r1.Intn(100), ",")
fmt.Print(r1.Intn(100))
fmt.Println()
@@ -149,7 +151,7 @@ produces the same sequence of random numbers.
s2 := rand.NewSource(42)
r2 := rand.New(s2)
fmt.Print(r2.Intn(100), ",")
@@ -174,7 +176,7 @@ produces the same sequence of random numbers.
$ go run random-numbers.go
81,87
0.6645600532184904
@@ -195,7 +197,7 @@ that Go can provide.
package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
@@ -89,7 +91,7 @@ the indexes though.
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
@@ -106,7 +108,7 @@ the indexes though.
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
@@ -122,7 +124,7 @@ the indexes though.
for k := range kvs {
fmt.Println("key:", k)
}
@@ -139,7 +141,7 @@ of the rune
and the second the rune
itself.
for i, c := range "go" {
fmt.Println(i, c)
}
@@ -158,7 +160,7 @@ of the rune
and the second the rune
itself.
$ go run range.go
sum: 9
index: 1
diff --git a/public/range-over-channels b/public/range-over-channels
index 36222c6..a3ba422 100644
--- a/public/range-over-channels
+++ b/public/range-over-channels
@@ -20,7 +20,7 @@ values received from a channel.
package main
import "fmt"
func main() {
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
@@ -86,7 +88,7 @@ receiving the 2 elements.
for elem := range queue {
fmt.Println(elem)
}
@@ -105,7 +107,7 @@ receiving the 2 elements.
$ go run range-over-channels.go
one
two
@@ -122,7 +124,7 @@ values be received.
package main
import "time"
import "fmt"
func main() {
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
@@ -91,7 +93,7 @@ our rate limiting scheme.
limiter := time.Tick(200 * time.Millisecond)
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
@@ -126,7 +128,7 @@ channel will allow bursts of up to 3 events.
burstyLimiter := make(chan time.Time, 3)
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
@@ -155,7 +157,7 @@ value to burstyLimiter
, up to its limit of 3.
go func() {
for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t
@@ -174,7 +176,7 @@ of burstyLimiter
.
burstyRequests := make(chan int, 5)
for i := 1; i <= 5; i++ {
burstyRequests <- i
@@ -201,7 +203,7 @@ handled once every ~200 milliseconds as desired.
$ go run rate-limiting.go
request 1 2012-10-19 00:38:18.687438 +0000 UTC
request 2 2012-10-19 00:38:18.887471 +0000 UTC
@@ -221,7 +223,7 @@ then serve the remaining 2 with ~200ms delays each.
request 1 2012-10-19 00:38:20.487578 +0000 UTC
request 2 2012-10-19 00:38:20.487645 +0000 UTC
request 3 2012-10-19 00:38:20.487676 +0000 UTC
diff --git a/public/reading-files b/public/reading-files
index 1b08728..d51206c 100644
--- a/public/reading-files
+++ b/public/reading-files
@@ -19,7 +19,7 @@ reading files.
package main
import (
"bufio"
"fmt"
@@ -61,7 +63,7 @@ This helper will streamline our error checks below.
func check(e error) {
if e != nil {
panic(e)
@@ -77,7 +79,7 @@ This helper will streamline our error checks below.
func main() {
dat, err := ioutil.ReadFile("/tmp/dat")
check(err)
fmt.Print(string(dat))
@@ -108,7 +110,7 @@ by Open
ing a file to obtain an os.File
value.
f, err := os.Open("/tmp/dat")
check(err)
b1 := make([]byte, 5)
n1, err := f.Read(b1)
check(err)
@@ -141,7 +143,7 @@ and Read
from there.
o2, err := f.Seek(6, 0)
check(err)
b2 := make([]byte, 2)
@@ -163,7 +165,7 @@ implemented with ReadAtLeast
.
o3, err := f.Seek(6, 0)
check(err)
b3 := make([]byte, 2)
@@ -182,7 +184,7 @@ accomplishes this.
_, err = f.Seek(0, 0)
check(err)
r4 := bufio.NewReader(f)
b4, err := r4.Peek(5)
check(err)
@@ -217,7 +219,7 @@ be scheduled immediately after Open
ing with
f.Close()
}
Open
ing with
$ echo "hello" > /tmp/dat
$ echo "go" >> /tmp/dat
$ go run reading-files.go
@@ -255,7 +257,7 @@ be scheduled immediately after Open
ing with
package main
import "fmt"
fact(0)
.
func fact(n int) int {
if n == 0 {
return 1
@@ -72,7 +74,7 @@ base case of fact(0)
.
func main() {
fmt.Println(fact(7))
}
@@ -90,7 +92,7 @@ base case of fact(0)
.
$ go run recursion.go
5040
package main
import "bytes"
import "fmt"
import "regexp"
@@ -55,7 +57,7 @@ in Go.
func main() {
match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
fmt.Println(match)
Regexp
struct.
r, _ := regexp.Compile("p([a-z]+)ch")
fmt.Println(r.MatchString("peach"))
fmt.Println(r.FindString("peach punch"))
fmt.Println(r.FindStringIndex("peach punch"))
p([a-z]+)ch
and ([a-z]+)
.
fmt.Println(r.FindStringSubmatch("peach punch"))
fmt.Println(r.FindStringSubmatchIndex("peach punch"))
fmt.Println(r.FindAllString("peach punch pinch", -1))
fmt.Println(r.FindAllStringSubmatchIndex(
"peach punch pinch", -1))
fmt.Println(r.FindAllString("peach punch pinch", 2))
fmt.Println(r.Match([]byte("peach")))
r = regexp.MustCompile("p([a-z]+)ch")
fmt.Println(r)
fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
in := []byte("a peach")
out := r.ReplaceAllFunc(in, bytes.ToUpper)
fmt.Println(string(out))
@@ -281,7 +283,7 @@ text with a given function.
$ go run regular-expressions.go
true
true
@@ -308,7 +310,7 @@ the regexp
package docs
package main
import "time"
import "fmt"
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
@@ -104,7 +106,7 @@ simultaneously, printing each one as it arrives.
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
@@ -130,7 +132,7 @@ expected.
$ time go run select.go
received one
received two
@@ -147,7 +149,7 @@ concurrently.
real 0m2.245s
package main
import "crypto/sha1"
import "fmt"
func main() {
s := "sha1 this string"
h := sha1.New()
[]byte(s)
to coerce it to bytes.
h.Write([]byte(s))
bs := h.Sum(nil)
fmt.Println(s)
fmt.Printf("%x\n", bs)
}
@@ -139,7 +141,7 @@ a human-readable hex format.
$ go run sha1-hashes.go
sha1 this string
cf23df2207d99a74fbe169e3eba035e633b65d94
@@ -156,7 +158,7 @@ import crypto/md5
and use md5.New()
.
package main
import "fmt"
import "os"
import "os/signal"
@@ -59,7 +61,7 @@ Here’s how to handle signals in Go with channels.
func main() {
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println()
@@ -125,7 +127,7 @@ above sending a value on done
) and then exit.
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
@@ -148,7 +150,7 @@ causing the program to print interrupt
and then exit.
$ go run signals.go
awaiting signal
^C
diff --git a/public/slices b/public/slices
index 18acb11..fba69c9 100644
--- a/public/slices
+++ b/public/slices
@@ -18,7 +18,7 @@ powerful interface to sequences than arrays.
package main
import "fmt"
func main() {
make
. Here we make a slice of
s := make([]string, 3)
fmt.Println("emp:", s)
make
. Here we make a slice of
s[0] = "a"
s[1] = "b"
s[2] = "c"
@@ -100,7 +102,7 @@ the builtin make
. Here we make a slice of
fmt.Println("len:", len(s))
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println("apd:", s)
@@ -135,7 +137,7 @@ into c
from s
.
c := make([]string, len(s))
copy(c, s)
fmt.Println("cpy:", c)
@@ -152,7 +154,7 @@ of the elements s[2]
, s[3]
, and s[4]
.
l := s[2:5]
fmt.Println("sl1:", l)
s[2]
, s[3]
, and s[4]
.
l = s[:5]
fmt.Println("sl2:", l)
s[2]
, s[3]
, and s[4]
.
l = s[2:]
fmt.Println("sl3:", l)
t := []string{"g", "h", "i"}
fmt.Println("dcl:", t)
twoD := make([][]int, 3)
for i := 0; i < 3; i++ {
innerLen := i + 1
@@ -238,7 +240,7 @@ they are rendered similarly by fmt.Println
.
$ go run slices.go
emp: [ ]
set: [a b c]
@@ -264,7 +266,7 @@ implementation of slices in Go.
package main
import "fmt"
import "sort"
func main() {
strs := []string{"c", "a", "b"}
sort.Strings(strs)
fmt.Println("Strings:", strs)
@@ -85,7 +87,7 @@ return a new one.
ints := []int{7, 2, 4}
sort.Ints(ints)
fmt.Println("Ints: ", ints)
@@ -101,7 +103,7 @@ already in sorted order.
s := sort.IntsAreSorted(ints)
fmt.Println("Sorted: ", s)
}
@@ -121,7 +123,7 @@ slices and true
as the result of our AreSorted
test.
$ go run sorting.go
Strings: [a b c]
Ints: [2 4 7]
diff --git a/public/sorting-by-functions b/public/sorting-by-functions
index 5daf9d4..92c0f41 100644
--- a/public/sorting-by-functions
+++ b/public/sorting-by-functions
@@ -21,7 +21,7 @@ in Go.
package main
import "sort"
import "fmt"
type byLength []string
len(s[i])
and len(s[j])
here.
func (s byLength) Len() int {
return len(s)
}
@@ -103,7 +105,7 @@ slice.
func main() {
fruits := []string{"peach", "banana", "kiwi"}
sort.Sort(byLength(fruits))
@@ -125,7 +127,7 @@ length, as desired.
$ go run sorting-by-functions.go
[kiwi peach banana]
package main
import "fmt"
import "io/ioutil"
import "os/exec"
@@ -58,7 +60,7 @@ of spawning processes from Go.
func main() {
dateCmd := exec.Command("date")
dateOut, err := dateCmd.Output()
if err != nil {
panic(err)
@@ -110,7 +112,7 @@ where we pipe data to the external process on its
grepCmd := exec.Command("grep", "hello")
grepIn, _ := grepCmd.StdinPipe()
grepOut, _ := grepCmd.StdoutPipe()
grepCmd.Start()
@@ -149,7 +151,7 @@ exactly the same way.
fmt.Println("> grep hello")
fmt.Println(string(grepBytes))
lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
lsOut, err := lsCmd.Output()
if err != nil {
@@ -193,7 +195,7 @@ as if we had run them directly from the command-line.
$ go run spawning-processes.go
> date
Wed Oct 10 09:53:11 PDT 2012
@@ -207,7 +209,7 @@ as if we had run them directly from the command-line.
> grep hello
hello grep
> ls -a -l -h
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
diff --git a/public/stateful-goroutines b/public/stateful-goroutines
index f684680..a14245a 100644
--- a/public/stateful-goroutines
+++ b/public/stateful-goroutines
@@ -24,7 +24,7 @@ by exactly 1 goroutine.
package main
import (
"fmt"
"math/rand"
@@ -71,7 +73,7 @@ goroutine to respond.
type readOp struct {
key int
resp chan int
@@ -91,7 +93,7 @@ goroutine to respond.
func main() {
var readOps uint64
var writeOps uint64
reads := make(chan readOp)
writes := make(chan writeOp)
reads
).
go func() {
var state = make(map[int]int)
for {
@@ -170,7 +172,7 @@ result over the provided resp
channel.
for r := 0; r < 100; r++ {
go func() {
for {
@@ -196,7 +198,7 @@ approach.
for w := 0; w < 10; w++ {
go func() {
for {
@@ -222,7 +224,7 @@ approach.
time.Sleep(time.Second)
readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps)
@@ -258,7 +260,7 @@ total operations.
$ go run stateful-goroutines.go
readOps: 71708
writeOps: 7177
@@ -280,7 +282,7 @@ program.
package main
import "fmt"
import "os"
type point struct {
x, y int
}
@@ -68,7 +70,7 @@ common string formatting tasks.
func main() {
point
struct.
p := point{1, 2}
fmt.Printf("%v\n", p)
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
fmt.Printf("%T\n", p)
fmt.Printf("%t\n", true)
%d
for standard, base-10 formatting.
fmt.Printf("%d\n", 123)
%d
for standard, base-10 formatting.
fmt.Printf("%b\n", 14)
fmt.Printf("%c\n", 33)
fmt.Printf("%x\n", 456)
%f
.
fmt.Printf("%f\n", 78.9)
fmt.Printf("%e\n", 123400000.0)
fmt.Printf("%E\n", 123400000.0)
fmt.Printf("%s\n", "\"string\"")
fmt.Printf("%q\n", "\"string\"")
fmt.Printf("%x\n", "hex this")
fmt.Printf("%p\n", &p)
fmt.Printf("|%6d|%6d|\n", 12, 345)
fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
fmt.Printf("|%6s|%6s|\n", "foo", "b")
fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
s := fmt.Sprintf("a %s", "string")
fmt.Println(s)
fmt.Fprintf(os.Stderr, "an %s\n", "error")
}
$ go run string-formatting.go
{1 2}
{x:1 y:2}
diff --git a/public/string-functions b/public/string-functions
index 1fdf4cf..73b6019 100644
--- a/public/string-functions
+++ b/public/string-functions
@@ -19,7 +19,7 @@ to give you a sense of the package.
package main
import s "strings"
import "fmt"
var p = fmt.Println
func main() {
p("Contains: ", s.Contains("test", "es"))
p("Count: ", s.Count("test", "t"))
p("HasPrefix: ", s.HasPrefix("test", "te"))
@@ -114,7 +116,7 @@ bytes and getting a byte by index.
p("Len: ", len("hello"))
p("Char:", "hello"[1])
}
@@ -134,7 +136,7 @@ for more information.
$ go run string-functions.go
Contains: true
Count: 2
@@ -172,7 +174,7 @@ for more information.
Len: 5
Char: 101
package main
import "fmt"
type person struct {
name string
age int
@@ -69,7 +71,7 @@ records.
func main() {
fmt.Println(person{"Bob", 20})
fmt.Println(person{name: "Alice", age: 30})
fmt.Println(person{name: "Fred"})
fmt.Println(&person{name: "Ann", age: 40})
s := person{name: "Sean", age: 50}
fmt.Println(s.name)
sp := &s
fmt.Println(sp.age)
sp.age = 51
fmt.Println(sp.age)
}
@@ -181,7 +183,7 @@ pointers are automatically dereferenced.
$ go run structs.go
{Bob 20}
{Alice 30}
diff --git a/public/switch b/public/switch
index 37200b3..c739ea3 100644
--- a/public/switch
+++ b/public/switch
@@ -18,7 +18,7 @@ branches.
package main
import "fmt"
import "time"
func main() {
i := 2
fmt.Print("Write ", i, " as ")
switch i {
@@ -90,7 +92,7 @@ in the same case
statement. We use the optional
switch time.Now().Weekday() {
case time.Saturday, time.Sunday:
fmt.Println("It's the weekend")
@@ -110,7 +112,7 @@ to express if/else logic. Here we also show how the
t := time.Now()
switch {
case t.Hour() < 12:
@@ -132,7 +134,7 @@ type corresponding to its clause.
whatAmI := func(i interface{}) {
switch t := i.(type) {
case bool:
@@ -161,7 +163,7 @@ type corresponding to its clause.
$ go run switch.go
Write 2 as two
It's a weekday
diff --git a/public/tickers b/public/tickers
index 0ea1840..64f1044 100644
--- a/public/tickers
+++ b/public/tickers
@@ -21,7 +21,7 @@ periodically until we stop it.
package main
import "time"
import "fmt"
func main() {
ticker := time.NewTicker(500 * time.Millisecond)
go func() {
for t := range ticker.C {
@@ -92,7 +94,7 @@ channel. We’ll stop ours after 1600ms.
time.Sleep(1600 * time.Millisecond)
ticker.Stop()
fmt.Println("Ticker stopped")
@@ -113,7 +115,7 @@ before we stop it.
$ go run tickers.go
Tick at 2012-09-23 11:29:56.487625 -0700 PDT
Tick at 2012-09-23 11:29:56.988063 -0700 PDT
diff --git a/public/time b/public/time
index e5c1fe4..443f568 100644
--- a/public/time
+++ b/public/time
@@ -18,7 +18,7 @@ here are some examples.
package main
import "fmt"
import "time"
func main() {
p := fmt.Println
now := time.Now()
p(now)
Location
, i.e. time zone.
then := time.Date(
2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
p(then)
@@ -99,7 +101,7 @@ value as expected.
p(then.Year())
p(then.Month())
p(then.Day())
@@ -119,7 +121,7 @@ value as expected.
p(then.Weekday())
p(then.Before(now))
p(then.After(now))
p(then.Equal(now))
@@ -150,7 +152,7 @@ the interval between two times.
diff := now.Sub(then)
p(diff)
p(diff.Hours())
p(diff.Minutes())
p(diff.Seconds())
@@ -183,7 +185,7 @@ duration.
p(then.Add(diff))
p(then.Add(-diff))
}
@@ -201,7 +203,7 @@ duration.
$ go run time.go
2012-10-31 15:50:13.793654 +0000 UTC
2009-11-17 20:34:58.651387237 +0000 UTC
@@ -236,7 +238,7 @@ the Unix epoch.
package main
import "fmt"
import "time"
func main() {
p := fmt.Println
t := time.Now()
p(t.Format(time.RFC3339))
t1, e := time.Parse(
time.RFC3339,
"2012-11-01T22:08:41+00:00")
@@ -105,7 +107,7 @@ The example time must be exactly as shown: the year 2006,
p(t.Format("3:04PM"))
p(t.Format("Mon Jan _2 15:04:05 2006"))
p(t.Format("2006-01-02T15:04:05.999999-07:00"))
@@ -125,7 +127,7 @@ components of the time value.
fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
t.Year(), t.Month(), t.Day(),
t.Hour(), t.Minute(), t.Second())
@@ -141,7 +143,7 @@ explaining the parsing problem.
ansic := "Mon Jan _2 15:04:05 2006"
_, e = time.Parse(ansic, "8:41PM")
p(e)
@@ -160,7 +162,7 @@ explaining the parsing problem.
$ go run time-formatting-parsing.go
2014-04-15T18:00:15-07:00
2012-11-01 22:08:41 +0000 +0000
diff --git a/public/timeouts b/public/timeouts
index aa20120..449446a 100644
--- a/public/timeouts
+++ b/public/timeouts
@@ -20,7 +20,7 @@ elegant thanks to channels and select
.
select
.
package main
select
.
import "time"
import "fmt"
select
.
func main() {
c1 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
@@ -92,7 +94,7 @@ if the operation takes more than the allowed 1s.
select {
case res := <-c1:
fmt.Println(res)
@@ -111,7 +113,7 @@ from c2
will succeed and we’ll print the result.
c2 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
@@ -140,7 +142,7 @@ out and the second succeeding.
$ go run timeouts.go
timeout 1
result 2
@@ -159,7 +161,7 @@ examples of this next: timers and tickers.
package main
import "time"
import "fmt"
func main() {
timer1 := time.NewTimer(2 * time.Second)
<-timer1.C
fmt.Println("Timer 1 expired")
timer2 := time.NewTimer(time.Second)
go func() {
<-timer2.C
@@ -132,7 +134,7 @@ a chance to expire.
$ go run timers.go
Timer 1 expired
Timer 2 stopped
diff --git a/public/url-parsing b/public/url-parsing
index efe547c..8b17377 100644
--- a/public/url-parsing
+++ b/public/url-parsing
@@ -18,7 +18,7 @@ Here’s how to parse URLs in Go.
package main
import "fmt"
import "net"
import "net/url"
@@ -54,7 +56,7 @@ Here’s how to parse URLs in Go.
func main() {
s := "postgres://user:pass@host.com:5432/path?k=v#f"
u, err := url.Parse(s)
if err != nil {
panic(err)
@@ -98,7 +100,7 @@ query params, and query fragment.
fmt.Println(u.Scheme)
fmt.Println(u.User)
fmt.Println(u.User.Username())
p, _ := u.User.Password()
@@ -130,7 +132,7 @@ if present. Use SplitHostPort
to extract them.
fmt.Println(u.Host)
host, port, _ := net.SplitHostPort(u.Host)
fmt.Println(host)
@@ -147,7 +149,7 @@ the #
.
fmt.Println(u.Path)
fmt.Println(u.Fragment)
fmt.Println(u.RawQuery)
m, _ := url.ParseQuery(u.RawQuery)
fmt.Println(m)
@@ -187,7 +189,7 @@ pieces that we extracted.
$ go run url-parsing.go
postgres
user:pass
diff --git a/public/values b/public/values
index 57317d7..38966a3 100644
--- a/public/values
+++ b/public/values
@@ -19,7 +19,7 @@ basic examples.
package main
import "fmt"
func main() {
fmt.Println("go" + "lang")
fmt.Println("1+1 =", 1+1)
fmt.Println("7.0/3.0 =", 7.0/3.0)
fmt.Println(true && false)
fmt.Println(true || false)
fmt.Println(!true)
@@ -112,7 +114,7 @@ basic examples.
$ go run values.go
golang
1+1 = 2
diff --git a/public/variables b/public/variables
index a10e9c0..9c1156a 100644
--- a/public/variables
+++ b/public/variables
@@ -19,7 +19,7 @@ calls.
package main
import "fmt"
func main() {
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
int
is 0
.
var e int
fmt.Println(e)
f := "apple"
fmt.Println(f)
}
@@ -144,7 +146,7 @@ initializing a variable, e.g. for
$ go run variables.go
initial
1 2
diff --git a/public/variadic-functions b/public/variadic-functions
index b789f72..75ce887 100644
--- a/public/variadic-functions
+++ b/public/variadic-functions
@@ -20,7 +20,7 @@ function.
package main
import "fmt"
int
s as arguments.
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
@@ -75,7 +77,7 @@ of int
s as arguments.
func main() {
sum(1, 2)
sum(1, 2, 3)
nums := []int{1, 2, 3, 4}
sum(nums...)
}
@@ -123,7 +125,7 @@ apply them to a variadic function using
$ go run variadic-functions.go
[1 2] 3
[1 2 3] 6
@@ -140,7 +142,7 @@ to form closures, which we’ll look at next.
package main
import (
"fmt"
"sync"
@@ -59,7 +61,7 @@ pointer.
func worker(id int, wg *sync.WaitGroup) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
wg.Done()
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg)
@@ -145,7 +147,7 @@ all the workers notified they’re done.
wg.Wait()
}
$ go run waitgroups.go
Worker 5 starting
Worker 3 starting
@@ -186,7 +188,7 @@ is likely to be different for each invocation.
package main
import "fmt"
import "time"
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Println("worker", id, "started job", j)
@@ -77,7 +79,7 @@ simulate an expensive task.
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
@@ -123,7 +125,7 @@ channel to indicate that’s all the work we have.
for j := 1; j <= 5; j++ {
jobs <- j
}
@@ -142,7 +144,7 @@ goroutines is to use a WaitGroup.
for a := 1; a <= 5; a++ {
<-results
}
@@ -165,7 +167,7 @@ there are 3 workers operating concurrently.
$ time go run worker-pools.go
worker 1 started job 1
worker 2 started job 2
@@ -187,7 +189,7 @@ there are 3 workers operating concurrently.
real 0m2.358s
package main
import (
"bufio"
"fmt"
@@ -57,7 +59,7 @@ ones we saw earlier for reading.
func check(e error) {
if e != nil {
panic(e)
@@ -73,7 +75,7 @@ ones we saw earlier for reading.
func main() {
d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
check(err)
@@ -102,7 +104,7 @@ bytes) into a file.
f, err := os.Create("/tmp/dat2")
check(err)
defer f.Close()
d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
check(err)
@@ -146,7 +148,7 @@ after opening a file.
n3, err := f.WriteString("writes\n")
fmt.Printf("wrote %d bytes\n", n3)
f.Sync()
w := bufio.NewWriter(f)
n4, err := w.WriteString("buffered\n")
fmt.Printf("wrote %d bytes\n", n4)
@@ -190,7 +192,7 @@ been applied to the underlying writer.
w.Flush()
}
$ go run writing-files.go
wrote 5 bytes
wrote 7 bytes
@@ -235,7 +237,7 @@ been applied to the underlying writer.
$ cat /tmp/dat1
hello
go
@@ -255,7 +257,7 @@ we’ve just seen to the stdin
and stdout
streams.