From 45080c435bcdafbe2a53072c29186fd892021f4f Mon Sep 17 00:00:00 2001 From: oohira Date: Sat, 14 Jan 2017 00:28:38 +0900 Subject: [PATCH 001/133] Add style to 'append' function --- examples/slices/slices.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/slices/slices.go b/examples/slices/slices.go index 1918f98..521d1af 100644 --- a/examples/slices/slices.go +++ b/examples/slices/slices.go @@ -30,7 +30,7 @@ func main() { // arrays. One is the builtin `append`, which // returns a slice containing one or more new values. // Note that we need to accept a return value from - // append as we may get a new slice value. + // `append` as we may get a new slice value. s = append(s, "d") s = append(s, "e", "f") fmt.Println("apd:", s) From 8dcf72d27d66757cc87681ee389569059cd76e73 Mon Sep 17 00:00:00 2001 From: oohira Date: Sat, 14 Jan 2017 00:32:51 +0900 Subject: [PATCH 002/133] Replace `Println` with `fmt.Println` --- examples/maps/maps.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/maps/maps.go b/examples/maps/maps.go index 425532e..2ed1363 100644 --- a/examples/maps/maps.go +++ b/examples/maps/maps.go @@ -16,7 +16,7 @@ func main() { m["k1"] = 7 m["k2"] = 13 - // Printing a map with e.g. `Println` will show all of + // Printing a map with e.g. `fmt.Println` will show all of // its key/value pairs. fmt.Println("map:", m) From d4b81ba058abb97e76431538c0aeb929dedaa254 Mon Sep 17 00:00:00 2001 From: oohira Date: Sat, 14 Jan 2017 00:34:14 +0900 Subject: [PATCH 003/133] Replace `ints` with `int`s --- examples/variadic-functions/variadic-functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variadic-functions/variadic-functions.go b/examples/variadic-functions/variadic-functions.go index 8277bea..5ee4ef2 100644 --- a/examples/variadic-functions/variadic-functions.go +++ b/examples/variadic-functions/variadic-functions.go @@ -8,7 +8,7 @@ package main import "fmt" // Here's a function that will take an arbitrary number -// of `ints` as arguments. +// of `int`s as arguments. func sum(nums ...int) { fmt.Print(nums, " ") total := 0 From 5f9b7a263d131981fb16c81a4d7910f68f093e1b Mon Sep 17 00:00:00 2001 From: oohira Date: Sat, 14 Jan 2017 00:36:06 +0900 Subject: [PATCH 004/133] Add style to 'nil' and Remove redundant space --- examples/errors/errors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/errors/errors.go b/examples/errors/errors.go index 48ee27e..72a20b0 100644 --- a/examples/errors/errors.go +++ b/examples/errors/errors.go @@ -23,7 +23,7 @@ func f1(arg int) (int, error) { } - // A nil value in the error position indicates that + // A `nil` value in the error position indicates that // there was no error. return arg + 3, nil } @@ -74,7 +74,7 @@ func main() { } // If you want to programmatically use the data in - // a custom error, you'll need to get the error as an + // a custom error, you'll need to get the error as an // instance of the custom error type via type // assertion. _, e := f2(42) From c99a949b23e0eee5c7248aed3f7ba35896744710 Mon Sep 17 00:00:00 2001 From: Xingan Wang Date: Sat, 18 Nov 2017 00:18:14 -0800 Subject: [PATCH 005/133] update Chinese version info --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index abe01e7..3a2ef56 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The Go Gopher is copyright [Renée French](http://reneefrench.blogspot.com/) and Contributor translations of the Go by Example site are available in: -* [Chinese](http://gobyexample.everyx.in/) by [everyx](https://github.com/everyx) +* [Chinese](https://gobyexample.xgwang.me/) by [xg-wang](https://github.com/xg-wang/gobyexample) * [French](http://le-go-par-l-exemple.keiruaprod.fr) by [keirua](https://github.com/keirua/gobyexample) * [Italian](http://gobyexample.it) by the [Go Italian community](https://github.com/golangit/gobyexample-it) * [Spanish](http://goconejemplos.com) by the [Go Mexico community](https://github.com/dabit/gobyexample) From c867632ebfee02b91314fc564b29dfd19cca839a Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:25:29 -0800 Subject: [PATCH 006/133] boilerplate golang bios script --- bios.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 bios.sh diff --git a/bios.sh b/bios.sh new file mode 100755 index 0000000..1250f42 --- /dev/null +++ b/bios.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +mkdir -p src/$PKG && cd src/$PKG +run -s "Cloning" git clone $URL --branch $REF --single-branch . +git reset --hard $SHA + +PKGS=$(go list $PKG/...) +run -s "Linting" golint -set_exit_status $PKGS +run -s "Vetting" go vet -x $PKGS +run -s "Building" go build -v $PKGS +run -s "Testing" go test -v $PKGS From 116b4c734125291c79104cd882edd216156f4308 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:46:33 -0800 Subject: [PATCH 007/133] exported types should have comment (golint) --- tools/generate.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/generate.go b/tools/generate.go index 6bb3184..adccc7b 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -118,12 +118,14 @@ func debug(msg string) { var docsPat = regexp.MustCompile("^\\s*(\\/\\/|#)\\s") var dashPat = regexp.MustCompile("\\-+") +// Seg is a segment of an example type Seg struct { Docs, DocsRendered string Code, CodeRendered string CodeEmpty, CodeLeading, CodeRun bool } +// Example is info extracted from an example file type Example struct { Id, Name string GoCode, GoCodeHash, UrlHash string From 13a5dea6a788dfed74ddf070ef7e39fca1c6ff33 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:48:48 -0800 Subject: [PATCH 008/133] Id should be ID (golint) --- tools/generate.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/generate.go b/tools/generate.go index adccc7b..6f17c84 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -127,7 +127,7 @@ type Seg struct { // Example is info extracted from an example file type Example struct { - Id, Name string + ID, Name string GoCode, GoCodeHash, UrlHash string Segs [][]*Seg NextExample *Example @@ -222,14 +222,14 @@ func parseExamples() []*Example { for _, exampleName := range exampleNames { if (exampleName != "") && !strings.HasPrefix(exampleName, "#") { example := Example{Name: exampleName} - exampleId := strings.ToLower(exampleName) - exampleId = strings.Replace(exampleId, " ", "-", -1) - exampleId = strings.Replace(exampleId, "/", "-", -1) - exampleId = strings.Replace(exampleId, "'", "", -1) - exampleId = dashPat.ReplaceAllString(exampleId, "-") - example.Id = exampleId + exampleID := strings.ToLower(exampleName) + exampleID = strings.Replace(exampleID, " ", "-", -1) + exampleID = strings.Replace(exampleID, "/", "-", -1) + exampleID = strings.Replace(exampleID, "'", "", -1) + exampleID = dashPat.ReplaceAllString(exampleID, "-") + example.ID = exampleID example.Segs = make([][]*Seg, 0) - sourcePaths := mustGlob("examples/" + exampleId + "/*") + sourcePaths := mustGlob("examples/" + exampleID + "/*") for _, sourcePath := range sourcePaths { if strings.HasSuffix(sourcePath, ".hash") { example.GoCodeHash, example.UrlHash = parseHashFile(sourcePath) @@ -243,7 +243,7 @@ func parseExamples() []*Example { } newCodeHash := sha1Sum(example.GoCode) if example.GoCodeHash != newCodeHash { - example.UrlHash = resetUrlHashFile(newCodeHash, example.GoCode, "examples/"+example.Id+"/"+example.Id+".hash") + example.UrlHash = resetUrlHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") } examples = append(examples, &example) } @@ -270,7 +270,7 @@ func renderExamples(examples []*Example) { _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) check(err) for _, example := range examples { - exampleF, err := os.Create(siteDir + "/" + example.Id) + exampleF, err := os.Create(siteDir + "/" + example.ID) check(err) exampleTmpl.Execute(exampleF, example) } From d5a7560cdcdfc749f8f04d598bceb1046496c616 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:51:01 -0800 Subject: [PATCH 009/133] Url should be URL (golint) --- tools/generate.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/generate.go b/tools/generate.go index 6f17c84..56362b4 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -128,7 +128,7 @@ type Seg struct { // Example is info extracted from an example file type Example struct { ID, Name string - GoCode, GoCodeHash, UrlHash string + GoCode, GoCodeHash, URLHash string Segs [][]*Seg NextExample *Example } @@ -138,7 +138,7 @@ func parseHashFile(sourcePath string) (string, string) { return lines[0], lines[1] } -func resetUrlHashFile(codehash, code, sourcePath string) string { +func resetURLHashFile(codehash, code, sourcePath string) string { payload := strings.NewReader(code) resp, err := http.Post("https://play.golang.org/share", "text/plain", payload) if err != nil { @@ -232,7 +232,7 @@ func parseExamples() []*Example { sourcePaths := mustGlob("examples/" + exampleID + "/*") for _, sourcePath := range sourcePaths { if strings.HasSuffix(sourcePath, ".hash") { - example.GoCodeHash, example.UrlHash = parseHashFile(sourcePath) + example.GoCodeHash, example.URLHash = parseHashFile(sourcePath) } else { sourceSegs, filecontents := parseAndRenderSegs(sourcePath) if filecontents != "" { @@ -243,7 +243,7 @@ func parseExamples() []*Example { } newCodeHash := sha1Sum(example.GoCode) if example.GoCodeHash != newCodeHash { - example.UrlHash = resetUrlHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") + example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") } examples = append(examples, &example) } From 08b8a982487149fcfdf13c34640351e320616028 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:52:01 -0800 Subject: [PATCH 010/133] remove unreachable code (go vet) --- tools/generate.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/generate.go b/tools/generate.go index 56362b4..700f447 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -106,7 +106,6 @@ func whichLexer(path string) string { return "console" } panic("No lexer for " + path) - return "" } func debug(msg string) { From e83d23555c2f00a9d0046fccca9c27a3cf83e861 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:55:12 -0800 Subject: [PATCH 011/133] customize build --- bios.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bios.sh b/bios.sh index 1250f42..772ccd3 100755 --- a/bios.sh +++ b/bios.sh @@ -5,8 +5,10 @@ mkdir -p src/$PKG && cd src/$PKG run -s "Cloning" git clone $URL --branch $REF --single-branch . git reset --hard $SHA -PKGS=$(go list $PKG/...) +go get github.com/russross/blackfriday + +PKGS=$(go list $PKG/... | grep -v examples) run -s "Linting" golint -set_exit_status $PKGS run -s "Vetting" go vet -x $PKGS -run -s "Building" go build -v $PKGS +run -s "Building" tools/build run -s "Testing" go test -v $PKGS From fd573c309521427f407dd689e5344b29ec4d2804 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 08:55:25 -0800 Subject: [PATCH 012/133] no tests --- bios.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/bios.sh b/bios.sh index 772ccd3..353ef84 100755 --- a/bios.sh +++ b/bios.sh @@ -11,4 +11,3 @@ PKGS=$(go list $PKG/... | grep -v examples) run -s "Linting" golint -set_exit_status $PKGS run -s "Vetting" go vet -x $PKGS run -s "Building" tools/build -run -s "Testing" go test -v $PKGS From de34a8a2af7ac35efc416cabfa352f9fff24324e Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:21:58 -0800 Subject: [PATCH 013/133] drop 0 from declaration (golint) --- examples/atomic-counters/atomic-counters.go | 2 +- examples/mutexes/mutexes.go | 4 ++-- examples/stateful-goroutines/stateful-goroutines.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/atomic-counters/atomic-counters.go b/examples/atomic-counters/atomic-counters.go index 72f2396..0f3a52e 100644 --- a/examples/atomic-counters/atomic-counters.go +++ b/examples/atomic-counters/atomic-counters.go @@ -15,7 +15,7 @@ func main() { // We'll use an unsigned integer to represent our // (always-positive) counter. - var ops uint64 = 0 + var ops uint64 // To simulate concurrent updates, we'll start 50 // goroutines that each increment the counter about diff --git a/examples/mutexes/mutexes.go b/examples/mutexes/mutexes.go index c2068b2..20dab28 100644 --- a/examples/mutexes/mutexes.go +++ b/examples/mutexes/mutexes.go @@ -23,8 +23,8 @@ func main() { // We'll keep track of how many read and write // operations we do. - var readOps uint64 = 0 - var writeOps uint64 = 0 + var readOps uint64 + var writeOps uint64 // Here we start 100 goroutines to execute repeated // reads against the state, once per millisecond in diff --git a/examples/stateful-goroutines/stateful-goroutines.go b/examples/stateful-goroutines/stateful-goroutines.go index eb2ff79..20b0923 100644 --- a/examples/stateful-goroutines/stateful-goroutines.go +++ b/examples/stateful-goroutines/stateful-goroutines.go @@ -37,8 +37,8 @@ type writeOp struct { func main() { // As before we'll count how many operations we perform. - var readOps uint64 = 0 - var writeOps uint64 = 0 + var readOps uint64 + var writeOps uint64 // The `reads` and `writes` channels will be used by // other goroutines to issue read and write requests, From 2faeae3aa638492d8f43d7d1c1bcf64e3d886ede Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:23:36 -0800 Subject: [PATCH 014/133] omit type from declaration (golint) --- examples/variables/variables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variables/variables.go b/examples/variables/variables.go index 72a5327..13b371c 100644 --- a/examples/variables/variables.go +++ b/examples/variables/variables.go @@ -9,7 +9,7 @@ import "fmt" func main() { // `var` declares 1 or more variables. - var a string = "initial" + var a = "initial" fmt.Println(a) // You can declare multiple variables at once. From 080d71ef9c11600098efa4505c02bfeb27e952bf Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:28:53 -0800 Subject: [PATCH 015/133] i++ (golint) --- examples/closures/closures.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/closures/closures.go b/examples/closures/closures.go index 1fbe36b..195a1ef 100644 --- a/examples/closures/closures.go +++ b/examples/closures/closures.go @@ -14,7 +14,7 @@ import "fmt" func intSeq() func() int { i := 0 return func() int { - i += 1 + i++ return i } } From ee20cfb5435060b59793059db7bbaf565cb7d3d4 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:34:36 -0800 Subject: [PATCH 016/133] exported function comment (golint) --- .../collection-functions/collection-functions.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/collection-functions/collection-functions.go b/examples/collection-functions/collection-functions.go index 1b2b237..1e217d5 100644 --- a/examples/collection-functions/collection-functions.go +++ b/examples/collection-functions/collection-functions.go @@ -21,7 +21,7 @@ package main import "strings" import "fmt" -// Returns the first index of the target string `t`, or +// Index returns the first index of the target string `t`, or // -1 if no match is found. func Index(vs []string, t string) int { for i, v := range vs { @@ -32,13 +32,13 @@ func Index(vs []string, t string) int { return -1 } -// Returns `true` if the target string t is in the +// Include returns `true` if the target string t is in the // slice. func Include(vs []string, t string) bool { return Index(vs, t) >= 0 } -// Returns `true` if one of the strings in the slice +// Any returns `true` if one of the strings in the slice // satisfies the predicate `f`. func Any(vs []string, f func(string) bool) bool { for _, v := range vs { @@ -49,7 +49,7 @@ func Any(vs []string, f func(string) bool) bool { return false } -// Returns `true` if all of the strings in the slice +// All returns `true` if all of the strings in the slice // satisfy the predicate `f`. func All(vs []string, f func(string) bool) bool { for _, v := range vs { @@ -60,7 +60,7 @@ func All(vs []string, f func(string) bool) bool { return true } -// Returns a new slice containing all strings in the +// Filter returns a new slice containing all strings in the // slice that satisfy the predicate `f`. func Filter(vs []string, f func(string) bool) []string { vsf := make([]string, 0) @@ -72,7 +72,7 @@ func Filter(vs []string, f func(string) bool) []string { return vsf } -// Returns a new slice containing the results of applying +// Map returns a new slice containing the results of applying // the function `f` to each string in the original slice. func Map(vs []string, f func(string) string) []string { vsm := make([]string, len(vs)) From ee5400dc9f2b0d788bf92c3948b3a7d460be2bad Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:35:38 -0800 Subject: [PATCH 017/133] dont export types (golint) --- examples/json/json.go | 10 +++++----- .../sorting-by-functions/sorting-by-functions.go | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/json/json.go b/examples/json/json.go index b3853f2..475ffe5 100644 --- a/examples/json/json.go +++ b/examples/json/json.go @@ -10,11 +10,11 @@ import "os" // We'll use these two structs to demonstrate encoding and // decoding of custom types below. -type Response1 struct { +type response1 struct { Page int Fruits []string } -type Response2 struct { +type response2 struct { Page int `json:"page"` Fruits []string `json:"fruits"` } @@ -50,7 +50,7 @@ func main() { // custom data types. It will only include exported // fields in the encoded output and will by default // use those names as the JSON keys. - res1D := &Response1{ + res1D := &response1{ Page: 1, Fruits: []string{"apple", "peach", "pear"}} res1B, _ := json.Marshal(res1D) @@ -60,7 +60,7 @@ func main() { // to customize the encoded JSON key names. Check the // definition of `Response2` above to see an example // of such tags. - res2D := &Response2{ + res2D := &response2{ Page: 1, Fruits: []string{"apple", "peach", "pear"}} res2B, _ := json.Marshal(res2D) @@ -103,7 +103,7 @@ func main() { // need for type assertions when accessing the decoded // data. str := `{"page": 1, "fruits": ["apple", "peach"]}` - res := Response2{} + res := response2{} json.Unmarshal([]byte(str), &res) fmt.Println(res) fmt.Println(res.Fruits[0]) diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index 3564da9..f68c298 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -13,7 +13,7 @@ import "fmt" // corresponding type. Here we've created a `ByLength` // type that is just an alias for the builtin `[]string` // type. -type ByLength []string +type byLength []string // We implement `sort.Interface` - `Len`, `Less`, and // `Swap` - on our type so we can use the `sort` package's @@ -22,22 +22,22 @@ type ByLength []string // hold the actual custom sorting logic. In our case we // want to sort in order of increasing string length, so // we use `len(s[i])` and `len(s[j])` here. -func (s ByLength) Len() int { +func (s byLength) Len() int { return len(s) } -func (s ByLength) Swap(i, j int) { +func (s byLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s ByLength) Less(i, j int) bool { +func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) } // With all of this in place, we can now implement our // custom sort by casting the original `fruits` slice to -// `ByLength`, and then use `sort.Sort` on that typed +// `byLength`, and then use `sort.Sort` on that typed // slice. func main() { fruits := []string{"peach", "banana", "kiwi"} - sort.Sort(ByLength(fruits)) + sort.Sort(byLength(fruits)) fmt.Println(fruits) } From db3bf49cddfceb26a714968894f8b23911f486c2 Mon Sep 17 00:00:00 2001 From: Noah Zoschke Date: Fri, 26 Jan 2018 09:37:05 -0800 Subject: [PATCH 018/133] lint and vet examples, with a few exceptions --- bios.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bios.sh b/bios.sh index 353ef84..cd16a0a 100755 --- a/bios.sh +++ b/bios.sh @@ -7,7 +7,10 @@ git reset --hard $SHA go get github.com/russross/blackfriday -PKGS=$(go list $PKG/... | grep -v examples) +PKGS=$(go list $PKG/... | grep -v examples/variables) run -s "Linting" golint -set_exit_status $PKGS + +PKGS=$(go list $PKG/... | grep -v examples/panic) run -s "Vetting" go vet -x $PKGS + run -s "Building" tools/build From 451160492a7f6b37e124714e0900b5860e68b4ea Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:09:53 -0500 Subject: [PATCH 019/133] Check for template errors --- tools/generate.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/generate.go b/tools/generate.go index 700f447..ee5db8d 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -261,7 +261,8 @@ func renderIndex(examples []*Example) { check(err) indexF, err := os.Create(siteDir + "/index.html") check(err) - indexTmpl.Execute(indexF, examples) + err = indexTmpl.Execute(indexF, examples) + check(err) } func renderExamples(examples []*Example) { From bbab9ca96843b3d0789bc5e7113ded3f606e5bd6 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:11:22 -0500 Subject: [PATCH 020/133] Update templates to reflect new structs --- templates/example.tmpl | 8 ++++---- templates/index.tmpl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/example.tmpl b/templates/example.tmpl index dabad82..8315df7 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -18,7 +18,7 @@ } -
+

Go by Example: {{.Name}}

{{range .Segs}} @@ -28,7 +28,7 @@ {{.DocsRendered}} @@ -37,11 +37,11 @@ {{end}} {{if .NextExample}}

- Next example: {{.NextExample.Name}}. + Next example: {{.NextExample.Name}}.

{{end}} diff --git a/templates/index.tmpl b/templates/index.tmpl index 9c5c02f..313904d 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -35,7 +35,7 @@ diff --git a/public/closures b/public/closures index 1591a76..12d2443 100644 --- a/public/closures +++ b/public/closures @@ -42,7 +42,7 @@ a function inline without having to name it.

@@ -116,7 +116,7 @@ helper function.

@@ -132,7 +132,7 @@ slice.

@@ -153,7 +153,7 @@ satisfies the predicate f.

@@ -174,7 +174,7 @@ satisfy the predicate f.

@@ -196,7 +196,7 @@ slice that satisfy the predicate f.

diff --git a/public/json b/public/json index 7c6528e..5cd6e90 100644 --- a/public/json +++ b/public/json @@ -41,7 +41,7 @@ data types.

diff --git a/public/sorting-by-functions b/public/sorting-by-functions index f610b59..710700f 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -43,7 +43,7 @@ in Go.

@@ -92,13 +92,13 @@ we use len(s[i]) and len(s[j]) here.

@@ -118,7 +118,7 @@ slice.

func main() {
     fruits := []string{"peach", "banana", "kiwi"}
-    sort.Sort(ByLength(fruits))
+    sort.Sort(byLength(fruits))
     fmt.Println(fruits)
 }
 
diff --git a/public/stateful-goroutines b/public/stateful-goroutines index fdf3e10..aa0579e 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -46,7 +46,7 @@ by exactly 1 goroutine.

diff --git a/public/variables b/public/variables index 222135d..856f4c5 100644 --- a/public/variables +++ b/public/variables @@ -41,7 +41,7 @@ calls.

@@ -230,7 +230,7 @@ idiom in Go code.

diff --git a/public/slices b/public/slices index 21a827d..412b741 100644 --- a/public/slices +++ b/public/slices @@ -40,7 +40,7 @@ powerful interface to sequences than arrays.

From 01a5f6de689fa9f0ce0b7acfd35529ad86a07fc7 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 9 Feb 2018 14:14:25 -0800 Subject: [PATCH 038/133] Use more idiomatic * for intervals --- examples/rate-limiting/rate-limiting.go | 4 ++-- examples/rate-limiting/rate-limiting.hash | 4 ++-- examples/select/select.go | 4 ++-- examples/select/select.hash | 4 ++-- examples/tickers/tickers.go | 4 ++-- examples/tickers/tickers.hash | 4 ++-- examples/timeouts/timeouts.go | 8 ++++---- examples/timeouts/timeouts.hash | 4 ++-- examples/timers/timers.go | 2 +- examples/timers/timers.hash | 4 ++-- public/rate-limiting | 6 +++--- public/select | 6 +++--- public/tickers | 6 +++--- public/timeouts | 10 +++++----- public/timers | 4 ++-- 15 files changed, 37 insertions(+), 37 deletions(-) diff --git a/examples/rate-limiting/rate-limiting.go b/examples/rate-limiting/rate-limiting.go index 8a131cb..f5eea19 100644 --- a/examples/rate-limiting/rate-limiting.go +++ b/examples/rate-limiting/rate-limiting.go @@ -24,7 +24,7 @@ func main() { // This `limiter` channel will receive a value // every 200 milliseconds. This is the regulator in // our rate limiting scheme. - limiter := time.Tick(time.Millisecond * 200) + limiter := time.Tick(200 * time.Millisecond) // By blocking on a receive from the `limiter` channel // before serving each request, we limit ourselves to @@ -49,7 +49,7 @@ func main() { // Every 200 milliseconds we'll try to add a new // value to `burstyLimiter`, up to its limit of 3. go func() { - for t := range time.Tick(time.Millisecond * 200) { + for t := range time.Tick(200 * time.Millisecond) { burstyLimiter <- t } }() diff --git a/examples/rate-limiting/rate-limiting.hash b/examples/rate-limiting/rate-limiting.hash index 81be22f..ccbbc49 100644 --- a/examples/rate-limiting/rate-limiting.hash +++ b/examples/rate-limiting/rate-limiting.hash @@ -1,2 +1,2 @@ -b8dbdb8d53386f00ff900fea62db400d962b4834 -h9TUTv494TN +edad78bf3b36ddc9bec30b344b8a72be4de90f3b +l4uDE-RCDpa diff --git a/examples/select/select.go b/examples/select/select.go index fba2346..cd9e418 100644 --- a/examples/select/select.go +++ b/examples/select/select.go @@ -17,11 +17,11 @@ func main() { // of time, to simulate e.g. blocking RPC operations // executing in concurrent goroutines. go func() { - time.Sleep(time.Second * 1) + time.Sleep(1 * time.Second) c1 <- "one" }() go func() { - time.Sleep(time.Second * 2) + time.Sleep(2 * time.Second) c2 <- "two" }() diff --git a/examples/select/select.hash b/examples/select/select.hash index df807f5..5037668 100644 --- a/examples/select/select.hash +++ b/examples/select/select.hash @@ -1,2 +1,2 @@ -72503557ab54ef765eeba153fe8a3446541dfc5f -Vco7d8Lmhn +8d743edffd7de6bf7bccdf4437f45672b6adc75e +ZdSOPe1Gj13 diff --git a/examples/tickers/tickers.go b/examples/tickers/tickers.go index 4db2759..ef55c97 100644 --- a/examples/tickers/tickers.go +++ b/examples/tickers/tickers.go @@ -15,7 +15,7 @@ func main() { // channel that is sent values. Here we'll use the // `range` builtin on the channel to iterate over // the values as they arrive every 500ms. - ticker := time.NewTicker(time.Millisecond * 500) + ticker := time.NewTicker(500 * time.Millisecond) go func() { for t := range ticker.C { fmt.Println("Tick at", t) @@ -25,7 +25,7 @@ func main() { // Tickers can be stopped like timers. Once a ticker // is stopped it won't receive any more values on its // channel. We'll stop ours after 1600ms. - time.Sleep(time.Millisecond * 1600) + time.Sleep(1600 * time.Millisecond) ticker.Stop() fmt.Println("Ticker stopped") } diff --git a/examples/tickers/tickers.hash b/examples/tickers/tickers.hash index 02465e8..0404929 100644 --- a/examples/tickers/tickers.hash +++ b/examples/tickers/tickers.hash @@ -1,2 +1,2 @@ -5d97b8ebdf36a65f0e92040bae0097f60b79e1ed -MO3ndiv5qR +7dc6447323f493f72aa70952bf3e3f2c6156f82f +Rgc_UDvHv6a diff --git a/examples/timeouts/timeouts.go b/examples/timeouts/timeouts.go index 2f545f2..2f110d1 100644 --- a/examples/timeouts/timeouts.go +++ b/examples/timeouts/timeouts.go @@ -15,7 +15,7 @@ func main() { // after 2s. c1 := make(chan string, 1) go func() { - time.Sleep(time.Second * 2) + time.Sleep(2 * time.Second) c1 <- "result 1" }() @@ -28,7 +28,7 @@ func main() { select { case res := <-c1: fmt.Println(res) - case <-time.After(time.Second * 1): + case <-time.After(1 * time.Second): fmt.Println("timeout 1") } @@ -36,13 +36,13 @@ func main() { // from `c2` will succeed and we'll print the result. c2 := make(chan string, 1) go func() { - time.Sleep(time.Second * 2) + time.Sleep(2 * time.Second) c2 <- "result 2" }() select { case res := <-c2: fmt.Println(res) - case <-time.After(time.Second * 3): + case <-time.After(3 * time.Second): fmt.Println("timeout 2") } } diff --git a/examples/timeouts/timeouts.hash b/examples/timeouts/timeouts.hash index ae18eff..64d1c5a 100644 --- a/examples/timeouts/timeouts.hash +++ b/examples/timeouts/timeouts.hash @@ -1,2 +1,2 @@ -5ea69771a4d4c6286fd587f91e03cd386f77cada -NR2GHXUKeM +93343e1aacb14f818c87732914c29ba57afab245 +MgcfA-xpJO9 diff --git a/examples/timers/timers.go b/examples/timers/timers.go index 08fe02b..61cbdde 100644 --- a/examples/timers/timers.go +++ b/examples/timers/timers.go @@ -15,7 +15,7 @@ func main() { // tell the timer how long you want to wait, and it // provides a channel that will be notified at that // time. This timer will wait 2 seconds. - timer1 := time.NewTimer(time.Second * 2) + timer1 := time.NewTimer(2 * time.Second) // The `<-timer1.C` blocks on the timer's channel `C` // until it sends a value indicating that the timer diff --git a/examples/timers/timers.hash b/examples/timers/timers.hash index 911fc88..f51b1f0 100644 --- a/examples/timers/timers.hash +++ b/examples/timers/timers.hash @@ -1,2 +1,2 @@ -a5b44952d93152ba6bfdb100ea30cd8446cad47e -6fSHrYxpMu +e10c601ab3b702dfcea728c1edb31673561484b5 +pybl9hRvJq2 diff --git a/public/rate-limiting b/public/rate-limiting index f453286..39a49c9 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -43,7 +43,7 @@ channels, and tickers.

@@ -169,7 +169,7 @@ value to burstyLimiter, up to its limit of 3.

From ee8149219e542f5a130472dbd35a2389cc2a9eb8 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 9 Feb 2018 14:47:28 -0800 Subject: [PATCH 039/133] Explain non-blocking sends --- .../non-blocking-channel-operations.go | 5 ++++- .../non-blocking-channel-operations.hash | 4 ++-- public/non-blocking-channel-operations | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/non-blocking-channel-operations/non-blocking-channel-operations.go b/examples/non-blocking-channel-operations/non-blocking-channel-operations.go index 24cd6ff..dfd0516 100644 --- a/examples/non-blocking-channel-operations/non-blocking-channel-operations.go +++ b/examples/non-blocking-channel-operations/non-blocking-channel-operations.go @@ -22,7 +22,10 @@ func main() { fmt.Println("no message received") } - // A non-blocking send works similarly. + // A non-blocking send works similarly. Here `msg` + // cannot be sent to the `messages` channel, because + // the channel has no buffer and there is no receiver. + // Therefore the `default` case is selected. msg := "hi" select { case messages <- msg: diff --git a/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash b/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash index 3bca2a4..a9f03de 100644 --- a/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash +++ b/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash @@ -1,2 +1,2 @@ -119ced4df4f79795b163483b6abfd855e76ef577 -M972dltae2 +a6e0a8bb87153c7ed0de4996172f7ad5d89c6814 +n5ttmOsMrrJ diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index ba7aed6..2e2e713 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -42,7 +42,7 @@ non-blocking multi-way selects.

@@ -40,7 +40,7 @@ Here’s how to parse URLs in Go.

From 2d9b20457174f18188dc52693064689fa2bef82b Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:45:42 -0700 Subject: [PATCH 078/133] Use "conversion" instead of "cast", per spec Closes #200 --- examples/base64-encoding/base64-encoding.go | 2 +- examples/base64-encoding/base64-encoding.hash | 4 ++-- examples/constants/constants.go | 2 +- examples/constants/constants.hash | 4 ++-- examples/json/json.go | 6 +++--- examples/json/json.hash | 4 ++-- examples/sorting-by-functions/sorting-by-functions.go | 4 ++-- examples/sorting-by-functions/sorting-by-functions.hash | 4 ++-- public/base64-encoding | 4 ++-- public/constants | 4 ++-- public/json | 8 ++++---- public/sorting-by-functions | 6 +++--- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/base64-encoding/base64-encoding.go b/examples/base64-encoding/base64-encoding.go index d37167f..d428ae5 100644 --- a/examples/base64-encoding/base64-encoding.go +++ b/examples/base64-encoding/base64-encoding.go @@ -17,7 +17,7 @@ func main() { // Go supports both standard and URL-compatible // base64. Here's how to encode using the standard // encoder. The encoder requires a `[]byte` so we - // cast our `string` to that type. + // convert our `string` to that type. sEnc := b64.StdEncoding.EncodeToString([]byte(data)) fmt.Println(sEnc) diff --git a/examples/base64-encoding/base64-encoding.hash b/examples/base64-encoding/base64-encoding.hash index 25e1653..1cb409a 100644 --- a/examples/base64-encoding/base64-encoding.hash +++ b/examples/base64-encoding/base64-encoding.hash @@ -1,2 +1,2 @@ -e57f5be3a796261fb4a55cdb0580a254e14b4930 -t6rFm2x4Yr +c20da14820b656c867790f2e99bc37140babca8c +y_QTcqdkvZh diff --git a/examples/constants/constants.go b/examples/constants/constants.go index 5ed88a4..ed4b56a 100644 --- a/examples/constants/constants.go +++ b/examples/constants/constants.go @@ -22,7 +22,7 @@ func main() { fmt.Println(d) // A numeric constant has no type until it's given - // one, such as by an explicit cast. + // one, such as by an explicit conversion. fmt.Println(int64(d)) // A number can be given a type by using it in a diff --git a/examples/constants/constants.hash b/examples/constants/constants.hash index b5ab256..1e282aa 100644 --- a/examples/constants/constants.hash +++ b/examples/constants/constants.hash @@ -1,2 +1,2 @@ -3de4f16f1ed032378268411b2173b95e8000305d -T5sj0eINnp +2f2ec3a5ff4eef280199da1908eed261346fb40e +VhP0f8moZd3 diff --git a/examples/json/json.go b/examples/json/json.go index 6a1f56d..ff777a1 100644 --- a/examples/json/json.go +++ b/examples/json/json.go @@ -85,14 +85,14 @@ func main() { fmt.Println(dat) // In order to use the values in the decoded map, - // we'll need to cast them to their appropriate type. - // For example here we cast the value in `num` to + // we'll need to convert them to their appropriate type. + // For example here we convert the value in `num` to // the expected `float64` type. num := dat["num"].(float64) fmt.Println(num) // Accessing nested data requires a series of - // casts. + // conversions. strs := dat["strs"].([]interface{}) str1 := strs[0].(string) fmt.Println(str1) diff --git a/examples/json/json.hash b/examples/json/json.hash index c9282a5..3acb1f6 100644 --- a/examples/json/json.hash +++ b/examples/json/json.hash @@ -1,2 +1,2 @@ -43e8d66fb862ea224994ca766e5689a96016f7ca -UGeNKd-cw34 +d4dc2281f64061f077d8f1e9687538f41a339b25 +xC6SHbzGBZC diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index 9ea8c05..e01bdcc 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -33,8 +33,8 @@ func (s byLength) Less(i, j int) bool { } // With all of this in place, we can now implement our -// custom sort by casting the original `fruits` slice to -// `byLength`, and then use `sort.Sort` on that typed +// custom sort by converting the original `fruits` slice +// to `byLength`, and then use `sort.Sort` on that typed // slice. func main() { fruits := []string{"peach", "banana", "kiwi"} diff --git a/examples/sorting-by-functions/sorting-by-functions.hash b/examples/sorting-by-functions/sorting-by-functions.hash index fbf46ed..776dde8 100644 --- a/examples/sorting-by-functions/sorting-by-functions.hash +++ b/examples/sorting-by-functions/sorting-by-functions.hash @@ -1,2 +1,2 @@ -a5bcb1620c62f89f8253d7d2a2580b5ae48771b6 -4b7_qiGp33y +6a04058b564d5741815e523f97f240ee6563cb15 +y3kuCwIFRYK diff --git a/public/base64-encoding b/public/base64-encoding index 5a82f4c..f067bee 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -28,7 +28,7 @@ encoding/decoding.

@@ -276,7 +276,7 @@ the expected float64 type.

From f2f5af36906783caaf6367ebb498edd781229ba3 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Mon, 3 Jun 2019 18:35:36 -0700 Subject: [PATCH 079/133] Fix output --- examples/variables/variables.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variables/variables.sh b/examples/variables/variables.sh index 24127cc..6513b1d 100644 --- a/examples/variables/variables.sh +++ b/examples/variables/variables.sh @@ -3,4 +3,4 @@ initial 1 2 true 0 -short +apple From 738fc184ef2421f504f3b98506f4a58574b56b82 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 4 Jun 2019 05:48:59 -0700 Subject: [PATCH 080/133] Subcommands example --- examples.txt | 1 + .../command-line-subcommands.go | 57 +++++ .../command-line-subcommands.hash | 2 + .../command-line-subcommands.sh | 21 ++ public/command-line-flags | 2 +- public/command-line-subcommands | 239 ++++++++++++++++++ public/index.html | 2 + 7 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 examples/command-line-subcommands/command-line-subcommands.go create mode 100644 examples/command-line-subcommands/command-line-subcommands.hash create mode 100644 examples/command-line-subcommands/command-line-subcommands.sh create mode 100644 public/command-line-subcommands diff --git a/examples.txt b/examples.txt index 9e13b51..2c1539b 100644 --- a/examples.txt +++ b/examples.txt @@ -59,6 +59,7 @@ Writing Files Line Filters Command-Line Arguments Command-Line Flags +Command-Line Subcommands Environment Variables HTTP Clients Spawning Processes diff --git a/examples/command-line-subcommands/command-line-subcommands.go b/examples/command-line-subcommands/command-line-subcommands.go new file mode 100644 index 0000000..132c9ec --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.go @@ -0,0 +1,57 @@ +// Some command-line tools, like the `go` tool or `git` +// have many *subcommands*, each with its own set of +// flags. For example, `go build` and `go get` are two +// different subcommands of the `go` tool. +// The `flag` package lets us easily define simple +// subcommands that have their own flags. + +package main + +import ( + "flag" + "fmt" + "os" +) + +func main() { + + // We declare a subcommand using the `NewFlagSet` + // function, and proceed to define new flags specific + // for this subcommand. + fooCmd := flag.NewFlagSet("foo", flag.ExitOnError) + fooEnable := fooCmd.Bool("enable", false, "enable") + fooName := fooCmd.String("name", "", "name") + + // For a different subcommand we can define different + // supported flags. + barCmd := flag.NewFlagSet("bar", flag.ExitOnError) + barLevel := barCmd.Int("level", 0, "level") + + // The subcommand is expected as the first argument + // to the program. + if len(os.Args) < 2 { + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } + + // Check which subcommand is invoked. + switch os.Args[1] { + case "foo": + + // For every subcommand, we parse its own flags and + // have access to trailing positional arguments. + fooCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'foo'") + fmt.Println(" enable:", *fooEnable) + fmt.Println(" name:", *fooName) + fmt.Println(" tail:", fooCmd.Args()) + case "bar": + barCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'bar'") + fmt.Println(" level:", *barLevel) + fmt.Println(" tail:", barCmd.Args()) + default: + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } +} diff --git a/examples/command-line-subcommands/command-line-subcommands.hash b/examples/command-line-subcommands/command-line-subcommands.hash new file mode 100644 index 0000000..b26ba5f --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.hash @@ -0,0 +1,2 @@ +673d7811734cfd8f8f5bcb411e12def1e158cf0b +V7xR3wMkquz diff --git a/examples/command-line-subcommands/command-line-subcommands.sh b/examples/command-line-subcommands/command-line-subcommands.sh new file mode 100644 index 0000000..a7cec9a --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.sh @@ -0,0 +1,21 @@ +$ go build command-line-subcommands.go + +# First invoke the foo subcommand +$ ./command-line-subcommands foo -enable -name=joe a1 a2 +subcommand 'foo' + enable: true + name: joe + tail: [a1 a2] + +# Now try bar +$ ./command-line-subcommands bar -level 8 a1 +subcommand 'bar' + level: 8 + tail: [a1] + +# But bar won't accept foo's flags +$ ./command-line-subcommands bar -enable a1 +flag provided but not defined: -enable +Usage of bar: + -level int + level diff --git a/public/command-line-flags b/public/command-line-flags index 47341d4..b2eb253 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -297,7 +297,7 @@ way to parameterize programs.

- Next example: Environment Variables. + Next example: Command-Line Subcommands.

+

Go by Example: Command-Line Subcommands

+ +
- {{if .CodeRun}}{{end}} + {{if .CodeRun}}{{end}} {{.CodeRendered}}
- +
package main
 
diff --git a/public/rate-limiting b/public/rate-limiting index 224292d..f453286 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -43,7 +43,7 @@ channels, and tickers.

- +
package main
 
From 39e7009dfef55d698863a2e9713cac9967e0ddf3 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:18:25 -0500 Subject: [PATCH 022/133] Remind myself how to publish the site --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index abe01e7..36b9f56 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,16 @@ To build continuously in a loop: $ tools/build-loop ``` +### Publishing + +To upload the site: + +```console +$ gem install aws-sdk +$ export export AWS_ACCESS_KEY_ID=... +$ export AWS_SECRET_ACCESS_KEY=... +$ tools/upload-site +``` ### License From bb743bb826e49bd3e8efd7f2b1547d468640bb52 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:32:12 -0500 Subject: [PATCH 023/133] Consistency in json.go --- examples/json/json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/json/json.go b/examples/json/json.go index 475ffe5..6a1f56d 100644 --- a/examples/json/json.go +++ b/examples/json/json.go @@ -58,7 +58,7 @@ func main() { // You can use tags on struct field declarations // to customize the encoded JSON key names. Check the - // definition of `Response2` above to see an example + // definition of `response2` above to see an example // of such tags. res2D := &response2{ Page: 1, From 12791a4921437d9e9215661f7da2b521aa84b46d Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:33:23 -0500 Subject: [PATCH 024/133] Consistency in sorting-by-functions.go --- examples/sorting-by-functions/sorting-by-functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index f68c298..9ea8c05 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -10,7 +10,7 @@ import "sort" import "fmt" // In order to sort by a custom function in Go, we need a -// corresponding type. Here we've created a `ByLength` +// corresponding type. Here we've created a `byLength` // type that is just an alias for the builtin `[]string` // type. type byLength []string From 47be1a0ff8f6c7ce9c54146b9e04f24228054f95 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:35:20 -0500 Subject: [PATCH 025/133] Build updates --- examples/atomic-counters/atomic-counters.hash | 4 ++-- examples/closures/closures.hash | 4 ++-- .../collection-functions.hash | 4 ++-- examples/json/json.hash | 4 ++-- examples/mutexes/mutexes.hash | 4 ++-- .../sorting-by-functions.hash | 4 ++-- .../stateful-goroutines/stateful-goroutines.hash | 4 ++-- examples/variables/variables.hash | 4 ++-- public/atomic-counters | 4 ++-- public/closures | 4 ++-- public/collection-functions | 14 +++++++------- public/json | 14 +++++++------- public/mutexes | 6 +++--- public/sorting-by-functions | 16 ++++++++-------- public/stateful-goroutines | 6 +++--- public/variables | 4 ++-- 16 files changed, 50 insertions(+), 50 deletions(-) diff --git a/examples/atomic-counters/atomic-counters.hash b/examples/atomic-counters/atomic-counters.hash index 199e3b1..c1b531a 100644 --- a/examples/atomic-counters/atomic-counters.hash +++ b/examples/atomic-counters/atomic-counters.hash @@ -1,2 +1,2 @@ -ce8821f1f4fd99d554ad6cde52403dd3b69bb70a -8p48eFFxDZ +a4190094ea0405b5f2733101beb97939a1d43aee +KDr9EMMPMgi diff --git a/examples/closures/closures.hash b/examples/closures/closures.hash index a1f8255..fa66f0f 100644 --- a/examples/closures/closures.hash +++ b/examples/closures/closures.hash @@ -1,2 +1,2 @@ -2e062d01989caada16c4b22ff6a35cd58e4eb819 -gQtEWkhWyp +e304df67e760dda93ffe434aca58aea4a6c94f19 +zb93qzV6iN3 diff --git a/examples/collection-functions/collection-functions.hash b/examples/collection-functions/collection-functions.hash index cab1518..4c45952 100644 --- a/examples/collection-functions/collection-functions.hash +++ b/examples/collection-functions/collection-functions.hash @@ -1,2 +1,2 @@ -ed54b3fc0512ccace0f3d0b74975c9bcd2e7a8a2 -3PNdke3Wia +d961fc0e0074aed46cfd1516efdadea78781af56 +BJB_npWH516 diff --git a/examples/json/json.hash b/examples/json/json.hash index 8d238b0..c9282a5 100644 --- a/examples/json/json.hash +++ b/examples/json/json.hash @@ -1,2 +1,2 @@ -dee52e022a957b97c53fb2d2835653ef507502be -WxRgpycMaH +43e8d66fb862ea224994ca766e5689a96016f7ca +UGeNKd-cw34 diff --git a/examples/mutexes/mutexes.hash b/examples/mutexes/mutexes.hash index a175d8e..aea2025 100644 --- a/examples/mutexes/mutexes.hash +++ b/examples/mutexes/mutexes.hash @@ -1,2 +1,2 @@ -b62f93a169c2d9141b2f7edceb840ede59598bd7 -tWqg2zQSVpb +ca257d9594a6219d5803193132e999a32dc8c856 +IRewFKz2OPN diff --git a/examples/sorting-by-functions/sorting-by-functions.hash b/examples/sorting-by-functions/sorting-by-functions.hash index 91f67df..fbf46ed 100644 --- a/examples/sorting-by-functions/sorting-by-functions.hash +++ b/examples/sorting-by-functions/sorting-by-functions.hash @@ -1,2 +1,2 @@ -cec0da0bd98abd7f66fcd38122e4405f757161bc -N6GbEgBffd +a5bcb1620c62f89f8253d7d2a2580b5ae48771b6 +4b7_qiGp33y diff --git a/examples/stateful-goroutines/stateful-goroutines.hash b/examples/stateful-goroutines/stateful-goroutines.hash index c2233b3..f88cfa8 100644 --- a/examples/stateful-goroutines/stateful-goroutines.hash +++ b/examples/stateful-goroutines/stateful-goroutines.hash @@ -1,2 +1,2 @@ -c306add52c0752f0b3099eb669364fc4bdb74be1 -P4SrrlosMp +ff8b7e93a43c284ada17f4387cc5dfeafa3ee316 +dlfBGF-qff6 diff --git a/examples/variables/variables.hash b/examples/variables/variables.hash index 8e7c623..ae31cd9 100644 --- a/examples/variables/variables.hash +++ b/examples/variables/variables.hash @@ -1,2 +1,2 @@ -8c74aae4850358073926dba5d98aa402f9968251 -Zv45CSMaiD +f7a75d8fb2525099e9de6c5a5916e2411c5f3489 +1FnG0dJfxs8 diff --git a/public/atomic-counters b/public/atomic-counters index fb7e27e..0afd46e 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -44,7 +44,7 @@ counters accessed by multiple goroutines.

- +
package main
 
@@ -85,7 +85,7 @@ counters accessed by multiple goroutines.

-
    var ops uint64 = 0
+            
    var ops uint64
 
- +
package main
 
@@ -74,7 +74,7 @@ form a closure.

func intSeq() func() int {
     i := 0
     return func() int {
-        i += 1
+        i++
         return i
     }
 }
diff --git a/public/collection-functions b/public/collection-functions
index 7d71950..0d2e11a 100644
--- a/public/collection-functions
+++ b/public/collection-functions
@@ -73,7 +73,7 @@ helper function.

- +
package main
 
@@ -95,7 +95,7 @@ helper function.

-

Returns the first index of the target string t, or +

Index returns the first index of the target string t, or -1 if no match is found.

-

Returns true if the target string t is in the +

Include returns true if the target string t is in the slice.

-

Returns true if one of the strings in the slice +

Any returns true if one of the strings in the slice satisfies the predicate f.

-

Returns true if all of the strings in the slice +

All returns true if all of the strings in the slice satisfy the predicate f.

-

Returns a new slice containing all strings in the +

Filter returns a new slice containing all strings in the slice that satisfy the predicate f.

-

Returns a new slice containing the results of applying +

Map returns a new slice containing the results of applying the function f to each string in the original slice.

- +
package main
 
@@ -70,11 +70,11 @@ decoding of custom types below.

-
type Response1 struct {
+            
type response1 struct {
     Page   int
     Fruits []string
 }
-type Response2 struct {
+type response2 struct {
     Page   int      `json:"page"`
     Fruits []string `json:"fruits"`
 }
@@ -190,7 +190,7 @@ use those names as the JSON keys.

-
    res1D := &Response1{
+            
    res1D := &response1{
         Page:   1,
         Fruits: []string{"apple", "peach", "pear"}}
     res1B, _ := json.Marshal(res1D)
@@ -204,13 +204,13 @@ use those names as the JSON keys.

You can use tags on struct field declarations to customize the encoded JSON key names. Check the -definition of Response2 above to see an example +definition of response2 above to see an example of such tags.

-
    res2D := &Response2{
+            
    res2D := &response2{
         Page:   1,
         Fruits: []string{"apple", "peach", "pear"}}
     res2B, _ := json.Marshal(res2D)
@@ -313,7 +313,7 @@ data.

    str := `{"page": 1, "fruits": ["apple", "peach"]}`
-    res := Response2{}
+    res := response2{}
     json.Unmarshal([]byte(str), &res)
     fmt.Println(res)
     fmt.Println(res.Fruits[0])
diff --git a/public/mutexes b/public/mutexes
index 83935b9..7940e38 100644
--- a/public/mutexes
+++ b/public/mutexes
@@ -42,7 +42,7 @@ to safely access data across multiple goroutines.

- +
package main
 
@@ -113,8 +113,8 @@ operations we do.

-
    var readOps uint64 = 0
-    var writeOps uint64 = 0
+            
    var readOps uint64
+    var writeOps uint64
 
- +
package main
 
@@ -66,14 +66,14 @@ in Go.

In order to sort by a custom function in Go, we need a -corresponding type. Here we’ve created a ByLength +corresponding type. Here we’ve created a byLength type that is just an alias for the builtin []string type.

-
type ByLength []string
+            
type byLength []string
 
-
func (s ByLength) Len() int {
+            
func (s byLength) Len() int {
     return len(s)
 }
-func (s ByLength) Swap(i, j int) {
+func (s byLength) Swap(i, j int) {
     s[i], s[j] = s[j], s[i]
 }
-func (s ByLength) Less(i, j int) bool {
+func (s byLength) Less(i, j int) bool {
     return len(s[i]) < len(s[j])
 }
 
@@ -110,7 +110,7 @@ we use len(s[i]) and len(s[j]) here.

With all of this in place, we can now implement our custom sort by casting the original fruits slice to -ByLength, and then use sort.Sort on that typed +byLength, and then use sort.Sort on that typed slice.

- +
package main
 
@@ -117,8 +117,8 @@ goroutine to respond.

-
    var readOps uint64 = 0
-    var writeOps uint64 = 0
+            
    var readOps uint64
+    var writeOps uint64
 
- +
package main
 
@@ -79,7 +79,7 @@ calls.

-
    var a string = "initial"
+            
    var a = "initial"
     fmt.Println(a)
 
From c3884e7329312c1ad04b23282e12c583c689ebd9 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:47:23 -0500 Subject: [PATCH 026/133] Link Korean translation. Closes #155 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 36b9f56..7041d92 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Contributor translations of the Go by Example site are available in: * [Chinese](http://gobyexample.everyx.in/) by [everyx](https://github.com/everyx) * [French](http://le-go-par-l-exemple.keiruaprod.fr) by [keirua](https://github.com/keirua/gobyexample) * [Italian](http://gobyexample.it) by the [Go Italian community](https://github.com/golangit/gobyexample-it) +* [Korean](https://mingrammer.com/gobyexample/) by [mingrammer](https://github.com/mingrammer) * [Spanish](http://goconejemplos.com) by the [Go Mexico community](https://github.com/dabit/gobyexample) ### Thanks From b79190366270b650e5f605cb0177bfcab83825ed Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 16:53:56 -0500 Subject: [PATCH 027/133] Explictly install golint --- bios.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bios.sh b/bios.sh index cd16a0a..fabadba 100755 --- a/bios.sh +++ b/bios.sh @@ -6,6 +6,7 @@ run -s "Cloning" git clone $URL --branch $REF --single-branch . git reset --hard $SHA go get github.com/russross/blackfriday +go get github.com/golang/lint/golint PKGS=$(go list $PKG/... | grep -v examples/variables) run -s "Linting" golint -set_exit_status $PKGS From 0a96c218813bb6a0a9e9489cba0a24c91e53c20a Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:07:33 -0500 Subject: [PATCH 028/133] Allows tools to use Go-standard formatting --- tools/format | 2 +- tools/generate.go | 416 +++++++++++++++++++++++----------------------- tools/measure.go | 60 +++---- 3 files changed, 239 insertions(+), 239 deletions(-) diff --git a/tools/format b/tools/format index 99c5089..cdec6a5 100755 --- a/tools/format +++ b/tools/format @@ -2,7 +2,7 @@ set -eo pipefail -paths=$(ls tools/*.go examples/*/*.go) +paths=$(ls examples/*/*.go) gbe_to_4spaces() { local os=$(tr [A-Z] [a-z] <<< "`uname`") diff --git a/tools/generate.go b/tools/generate.go index ee5db8d..c30137f 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -1,17 +1,17 @@ package main import ( - "crypto/sha1" - "fmt" - "github.com/russross/blackfriday" - "io/ioutil" - "net/http" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "text/template" + "crypto/sha1" + "fmt" + "github.com/russross/blackfriday" + "io/ioutil" + "net/http" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + "text/template" ) var cacheDir = "/tmp/gobyexample-cache" @@ -19,99 +19,99 @@ var siteDir = "./public" var pygmentizeBin = "./vendor/pygments/pygmentize" func check(err error) { - if err != nil { - panic(err) - } + if err != nil { + panic(err) + } } func ensureDir(dir string) { - err := os.MkdirAll(dir, 0755) - check(err) + err := os.MkdirAll(dir, 0755) + check(err) } func copyFile(src, dst string) { - dat, err := ioutil.ReadFile(src) - check(err) - err = ioutil.WriteFile(dst, dat, 0644) - check(err) + dat, err := ioutil.ReadFile(src) + check(err) + err = ioutil.WriteFile(dst, dat, 0644) + check(err) } func pipe(bin string, arg []string, src string) []byte { - cmd := exec.Command(bin, arg...) - in, err := cmd.StdinPipe() - check(err) - out, err := cmd.StdoutPipe() - check(err) - err = cmd.Start() - check(err) - _, err = in.Write([]byte(src)) - check(err) - err = in.Close() - check(err) - bytes, err := ioutil.ReadAll(out) - check(err) - err = cmd.Wait() - check(err) - return bytes + cmd := exec.Command(bin, arg...) + in, err := cmd.StdinPipe() + check(err) + out, err := cmd.StdoutPipe() + check(err) + err = cmd.Start() + check(err) + _, err = in.Write([]byte(src)) + check(err) + err = in.Close() + check(err) + bytes, err := ioutil.ReadAll(out) + check(err) + err = cmd.Wait() + check(err) + return bytes } func sha1Sum(s string) string { - h := sha1.New() - h.Write([]byte(s)) - b := h.Sum(nil) - return fmt.Sprintf("%x", b) + h := sha1.New() + h.Write([]byte(s)) + b := h.Sum(nil) + return fmt.Sprintf("%x", b) } func mustReadFile(path string) string { - bytes, err := ioutil.ReadFile(path) - check(err) - return string(bytes) + bytes, err := ioutil.ReadFile(path) + check(err) + return string(bytes) } func cachedPygmentize(lex string, src string) string { - ensureDir(cacheDir) - arg := []string{"-l", lex, "-f", "html"} - cachePath := cacheDir + "/pygmentize-" + strings.Join(arg, "-") + "-" + sha1Sum(src) - cacheBytes, cacheErr := ioutil.ReadFile(cachePath) - if cacheErr == nil { - return string(cacheBytes) - } - renderBytes := pipe(pygmentizeBin, arg, src) - // Newer versions of Pygments add silly empty spans. - renderCleanString := strings.Replace(string(renderBytes), "", "", -1) - writeErr := ioutil.WriteFile(cachePath, []byte(renderCleanString), 0600) - check(writeErr) - return renderCleanString + ensureDir(cacheDir) + arg := []string{"-l", lex, "-f", "html"} + cachePath := cacheDir + "/pygmentize-" + strings.Join(arg, "-") + "-" + sha1Sum(src) + cacheBytes, cacheErr := ioutil.ReadFile(cachePath) + if cacheErr == nil { + return string(cacheBytes) + } + renderBytes := pipe(pygmentizeBin, arg, src) + // Newer versions of Pygments add silly empty spans. + renderCleanString := strings.Replace(string(renderBytes), "", "", -1) + writeErr := ioutil.WriteFile(cachePath, []byte(renderCleanString), 0600) + check(writeErr) + return renderCleanString } func markdown(src string) string { - return string(blackfriday.MarkdownCommon([]byte(src))) + return string(blackfriday.MarkdownCommon([]byte(src))) } func readLines(path string) []string { - src := mustReadFile(path) - return strings.Split(src, "\n") + src := mustReadFile(path) + return strings.Split(src, "\n") } func mustGlob(glob string) []string { - paths, err := filepath.Glob(glob) - check(err) - return paths + paths, err := filepath.Glob(glob) + check(err) + return paths } func whichLexer(path string) string { - if strings.HasSuffix(path, ".go") { - return "go" - } else if strings.HasSuffix(path, ".sh") { - return "console" - } - panic("No lexer for " + path) + if strings.HasSuffix(path, ".go") { + return "go" + } else if strings.HasSuffix(path, ".sh") { + return "console" + } + panic("No lexer for " + path) } func debug(msg string) { - if os.Getenv("DEBUG") == "1" { - fmt.Fprintln(os.Stderr, msg) - } + if os.Getenv("DEBUG") == "1" { + fmt.Fprintln(os.Stderr, msg) + } } var docsPat = regexp.MustCompile("^\\s*(\\/\\/|#)\\s") @@ -119,169 +119,169 @@ var dashPat = regexp.MustCompile("\\-+") // Seg is a segment of an example type Seg struct { - Docs, DocsRendered string - Code, CodeRendered string - CodeEmpty, CodeLeading, CodeRun bool + Docs, DocsRendered string + Code, CodeRendered string + CodeEmpty, CodeLeading, CodeRun bool } // Example is info extracted from an example file type Example struct { - ID, Name string - GoCode, GoCodeHash, URLHash string - Segs [][]*Seg - NextExample *Example + ID, Name string + GoCode, GoCodeHash, URLHash string + Segs [][]*Seg + NextExample *Example } func parseHashFile(sourcePath string) (string, string) { - lines := readLines(sourcePath) - return lines[0], lines[1] + lines := readLines(sourcePath) + return lines[0], lines[1] } func resetURLHashFile(codehash, code, sourcePath string) string { - payload := strings.NewReader(code) - resp, err := http.Post("https://play.golang.org/share", "text/plain", payload) - if err != nil { - panic(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - urlkey := string(body) - data := fmt.Sprintf("%s\n%s\n", codehash, urlkey) - ioutil.WriteFile(sourcePath, []byte(data), 0644) - return urlkey + payload := strings.NewReader(code) + resp, err := http.Post("https://play.golang.org/share", "text/plain", payload) + if err != nil { + panic(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + urlkey := string(body) + data := fmt.Sprintf("%s\n%s\n", codehash, urlkey) + ioutil.WriteFile(sourcePath, []byte(data), 0644) + return urlkey } func parseSegs(sourcePath string) ([]*Seg, string) { - lines := readLines(sourcePath) - filecontent := strings.Join(lines, "\n") - segs := []*Seg{} - lastSeen := "" - for _, line := range lines { - if line == "" { - lastSeen = "" - continue - } - matchDocs := docsPat.MatchString(line) - matchCode := !matchDocs - newDocs := (lastSeen == "") || ((lastSeen != "docs") && (segs[len(segs)-1].Docs != "")) - newCode := (lastSeen == "") || ((lastSeen != "code") && (segs[len(segs)-1].Code != "")) - if newDocs || newCode { - debug("NEWSEG") - } - if matchDocs { - trimmed := docsPat.ReplaceAllString(line, "") - if newDocs { - newSeg := Seg{Docs: trimmed, Code: ""} - segs = append(segs, &newSeg) - } else { - segs[len(segs)-1].Docs = segs[len(segs)-1].Docs + "\n" + trimmed - } - debug("DOCS: " + line) - lastSeen = "docs" - } else if matchCode { - if newCode { - newSeg := Seg{Docs: "", Code: line} - segs = append(segs, &newSeg) - } else { - segs[len(segs)-1].Code = segs[len(segs)-1].Code + "\n" + line - } - debug("CODE: " + line) - lastSeen = "code" - } - } - for i, seg := range segs { - seg.CodeEmpty = (seg.Code == "") - seg.CodeLeading = (i < (len(segs) - 1)) - seg.CodeRun = strings.Contains(seg.Code, "package main") - } - return segs, filecontent + lines := readLines(sourcePath) + filecontent := strings.Join(lines, "\n") + segs := []*Seg{} + lastSeen := "" + for _, line := range lines { + if line == "" { + lastSeen = "" + continue + } + matchDocs := docsPat.MatchString(line) + matchCode := !matchDocs + newDocs := (lastSeen == "") || ((lastSeen != "docs") && (segs[len(segs)-1].Docs != "")) + newCode := (lastSeen == "") || ((lastSeen != "code") && (segs[len(segs)-1].Code != "")) + if newDocs || newCode { + debug("NEWSEG") + } + if matchDocs { + trimmed := docsPat.ReplaceAllString(line, "") + if newDocs { + newSeg := Seg{Docs: trimmed, Code: ""} + segs = append(segs, &newSeg) + } else { + segs[len(segs)-1].Docs = segs[len(segs)-1].Docs + "\n" + trimmed + } + debug("DOCS: " + line) + lastSeen = "docs" + } else if matchCode { + if newCode { + newSeg := Seg{Docs: "", Code: line} + segs = append(segs, &newSeg) + } else { + segs[len(segs)-1].Code = segs[len(segs)-1].Code + "\n" + line + } + debug("CODE: " + line) + lastSeen = "code" + } + } + for i, seg := range segs { + seg.CodeEmpty = (seg.Code == "") + seg.CodeLeading = (i < (len(segs) - 1)) + seg.CodeRun = strings.Contains(seg.Code, "package main") + } + return segs, filecontent } func parseAndRenderSegs(sourcePath string) ([]*Seg, string) { - segs, filecontent := parseSegs(sourcePath) - lexer := whichLexer(sourcePath) - for _, seg := range segs { - if seg.Docs != "" { - seg.DocsRendered = markdown(seg.Docs) - } - if seg.Code != "" { - seg.CodeRendered = cachedPygmentize(lexer, seg.Code) - } - } - // we are only interested in the 'go' code to pass to play.golang.org - if lexer != "go" { - filecontent = "" - } - return segs, filecontent + segs, filecontent := parseSegs(sourcePath) + lexer := whichLexer(sourcePath) + for _, seg := range segs { + if seg.Docs != "" { + seg.DocsRendered = markdown(seg.Docs) + } + if seg.Code != "" { + seg.CodeRendered = cachedPygmentize(lexer, seg.Code) + } + } + // we are only interested in the 'go' code to pass to play.golang.org + if lexer != "go" { + filecontent = "" + } + return segs, filecontent } func parseExamples() []*Example { - exampleNames := readLines("examples.txt") - examples := make([]*Example, 0) - for _, exampleName := range exampleNames { - if (exampleName != "") && !strings.HasPrefix(exampleName, "#") { - example := Example{Name: exampleName} - exampleID := strings.ToLower(exampleName) - exampleID = strings.Replace(exampleID, " ", "-", -1) - exampleID = strings.Replace(exampleID, "/", "-", -1) - exampleID = strings.Replace(exampleID, "'", "", -1) - exampleID = dashPat.ReplaceAllString(exampleID, "-") - example.ID = exampleID - example.Segs = make([][]*Seg, 0) - sourcePaths := mustGlob("examples/" + exampleID + "/*") - for _, sourcePath := range sourcePaths { - if strings.HasSuffix(sourcePath, ".hash") { - example.GoCodeHash, example.URLHash = parseHashFile(sourcePath) - } else { - sourceSegs, filecontents := parseAndRenderSegs(sourcePath) - if filecontents != "" { - example.GoCode = filecontents - } - example.Segs = append(example.Segs, sourceSegs) - } - } - newCodeHash := sha1Sum(example.GoCode) - if example.GoCodeHash != newCodeHash { - example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") - } - examples = append(examples, &example) - } - } - for i, example := range examples { - if i < (len(examples) - 1) { - example.NextExample = examples[i+1] - } - } - return examples + exampleNames := readLines("examples.txt") + examples := make([]*Example, 0) + for _, exampleName := range exampleNames { + if (exampleName != "") && !strings.HasPrefix(exampleName, "#") { + example := Example{Name: exampleName} + exampleID := strings.ToLower(exampleName) + exampleID = strings.Replace(exampleID, " ", "-", -1) + exampleID = strings.Replace(exampleID, "/", "-", -1) + exampleID = strings.Replace(exampleID, "'", "", -1) + exampleID = dashPat.ReplaceAllString(exampleID, "-") + example.ID = exampleID + example.Segs = make([][]*Seg, 0) + sourcePaths := mustGlob("examples/" + exampleID + "/*") + for _, sourcePath := range sourcePaths { + if strings.HasSuffix(sourcePath, ".hash") { + example.GoCodeHash, example.URLHash = parseHashFile(sourcePath) + } else { + sourceSegs, filecontents := parseAndRenderSegs(sourcePath) + if filecontents != "" { + example.GoCode = filecontents + } + example.Segs = append(example.Segs, sourceSegs) + } + } + newCodeHash := sha1Sum(example.GoCode) + if example.GoCodeHash != newCodeHash { + example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") + } + examples = append(examples, &example) + } + } + for i, example := range examples { + if i < (len(examples) - 1) { + example.NextExample = examples[i+1] + } + } + return examples } func renderIndex(examples []*Example) { - indexTmpl := template.New("index") - _, err := indexTmpl.Parse(mustReadFile("templates/index.tmpl")) - check(err) - indexF, err := os.Create(siteDir + "/index.html") - check(err) - err = indexTmpl.Execute(indexF, examples) - check(err) + indexTmpl := template.New("index") + _, err := indexTmpl.Parse(mustReadFile("templates/index.tmpl")) + check(err) + indexF, err := os.Create(siteDir + "/index.html") + check(err) + err = indexTmpl.Execute(indexF, examples) + check(err) } func renderExamples(examples []*Example) { - exampleTmpl := template.New("example") - _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) - check(err) - for _, example := range examples { - exampleF, err := os.Create(siteDir + "/" + example.ID) - check(err) - exampleTmpl.Execute(exampleF, example) - } + exampleTmpl := template.New("example") + _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) + check(err) + for _, example := range examples { + exampleF, err := os.Create(siteDir + "/" + example.ID) + check(err) + exampleTmpl.Execute(exampleF, example) + } } func main() { - copyFile("templates/site.css", siteDir+"/site.css") - copyFile("templates/favicon.ico", siteDir+"/favicon.ico") - copyFile("templates/404.html", siteDir+"/404.html") - copyFile("templates/play.png", siteDir+"/play.png") - examples := parseExamples() - renderIndex(examples) - renderExamples(examples) + copyFile("templates/site.css", siteDir+"/site.css") + copyFile("templates/favicon.ico", siteDir+"/favicon.ico") + copyFile("templates/404.html", siteDir+"/404.html") + copyFile("templates/play.png", siteDir+"/play.png") + examples := parseExamples() + renderIndex(examples) + renderExamples(examples) } diff --git a/tools/measure.go b/tools/measure.go index 9ea4e10..a4fafb1 100644 --- a/tools/measure.go +++ b/tools/measure.go @@ -1,45 +1,45 @@ package main import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "regexp" - "strings" - "unicode/utf8" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + "unicode/utf8" ) func check(err error) { - if err != nil { - panic(err) - } + if err != nil { + panic(err) + } } func readLines(path string) []string { - srcBytes, err := ioutil.ReadFile(path) - check(err) - return strings.Split(string(srcBytes), "\n") + srcBytes, err := ioutil.ReadFile(path) + check(err) + return strings.Split(string(srcBytes), "\n") } var commentPat = regexp.MustCompile("\\s*\\/\\/") func main() { - sourcePaths, err := filepath.Glob("./examples/*/*") - check(err) - foundLongFile := false - for _, sourcePath := range sourcePaths { - foundLongLine := false - lines := readLines(sourcePath) - for i, line := range lines { - if !foundLongLine && !commentPat.MatchString(line) && (utf8.RuneCountInString(line) > 58) { - fmt.Printf("measure: %s:%d\n", sourcePath, i+1) - foundLongLine = true - foundLongFile = true - } - } - } - if foundLongFile { - os.Exit(1) - } + sourcePaths, err := filepath.Glob("./examples/*/*") + check(err) + foundLongFile := false + for _, sourcePath := range sourcePaths { + foundLongLine := false + lines := readLines(sourcePath) + for i, line := range lines { + if !foundLongLine && !commentPat.MatchString(line) && (utf8.RuneCountInString(line) > 58) { + fmt.Printf("measure: %s:%d\n", sourcePath, i+1) + foundLongLine = true + foundLongFile = true + } + } + } + if foundLongFile { + os.Exit(1) + } } From 8753360214126f426fcbc0ad9fe9b1445e64b311 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:14:49 -0500 Subject: [PATCH 029/133] Verify the checked-in build Extend bios.sh to ensure that the there are no changes in the build-time git repo after `tools/build` has been run. This ensures that the checked-in .go and .sh sources match the check-in public/ files. --- bios.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bios.sh b/bios.sh index fabadba..3a3f525 100755 --- a/bios.sh +++ b/bios.sh @@ -15,3 +15,5 @@ PKGS=$(go list $PKG/... | grep -v examples/panic) run -s "Vetting" go vet -x $PKGS run -s "Building" tools/build + +run -s "Verifying" git diff --exit-code From 6805c6cdb821c6aa710b2fc7ab0b7e1a809ba224 Mon Sep 17 00:00:00 2001 From: Bharath Ram Hariharan Date: Thu, 4 Jan 2018 14:44:36 -0500 Subject: [PATCH 030/133] removal of unwanted variable --- examples/goroutines/goroutines.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/goroutines/goroutines.go b/examples/goroutines/goroutines.go index 88329e6..36a7207 100644 --- a/examples/goroutines/goroutines.go +++ b/examples/goroutines/goroutines.go @@ -32,7 +32,6 @@ func main() { // separate goroutines now, so execution falls through // to here. This `Scanln` code requires we press a key // before the program exits. - var input string - fmt.Scanln(&input) + fmt.Scanln() fmt.Println("done") } From 36352be54c08ac3f27a6b53187b9a59c7f089660 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:26:11 -0500 Subject: [PATCH 031/133] Can now shorten this --- examples/goroutines/goroutines.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/goroutines/goroutines.go b/examples/goroutines/goroutines.go index 36a7207..eed6ee2 100644 --- a/examples/goroutines/goroutines.go +++ b/examples/goroutines/goroutines.go @@ -30,7 +30,7 @@ func main() { // Our two function calls are running asynchronously in // separate goroutines now, so execution falls through - // to here. This `Scanln` code requires we press a key + // to here. This `Scanln` requires we press a key // before the program exits. fmt.Scanln() fmt.Println("done") From 9ae40faa32eaded2c6283ff9a5d6327901139870 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:26:14 -0500 Subject: [PATCH 032/133] Rebuild for goroutines change --- examples/goroutines/goroutines.hash | 4 ++-- public/goroutines | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/goroutines/goroutines.hash b/examples/goroutines/goroutines.hash index 85df0eb..e86550b 100644 --- a/examples/goroutines/goroutines.hash +++ b/examples/goroutines/goroutines.hash @@ -1,2 +1,2 @@ -a847131d7f112172f9d5509fd3cf31aefb6d710e -RW_RSAHfj- +bfdaa0c8104c1257e6fea102fd26d476a3e8c14e +6Y8t3Yxd1LD diff --git a/public/goroutines b/public/goroutines index 9fda47d..b1af6a0 100644 --- a/public/goroutines +++ b/public/goroutines @@ -39,7 +39,7 @@
- +
package main
 
@@ -136,14 +136,13 @@ function call.

Our two function calls are running asynchronously in separate goroutines now, so execution falls through -to here. This Scanln code requires we press a key +to here. This Scanln requires we press a key before the program exits.

-
    var input string
-    fmt.Scanln(&input)
+            
    fmt.Scanln()
     fmt.Println("done")
 }
 
From ef0b54de184d5270aa71c4aec0fcd8a94eabe8d6 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:29:58 -0500 Subject: [PATCH 033/133] Fix typo in switch --- examples/switch/switch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/switch/switch.go b/examples/switch/switch.go index 231558b..4df7afe 100644 --- a/examples/switch/switch.go +++ b/examples/switch/switch.go @@ -42,7 +42,7 @@ func main() { } // A type `switch` compares types instead of values. You - // can use this to discover the the type of an interface + // can use this to discover the type of an interface // value. In this example, the variable `t` will have the // type corresponding to its clause. whatAmI := func(i interface{}) { From c6f016430a4bb406fd8d45c235424446dac0efcb Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:30:13 -0500 Subject: [PATCH 034/133] Rebuild for switch changes --- examples/switch/switch.hash | 4 ++-- public/switch | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/switch/switch.hash b/examples/switch/switch.hash index 1bde959..5559e1a 100644 --- a/examples/switch/switch.hash +++ b/examples/switch/switch.hash @@ -1,2 +1,2 @@ -d255a1fe931fe471b745aeb66830b10216617479 -kxkBPpY_ue +b47004b3e3b6d787ea98642dc5b955df57cd2bcd +TJ4Az0KuLfL diff --git a/public/switch b/public/switch index 84ac576..5e82e98 100644 --- a/public/switch +++ b/public/switch @@ -40,7 +40,7 @@ branches.

- +
package main
 
@@ -138,7 +138,7 @@ to express if/else logic. Here we also show how the

A type switch compares types instead of values. You -can use this to discover the the type of an interface +can use this to discover the type of an interface value. In this example, the variable t will have the type corresponding to its clause.

From 4797db65928fd64df327f4490920bc131e237aa2 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:54:35 -0500 Subject: [PATCH 035/133] Rebuild for style fixes --- examples/errors/errors.hash | 4 ++-- examples/maps/maps.hash | 4 ++-- examples/slices/slices.hash | 4 ++-- examples/variadic-functions/variadic-functions.hash | 4 ++-- public/errors | 6 +++--- public/maps | 4 ++-- public/slices | 4 ++-- public/variadic-functions | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/errors/errors.hash b/examples/errors/errors.hash index aceb00c..d0b2112 100644 --- a/examples/errors/errors.hash +++ b/examples/errors/errors.hash @@ -1,2 +1,2 @@ -07cffb3d4e37162ab7e9e0a192561ddc8042b81a -BmDQXkPPTk +210ba0f8196006c0380acaec01655816848ef168 +mP_ZR1qjUvA diff --git a/examples/maps/maps.hash b/examples/maps/maps.hash index c5f8c38..57c1a72 100644 --- a/examples/maps/maps.hash +++ b/examples/maps/maps.hash @@ -1,2 +1,2 @@ -2895d63b87f88ab374256c12dd1539cf7b070b77 -E6cGoiKqka +3e39d07e3f80ecbac558c6fb8baee2a5f914cf97 +U67R66Oab8r diff --git a/examples/slices/slices.hash b/examples/slices/slices.hash index 68bb6a1..8b501cb 100644 --- a/examples/slices/slices.hash +++ b/examples/slices/slices.hash @@ -1,2 +1,2 @@ -d900c3b1cf2bd96591f7ad7ce7fd9e592ec31139 -dPQErsP6Yc +c6fa1627841f199dbf901f88580cb97eb92c5530 +Z3_U32sn8RF diff --git a/examples/variadic-functions/variadic-functions.hash b/examples/variadic-functions/variadic-functions.hash index 95ad82d..3c44a2b 100644 --- a/examples/variadic-functions/variadic-functions.hash +++ b/examples/variadic-functions/variadic-functions.hash @@ -1,2 +1,2 @@ -25bcf8d28adf0587d1959e88f32786d7f21872b2 -wRPLOM1VIH +34ba16069a5d972a837cc5c0172ab30873535220 +7f0JlVhToDD diff --git a/public/errors b/public/errors index ae50908..d402097 100644 --- a/public/errors +++ b/public/errors @@ -46,7 +46,7 @@ non-error tasks.

- +
package main
 
@@ -109,7 +109,7 @@ with the given error message.

-

A nil value in the error position indicates that +

A nil value in the error position indicates that there was no error.

If you want to programmatically use the data in -a custom error, you’ll need to get the error as an +a custom error, you’ll need to get the error as an instance of the custom error type via type assertion.

diff --git a/public/maps b/public/maps index 114b8d0..2829d28 100644 --- a/public/maps +++ b/public/maps @@ -40,7 +40,7 @@
- +
package main
 
@@ -102,7 +102,7 @@ syntax.

-

Printing a map with e.g. Println will show all of +

Printing a map with e.g. fmt.Println will show all of its key/value pairs.

- +
package main
 
@@ -126,7 +126,7 @@ support several more that make them richer than arrays. One is the builtin append, which returns a slice containing one or more new values. Note that we need to accept a return value from -append as we may get a new slice value.

+append as we may get a new slice value.

diff --git a/public/variadic-functions b/public/variadic-functions index a901b83..49b6a0f 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -42,7 +42,7 @@ function.

- +
package main
 
@@ -64,7 +64,7 @@ function.

Here’s a function that will take an arbitrary number -of ints as arguments.

+of ints as arguments.

From ca05e4208456c560ef24becb5521386c1a7662a5 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 17:58:40 -0500 Subject: [PATCH 036/133] Fix goroutines spelling --- examples/goroutines/goroutines.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/goroutines/goroutines.sh b/examples/goroutines/goroutines.sh index 9f5672d..2dcf3bb 100644 --- a/examples/goroutines/goroutines.sh +++ b/examples/goroutines/goroutines.sh @@ -1,6 +1,6 @@ # When we run this program, we see the output of the # blocking call first, then the interleaved output of the -# two gouroutines. This interleaving reflects the +# two goroutines. This interleaving reflects the # goroutines being run concurrently by the Go runtime. $ go run goroutines.go direct : 0 From f31487b81a12100ab8e0e86e8d9ce2f6443de5b0 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Feb 2018 18:00:01 -0500 Subject: [PATCH 037/133] Rebuild for spelling fix --- public/goroutines | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/goroutines b/public/goroutines index b1af6a0..11e301d 100644 --- a/public/goroutines +++ b/public/goroutines @@ -158,7 +158,7 @@ before the program exits.

When we run this program, we see the output of the blocking call first, then the interleaved output of the -two gouroutines. This interleaving reflects the +two goroutines. This interleaving reflects the goroutines being run concurrently by the Go runtime.

- +
package main
 
@@ -104,7 +104,7 @@ our rate limiting scheme.

-
    limiter := time.Tick(time.Millisecond * 200)
+            
    limiter := time.Tick(200 * time.Millisecond)
 
    go func() {
-        for t := range time.Tick(time.Millisecond * 200) {
+        for t := range time.Tick(200 * time.Millisecond) {
             burstyLimiter <- t
         }
     }()
diff --git a/public/select b/public/select
index 86c2434..6384e8b 100644
--- a/public/select
+++ b/public/select
@@ -41,7 +41,7 @@ select is a powerful feature of Go.

- +
package main
 
@@ -97,11 +97,11 @@ executing in concurrent goroutines.

    go func() {
-        time.Sleep(time.Second * 1)
+        time.Sleep(1 * time.Second)
         c1 <- "one"
     }()
     go func() {
-        time.Sleep(time.Second * 2)
+        time.Sleep(2 * time.Second)
         c2 <- "two"
     }()
 
diff --git a/public/tickers b/public/tickers index 8988089..18d65e0 100644 --- a/public/tickers +++ b/public/tickers @@ -43,7 +43,7 @@ periodically until we stop it.

- +
package main
 
@@ -85,7 +85,7 @@ the values as they arrive every 500ms.

-
    ticker := time.NewTicker(time.Millisecond * 500)
+            
    ticker := time.NewTicker(500 * time.Millisecond)
     go func() {
         for t := range ticker.C {
             fmt.Println("Tick at", t)
@@ -105,7 +105,7 @@ channel. We’ll stop ours after 1600ms.

-
    time.Sleep(time.Millisecond * 1600)
+            
    time.Sleep(1600 * time.Millisecond)
     ticker.Stop()
     fmt.Println("Ticker stopped")
 }
diff --git a/public/timeouts b/public/timeouts
index d8f346d..46d44ab 100644
--- a/public/timeouts
+++ b/public/timeouts
@@ -42,7 +42,7 @@ elegant thanks to channels and select.

- +
package main
 
@@ -85,7 +85,7 @@ after 2s.

    c1 := make(chan string, 1)
     go func() {
-        time.Sleep(time.Second * 2)
+        time.Sleep(2 * time.Second)
         c1 <- "result 1"
     }()
 
@@ -108,7 +108,7 @@ if the operation takes more than the allowed 1s.

    select {
     case res := <-c1:
         fmt.Println(res)
-    case <-time.After(time.Second * 1):
+    case <-time.After(1 * time.Second):
         fmt.Println("timeout 1")
     }
 
@@ -126,13 +126,13 @@ from c2 will succeed and we’ll print the result.

    c2 := make(chan string, 1)
     go func() {
-        time.Sleep(time.Second * 2)
+        time.Sleep(2 * time.Second)
         c2 <- "result 2"
     }()
     select {
     case res := <-c2:
         fmt.Println(res)
-    case <-time.After(time.Second * 3):
+    case <-time.After(3 * time.Second):
         fmt.Println("timeout 2")
     }
 }
diff --git a/public/timers b/public/timers
index e87596b..1b67628 100644
--- a/public/timers
+++ b/public/timers
@@ -43,7 +43,7 @@ at tickers.

- +
package main
 
@@ -85,7 +85,7 @@ time. This timer will wait 2 seconds.

-
    timer1 := time.NewTimer(time.Second * 2)
+            
    timer1 := time.NewTimer(2 * time.Second)
 
- +
package main
 
@@ -98,7 +98,10 @@ it will immediately take the default case.

-

A non-blocking send works similarly.

+

A non-blocking send works similarly. Here msg +cannot be sent to the messages channel, because +the channel has no buffer and there is no receiver. +Therefore the default case is selected.

From e8d3222b8ad874bb729f23edd3cfdf5a221a84b3 Mon Sep 17 00:00:00 2001 From: oohira Date: Sat, 10 Feb 2018 10:24:08 +0900 Subject: [PATCH 040/133] Fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d4e5ae..ca958fc 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ To upload the site: ```console $ gem install aws-sdk -$ export export AWS_ACCESS_KEY_ID=... +$ export AWS_ACCESS_KEY_ID=... $ export AWS_SECRET_ACCESS_KEY=... $ tools/upload-site ``` From ce69c753db2bac8e427d419246d7bf6512b47b4c Mon Sep 17 00:00:00 2001 From: Oleg Butuzov Date: Wed, 18 Apr 2018 09:31:00 +0300 Subject: [PATCH 041/133] Article URL updated. + article in url parsing example updated to current version. + in addition - static/hash files regenerated --- examples/url-parsing/url-parsing.go | 2 +- examples/url-parsing/url-parsing.hash | 4 ++-- public/url-parsing | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/url-parsing/url-parsing.go b/examples/url-parsing/url-parsing.go index d4d203b..a70e71f 100644 --- a/examples/url-parsing/url-parsing.go +++ b/examples/url-parsing/url-parsing.go @@ -1,4 +1,4 @@ -// URLs provide a [uniform way to locate resources](http://adam.heroku.com/past/2010/3/30/urls_are_the_uniform_way_to_locate_resources/). +// URLs provide a [uniform way to locate resources](https://adam.herokuapp.com/past/2010/3/30/urls_are_the_uniform_way_to_locate_resources/). // Here's how to parse URLs in Go. package main diff --git a/examples/url-parsing/url-parsing.hash b/examples/url-parsing/url-parsing.hash index a7fb972..019a1a6 100644 --- a/examples/url-parsing/url-parsing.hash +++ b/examples/url-parsing/url-parsing.hash @@ -1,2 +1,2 @@ -2a74211d0a7bc639c874d7be41e816bf168475d8 -e8HvuLLUw_ +b7a0813e9413bfcc956cc58b850f655dd129ebb7 +AL79Lv-9CWo diff --git a/public/url-parsing b/public/url-parsing index 9b3f974..31321f9 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -25,7 +25,7 @@
-

URLs provide a uniform way to locate resources. +

URLs provide a uniform way to locate resources. Here’s how to parse URLs in Go.

- +
package main
 
From bf6d887170b0a2855f9370c44b0afa567a9860de Mon Sep 17 00:00:00 2001 From: Oleg Butuzov Date: Tue, 19 Jun 2018 09:41:04 +0300 Subject: [PATCH 042/133] Ukrainian translation added. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ca958fc..174441c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ Contributor translations of the Go by Example site are available in: * [Italian](http://gobyexample.it) by the [Go Italian community](https://github.com/golangit/gobyexample-it) * [Korean](https://mingrammer.com/gobyexample/) by [mingrammer](https://github.com/mingrammer) * [Spanish](http://goconejemplos.com) by the [Go Mexico community](https://github.com/dabit/gobyexample) +* [Ukrainian](http://gobyexample.com.ua/) by [butuzov](https://github.com/butuzov/gobyexample) ### Thanks From 3f4d78ef6dc863c12e76a5679bc4b989eda2a75a Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Wed, 5 Dec 2018 15:48:40 -0500 Subject: [PATCH 043/133] Change example text in variables.go Instead of 'short', which is a common programming language keyword, use something random like 'apple'. This way it prevents confusion from people learning explicit variable declaration, and thinking the type is a short instead of a string. --- examples/variables/variables.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/variables/variables.go b/examples/variables/variables.go index 13b371c..abff6b9 100644 --- a/examples/variables/variables.go +++ b/examples/variables/variables.go @@ -28,7 +28,7 @@ func main() { // The `:=` syntax is shorthand for declaring and // initializing a variable, e.g. for - // `var f string = "short"` in this case. - f := "short" + // `var f string = "apple"` in this case. + f := "apple" fmt.Println(f) } From 501b8104ee79be0344535ab27db91147826f8596 Mon Sep 17 00:00:00 2001 From: spinute Date: Sun, 6 Jan 2019 09:30:23 +0800 Subject: [PATCH 044/133] add a link to Japanese translation in README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 174441c..0c73e20 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Contributor translations of the Go by Example site are available in: * [Chinese](https://gobyexample.xgwang.me/) by [xg-wang](https://github.com/xg-wang/gobyexample) * [French](http://le-go-par-l-exemple.keiruaprod.fr) by [keirua](https://github.com/keirua/gobyexample) * [Italian](http://gobyexample.it) by the [Go Italian community](https://github.com/golangit/gobyexample-it) +* [Japanese](http://spinute.org/go-by-example) by [spinute](https://github.com/spinute) * [Korean](https://mingrammer.com/gobyexample/) by [mingrammer](https://github.com/mingrammer) * [Spanish](http://goconejemplos.com) by the [Go Mexico community](https://github.com/dabit/gobyexample) * [Ukrainian](http://gobyexample.com.ua/) by [butuzov](https://github.com/butuzov/gobyexample) From 8656320237172821a7b0751c3c778d57aa00aa09 Mon Sep 17 00:00:00 2001 From: Go101 <22589241+go101@users.noreply.github.com> Date: Tue, 26 Feb 2019 12:29:27 -0400 Subject: [PATCH 045/133] update for Go 1.12 --- examples/maps/maps.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/maps/maps.sh b/examples/maps/maps.sh index bb667f4..03e1a25 100644 --- a/examples/maps/maps.sh +++ b/examples/maps/maps.sh @@ -6,4 +6,6 @@ v1: 7 len: 2 map: map[k1:7] prs: false -map: map[foo:1 bar:2] +map: map[bar:2 foo:1] + + From cdd115dfc80b82a986589cc2443526c81165e08e Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Wed, 20 Mar 2019 11:28:21 -0700 Subject: [PATCH 046/133] Update author links --- public/arrays | 2 +- public/atomic-counters | 2 +- public/base64-encoding | 2 +- public/channel-buffering | 2 +- public/channel-directions | 2 +- public/channel-synchronization | 2 +- public/channels | 2 +- public/closing-channels | 2 +- public/closures | 2 +- public/collection-functions | 2 +- public/command-line-arguments | 2 +- public/command-line-flags | 2 +- public/constants | 2 +- public/defer | 2 +- public/environment-variables | 2 +- public/epoch | 2 +- public/errors | 2 +- public/execing-processes | 2 +- public/exit | 2 +- public/for | 2 +- public/functions | 2 +- public/goroutines | 2 +- public/hello-world | 2 +- public/if-else | 2 +- public/index.html | 2 +- public/interfaces | 2 +- public/json | 2 +- public/line-filters | 2 +- public/maps | 2 +- public/methods | 2 +- public/multiple-return-values | 2 +- public/mutexes | 2 +- public/non-blocking-channel-operations | 2 +- public/number-parsing | 2 +- public/panic | 2 +- public/pointers | 2 +- public/random-numbers | 2 +- public/range | 2 +- public/range-over-channels | 2 +- public/rate-limiting | 2 +- public/reading-files | 2 +- public/recursion | 2 +- public/regular-expressions | 2 +- public/select | 2 +- public/sha1-hashes | 2 +- public/signals | 2 +- public/slices | 2 +- public/sorting | 2 +- public/sorting-by-functions | 2 +- public/spawning-processes | 2 +- public/stateful-goroutines | 2 +- public/string-formatting | 2 +- public/string-functions | 2 +- public/structs | 2 +- public/switch | 2 +- public/tickers | 2 +- public/time | 2 +- public/time-formatting-parsing | 2 +- public/timeouts | 2 +- public/timers | 2 +- public/url-parsing | 2 +- public/values | 2 +- public/variables | 2 +- public/variadic-functions | 2 +- public/worker-pools | 2 +- public/writing-files | 2 +- templates/example.tmpl | 2 +- templates/index.tmpl | 2 +- 68 files changed, 68 insertions(+), 68 deletions(-) diff --git a/public/arrays b/public/arrays index e173da9..606ea6e 100644 --- a/public/arrays +++ b/public/arrays @@ -199,7 +199,7 @@ typical Go. We’ll look at slices next.

diff --git a/public/atomic-counters b/public/atomic-counters index 0afd46e..0eb8aea 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -212,7 +212,7 @@ state.

diff --git a/public/base64-encoding b/public/base64-encoding index 2389ba3..fa3528a 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -182,7 +182,7 @@ but they both decode to the original string as desired.

diff --git a/public/channel-buffering b/public/channel-buffering index 74e6fa3..796efe8 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -146,7 +146,7 @@ concurrent receive.

diff --git a/public/channel-directions b/public/channel-directions index 134697b..84e130e 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -138,7 +138,7 @@ receive on this channel.

diff --git a/public/channel-synchronization b/public/channel-synchronization index f13f33d..7a974b3 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -173,7 +173,7 @@ started.

diff --git a/public/channels b/public/channels index 19f60d3..5d5d7e9 100644 --- a/public/channels +++ b/public/channels @@ -161,7 +161,7 @@ message without having to use any other synchronization.

diff --git a/public/closing-channels b/public/closing-channels index 384dc97..8730c42 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -187,7 +187,7 @@ example: range over channels.

diff --git a/public/closures b/public/closures index 12d2443..3afcb89 100644 --- a/public/closures +++ b/public/closures @@ -183,7 +183,7 @@ recursion.

diff --git a/public/collection-functions b/public/collection-functions index 0d2e11a..9b533d9 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -362,7 +362,7 @@ type.

diff --git a/public/command-line-arguments b/public/command-line-arguments index 7fb2e79..fa26f6c 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -161,7 +161,7 @@ with flags.

diff --git a/public/command-line-flags b/public/command-line-flags index 9414b9e..6c49752 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -313,7 +313,7 @@ way to parameterize programs.

diff --git a/public/constants b/public/constants index 7942b0f..76a6a89 100644 --- a/public/constants +++ b/public/constants @@ -174,7 +174,7 @@ assignment or function call. For example, here

diff --git a/public/defer b/public/defer index 98dc9e4..57d15fb 100644 --- a/public/defer +++ b/public/defer @@ -186,7 +186,7 @@ after being written.

diff --git a/public/environment-variables b/public/environment-variables index 1fbccfc..e2d7849 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -177,7 +177,7 @@ program picks that value up.

diff --git a/public/epoch b/public/epoch index 4db41c1..fe25dec 100644 --- a/public/epoch +++ b/public/epoch @@ -168,7 +168,7 @@ parsing and formatting.

diff --git a/public/errors b/public/errors index d402097..72ca49d 100644 --- a/public/errors +++ b/public/errors @@ -290,7 +290,7 @@ on the Go blog for more on error handling.

diff --git a/public/execing-processes b/public/execing-processes index a22e259..531e8f5 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -194,7 +194,7 @@ processes covers most use cases for fork.

diff --git a/public/exit b/public/exit index 071806b..721fbaa 100644 --- a/public/exit +++ b/public/exit @@ -165,7 +165,7 @@ the status in the terminal.

diff --git a/public/for b/public/for index ffffa5d..f7c841e 100644 --- a/public/for +++ b/public/for @@ -188,7 +188,7 @@ structures.

diff --git a/public/functions b/public/functions index f17fae9..debd8cb 100644 --- a/public/functions +++ b/public/functions @@ -186,7 +186,7 @@ multiple return values, which we’ll look at next.

diff --git a/public/goroutines b/public/goroutines index 11e301d..f46db9e 100644 --- a/public/goroutines +++ b/public/goroutines @@ -199,7 +199,7 @@ concurrent Go programs: channels.

diff --git a/public/hello-world b/public/hello-world index a4660a1..e6a37bd 100644 --- a/public/hello-world +++ b/public/hello-world @@ -132,7 +132,7 @@ learn more about the language.

diff --git a/public/if-else b/public/if-else index a161732..499fb4c 100644 --- a/public/if-else +++ b/public/if-else @@ -177,7 +177,7 @@ for basic conditions.

diff --git a/public/index.html b/public/index.html index c35be82..eaffb11 100644 --- a/public/index.html +++ b/public/index.html @@ -167,7 +167,7 @@ diff --git a/public/interfaces b/public/interfaces index 0f06447..ff701bd 100644 --- a/public/interfaces +++ b/public/interfaces @@ -227,7 +227,7 @@ these structs as arguments to measure.

diff --git a/public/json b/public/json index 5cd6e90..c23254e 100644 --- a/public/json +++ b/public/json @@ -394,7 +394,7 @@ for more.

diff --git a/public/line-filters b/public/line-filters index 7d0b994..2e9a547 100644 --- a/public/line-filters +++ b/public/line-filters @@ -197,7 +197,7 @@ lowercase lines.

diff --git a/public/maps b/public/maps index 2829d28..0cbf53c 100644 --- a/public/maps +++ b/public/maps @@ -225,7 +225,7 @@ printed with fmt.Println.

diff --git a/public/methods b/public/methods index 2245fba..856f473 100644 --- a/public/methods +++ b/public/methods @@ -190,7 +190,7 @@ naming related sets of methods: interfaces.

diff --git a/public/multiple-return-values b/public/multiple-return-values index fc2a627..ca34e40 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -159,7 +159,7 @@ feature of Go functions; we’ll look at this next.

diff --git a/public/mutexes b/public/mutexes index 7940e38..9c19368 100644 --- a/public/mutexes +++ b/public/mutexes @@ -290,7 +290,7 @@ management task using only goroutines and channels.

diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index 2e2e713..d7e2c1a 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -169,7 +169,7 @@ on both messages and signals.

diff --git a/public/number-parsing b/public/number-parsing index caf908d..288d9b7 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -204,7 +204,7 @@ bits.

diff --git a/public/panic b/public/panic index cfd8cbe..27a416a 100644 --- a/public/panic +++ b/public/panic @@ -165,7 +165,7 @@ to use error-indicating return values wherever possible.

diff --git a/public/pointers b/public/pointers index 9587b1d..62738ba 100644 --- a/public/pointers +++ b/public/pointers @@ -186,7 +186,7 @@ the memory address for that variable.

diff --git a/public/random-numbers b/public/random-numbers index bd84c0e..49f46c1 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -220,7 +220,7 @@ that Go can provide.

diff --git a/public/range b/public/range index f2532e8..09ab1ec 100644 --- a/public/range +++ b/public/range @@ -193,7 +193,7 @@ of the rune and the second the rune itself.

diff --git a/public/range-over-channels b/public/range-over-channels index 1362df6..e189190 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -147,7 +147,7 @@ values be received.

diff --git a/public/rate-limiting b/public/rate-limiting index 39a49c9..d635e11 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -252,7 +252,7 @@ then serve the remaining 2 with ~200ms delays each.

diff --git a/public/reading-files b/public/reading-files index 0545c3e..39e51de 100644 --- a/public/reading-files +++ b/public/reading-files @@ -290,7 +290,7 @@ be scheduled immediately after Opening with

diff --git a/public/recursion b/public/recursion index 069788c..844b85f 100644 --- a/public/recursion +++ b/public/recursion @@ -118,7 +118,7 @@ base case of fact(0).

diff --git a/public/regular-expressions b/public/regular-expressions index c7cd1ac..f000e06 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -333,7 +333,7 @@ the regexp package docs

diff --git a/public/select b/public/select index 6384e8b..f8ba88f 100644 --- a/public/select +++ b/public/select @@ -174,7 +174,7 @@ concurrently.

diff --git a/public/sha1-hashes b/public/sha1-hashes index 85e318f..66c6d77 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -194,7 +194,7 @@ you should carefully research

diff --git a/public/signals b/public/signals index 5103605..3288d91 100644 --- a/public/signals +++ b/public/signals @@ -179,7 +179,7 @@ causing the program to print interrupt and then exit.

diff --git a/public/slices b/public/slices index 412b741..ba38bc0 100644 --- a/public/slices +++ b/public/slices @@ -301,7 +301,7 @@ Go’s other key builtin data structure: maps.

diff --git a/public/sorting b/public/sorting index 9213a92..328e32c 100644 --- a/public/sorting +++ b/public/sorting @@ -151,7 +151,7 @@ slices and true as the result of our AreSorted test. diff --git a/public/sorting-by-functions b/public/sorting-by-functions index 710700f..cb0f615 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -168,7 +168,7 @@ functions.

diff --git a/public/spawning-processes b/public/spawning-processes index 62c3d3d..db1f72b 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -250,7 +250,7 @@ as if we had run them directly from the command-line.

diff --git a/public/stateful-goroutines b/public/stateful-goroutines index aa0579e..69d83a8 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -305,7 +305,7 @@ program.

diff --git a/public/string-formatting b/public/string-formatting index 0e63591..b884639 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -448,7 +448,7 @@ and returns a string without printing it anywhere.

diff --git a/public/string-functions b/public/string-functions index 30b2914..9594a23 100644 --- a/public/string-functions +++ b/public/string-functions @@ -200,7 +200,7 @@ for more information.

diff --git a/public/structs b/public/structs index 3b98324..c9f3181 100644 --- a/public/structs +++ b/public/structs @@ -215,7 +215,7 @@ pointers are automatically dereferenced.

diff --git a/public/switch b/public/switch index 5e82e98..32127df 100644 --- a/public/switch +++ b/public/switch @@ -194,7 +194,7 @@ type corresponding to its clause.

diff --git a/public/tickers b/public/tickers index 18d65e0..cf16820 100644 --- a/public/tickers +++ b/public/tickers @@ -144,7 +144,7 @@ before we stop it.

diff --git a/public/time b/public/time index ebc1a34..017a30f 100644 --- a/public/time +++ b/public/time @@ -261,7 +261,7 @@ the Unix epoch.

diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index b3a8a5c..7a154fb 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -195,7 +195,7 @@ explaining the parsing problem.

diff --git a/public/timeouts b/public/timeouts index 46d44ab..f19ecae 100644 --- a/public/timeouts +++ b/public/timeouts @@ -184,7 +184,7 @@ examples of this next: timers and tickers.

diff --git a/public/timers b/public/timers index 1b67628..4c2e27a 100644 --- a/public/timers +++ b/public/timers @@ -161,7 +161,7 @@ a chance to expire.

diff --git a/public/url-parsing b/public/url-parsing index 31321f9..4fba27c 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -226,7 +226,7 @@ pieces that we extracted.

diff --git a/public/values b/public/values index 03809d1..5a815cd 100644 --- a/public/values +++ b/public/values @@ -145,7 +145,7 @@ basic examples.

diff --git a/public/variables b/public/variables index 856f4c5..7f81e33 100644 --- a/public/variables +++ b/public/variables @@ -176,7 +176,7 @@ initializing a variable, e.g. for

diff --git a/public/variadic-functions b/public/variadic-functions index 49b6a0f..5991544 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -165,7 +165,7 @@ to form closures, which we’ll look at next.

diff --git a/public/worker-pools b/public/worker-pools index ba84dfe..baeb60a 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -211,7 +211,7 @@ there are 3 workers operating concurrently.

diff --git a/public/writing-files b/public/writing-files index fba471e..21cdd86 100644 --- a/public/writing-files +++ b/public/writing-files @@ -280,7 +280,7 @@ we’ve just seen to the stdin and stdout streams.

diff --git a/templates/example.tmpl b/templates/example.tmpl index 8315df7..3952463 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -41,7 +41,7 @@

{{end}} diff --git a/templates/index.tmpl b/templates/index.tmpl index 313904d..929d3c1 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -39,7 +39,7 @@ {{end}} From c43c319d2684b5ad7601e97b5fc2ba54552de4c3 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Wed, 20 Mar 2019 11:30:56 -0700 Subject: [PATCH 047/133] Add local serve script --- tools/serve | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 tools/serve diff --git a/tools/serve b/tools/serve new file mode 100755 index 0000000..9c74d8e --- /dev/null +++ b/tools/serve @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import SimpleHTTPServer +import SocketServer +import os + +PORT = 8000 + +public_dir = os.path.join(os.path.dirname(__file__), '..', 'public') +os.chdir(public_dir) + +Handler = SimpleHTTPServer.SimpleHTTPRequestHandler +Handler.extensions_map.update({ + '': 'text/html', +}); +httpd = SocketServer.TCPServer(("", PORT), Handler) +httpd.serve_forever() From 6ab81bdf71ec1cbfb178fecde2f1d32beec35eeb Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Wed, 29 May 2019 06:01:58 -0700 Subject: [PATCH 048/133] Add "Waiting For Goroutines To Finish" example. Also link to it from the Channel Synchronization example --- examples.txt | 1 + .../channel-synchronization.go | 2 + .../channel-synchronization.hash | 4 +- .../waiting-for-goroutines-to-finish.go | 47 ++++ .../waiting-for-goroutines-to-finish.hash | 2 + .../waiting-for-goroutines-to-finish.sh | 14 ++ public/channel-synchronization | 8 +- public/index.html | 2 + public/waiting-for-goroutines-to-finish | 223 ++++++++++++++++++ 9 files changed, 298 insertions(+), 5 deletions(-) create mode 100644 examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go create mode 100644 examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash create mode 100644 examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh create mode 100644 public/waiting-for-goroutines-to-finish diff --git a/examples.txt b/examples.txt index 8859292..289ee58 100644 --- a/examples.txt +++ b/examples.txt @@ -23,6 +23,7 @@ Goroutines Channels Channel Buffering Channel Synchronization +Waiting For Goroutines To Finish Channel Directions Select Timeouts diff --git a/examples/channel-synchronization/channel-synchronization.go b/examples/channel-synchronization/channel-synchronization.go index 4cc1461..6b18be1 100644 --- a/examples/channel-synchronization/channel-synchronization.go +++ b/examples/channel-synchronization/channel-synchronization.go @@ -1,6 +1,8 @@ // We can use channels to synchronize execution // across goroutines. Here's an example of using a // blocking receive to wait for a goroutine to finish. +// When waiting for multiple goroutines to finish, +// you may prefer to [use a WaitGroup](waiting-for-goroutines-to-finish). package main diff --git a/examples/channel-synchronization/channel-synchronization.hash b/examples/channel-synchronization/channel-synchronization.hash index 8680448..8fba20d 100644 --- a/examples/channel-synchronization/channel-synchronization.hash +++ b/examples/channel-synchronization/channel-synchronization.hash @@ -1,2 +1,2 @@ -fe3e2ea1a67d0f95ce4cb18f3e8aa16d416de0ce -0DfW-1RMqi +df90432a53832c045472981a9da23d1139fb2b5c +f6qTtt1agmN diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go new file mode 100644 index 0000000..db49ad4 --- /dev/null +++ b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go @@ -0,0 +1,47 @@ +// To wait for multiple goroutines to finish, we can +// use a sync.WaitGroup. + +package main + +import ( + "fmt" + "math/rand" + "sync" + "time" +) + +// This is the function we'll run in every goroutine. +// wg is the WaitGroup it uses to notify that it's done. +// Note that a WaitGroup must be passed to functions by +// pointer. +func worker(id int, wg *sync.WaitGroup) { + fmt.Printf("Worker %d starting\n", id) + + // Sleep for a random duration between 500-700 ms + // to simulate work. See the [random numbers](random-numbers) + // example for more details on *rand*. + msToSleep := time.Duration(500 + rand.Intn(200)) + time.Sleep(msToSleep * time.Millisecond) + fmt.Printf("Worker %d done\n", id) + + // Notify the WaitGroup that we're done. + wg.Done() +} + +func main() { + + // This WaitGroup is used to wait for all the + // goroutines launched here to finish. + var wg sync.WaitGroup + + // Launch several goroutines and increment the WorkGroup + // counter for each. + for i := 1; i <= 5; i++ { + wg.Add(1) + go worker(i, &wg) + } + + // Block until the WorkGroup counter goes back to 0; + // all the workers notified they're done. + wg.Wait() +} diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash new file mode 100644 index 0000000..00b9360 --- /dev/null +++ b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash @@ -0,0 +1,2 @@ +f068072d11ed9469174c18f5b7a6a7d9d8d3dafb +koKzXfbq8kg diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh new file mode 100644 index 0000000..f68210c --- /dev/null +++ b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh @@ -0,0 +1,14 @@ +$ go run waiting-for-goroutines-to-finish.go +Worker 5 starting +Worker 3 starting +Worker 4 starting +Worker 1 starting +Worker 2 starting +Worker 4 done +Worker 1 done +Worker 2 done +Worker 5 done +Worker 3 done + +# The order of workers starting up and finishing +# is likely to be different for each invocation. diff --git a/public/channel-synchronization b/public/channel-synchronization index 7a974b3..9c26e54 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -27,7 +27,9 @@

We can use channels to synchronize execution across goroutines. Here’s an example of using a -blocking receive to wait for a goroutine to finish.

+blocking receive to wait for a goroutine to finish. +When waiting for multiple goroutines to finish, +you may prefer to use a WaitGroup.

@@ -41,7 +43,7 @@ blocking receive to wait for a goroutine to finish.

- +
package main
 
@@ -169,7 +171,7 @@ started.

- Next example: Channel Directions. + Next example: Waiting For Goroutines To Finish.

  • Channel Synchronization
  • +
  • Waiting For Goroutines To Finish
  • +
  • Channel Directions
  • Select
  • diff --git a/public/waiting-for-goroutines-to-finish b/public/waiting-for-goroutines-to-finish new file mode 100644 index 0000000..4f20729 --- /dev/null +++ b/public/waiting-for-goroutines-to-finish @@ -0,0 +1,223 @@ + + + + + Go by Example: Waiting For Goroutines To Finish + + + + +
    +

    Go by Example: Waiting For Goroutines To Finish

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    To wait for multiple goroutines to finish, we can +use a sync.WaitGroup.

    + +
    + + +
    + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "math/rand"
    +    "sync"
    +    "time"
    +)
    +
    + +
    +

    This is the function we’ll run in every goroutine. +wg is the WaitGroup it uses to notify that it’s done. +Note that a WaitGroup must be passed to functions by +pointer.

    + +
    + +
    func worker(id int, wg *sync.WaitGroup) {
    +    fmt.Printf("Worker %d starting\n", id)
    +
    + +
    +

    Sleep for a random duration between 500-700 ms +to simulate work. See the random numbers +example for more details on rand.

    + +
    + +
        msToSleep := time.Duration(500 + rand.Intn(200))
    +    time.Sleep(msToSleep * time.Millisecond)
    +    fmt.Printf("Worker %d done\n", id)
    +
    + +
    +

    Notify the WaitGroup that we’re done.

    + +
    + +
        wg.Done()
    +}
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    This WaitGroup is used to wait for all the +goroutines launched here to finish.

    + +
    + +
        var wg sync.WaitGroup
    +
    + +
    +

    Launch several goroutines and increment the WorkGroup +counter for each.

    + +
    + +
        for i := 1; i <= 5; i++ {
    +        wg.Add(1)
    +        go worker(i, &wg)
    +    }
    +
    + +
    +

    Block until the WorkGroup counter goes back to 0; +all the workers notified they’re done.

    + +
    + +
        wg.Wait()
    +}
    +
    + +
    + + + + + + + + + + + + + +
    + + + +
    $ go run waiting-for-goroutines-to-finish.go
    +Worker 5 starting
    +Worker 3 starting
    +Worker 4 starting
    +Worker 1 starting
    +Worker 2 starting
    +Worker 4 done
    +Worker 1 done
    +Worker 2 done
    +Worker 5 done
    +Worker 3 done
    +
    + +
    +

    The order of workers starting up and finishing +is likely to be different for each invocation.

    + +
    + + +
    + + +

    + Next example: Channel Directions. +

    + + +
    + + From 0f3141a5fcfbbe0f19ff773cfe0e63292bbc7abf Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Wed, 29 May 2019 07:37:07 -0700 Subject: [PATCH 049/133] Remove bios.sh for now --- bios.sh | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100755 bios.sh diff --git a/bios.sh b/bios.sh deleted file mode 100755 index 3a3f525..0000000 --- a/bios.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -set -ex - -mkdir -p src/$PKG && cd src/$PKG -run -s "Cloning" git clone $URL --branch $REF --single-branch . -git reset --hard $SHA - -go get github.com/russross/blackfriday -go get github.com/golang/lint/golint - -PKGS=$(go list $PKG/... | grep -v examples/variables) -run -s "Linting" golint -set_exit_status $PKGS - -PKGS=$(go list $PKG/... | grep -v examples/panic) -run -s "Vetting" go vet -x $PKGS - -run -s "Building" tools/build - -run -s "Verifying" git diff --exit-code From be8a0d93ba796fcd91655f7c63eab282c9152f7c Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Wed, 29 May 2019 07:44:10 -0700 Subject: [PATCH 050/133] Indicate where we're serving --- tools/serve | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/serve b/tools/serve index 9c74d8e..7f67eb8 100755 --- a/tools/serve +++ b/tools/serve @@ -14,4 +14,6 @@ Handler.extensions_map.update({ '': 'text/html', }); httpd = SocketServer.TCPServer(("", PORT), Handler) + +print("Serving Go by Example at http://127.0.0.1:{}".format(PORT)) httpd.serve_forever() From f3f319cccea3b002183601c93943e2ee95877919 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Wed, 29 May 2019 13:46:05 -0700 Subject: [PATCH 051/133] Rewrite the local server in Go --- tools/serve | 18 ++---------------- tools/serve.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 tools/serve.go diff --git a/tools/serve b/tools/serve index 9c74d8e..baf68d1 100755 --- a/tools/serve +++ b/tools/serve @@ -1,17 +1,3 @@ -#!/usr/bin/python +#!/bin/bash -import SimpleHTTPServer -import SocketServer -import os - -PORT = 8000 - -public_dir = os.path.join(os.path.dirname(__file__), '..', 'public') -os.chdir(public_dir) - -Handler = SimpleHTTPServer.SimpleHTTPRequestHandler -Handler.extensions_map.update({ - '': 'text/html', -}); -httpd = SocketServer.TCPServer(("", PORT), Handler) -httpd.serve_forever() +exec go run tools/serve.go diff --git a/tools/serve.go b/tools/serve.go new file mode 100644 index 0000000..c54f79b --- /dev/null +++ b/tools/serve.go @@ -0,0 +1,15 @@ +package main + +import ( + "fmt" + "net/http" +) + +func main() { + port := "8000" + publicDir := "public" + fmt.Printf("Serving Go by Example at http://127.0.0.1:%s\n", port) + + // Simple static webserver: + http.ListenAndServe(":"+port, http.FileServer(http.Dir(publicDir))) +} From 9e31d5eb10efc123df29c551dab37e3a6205efeb Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Wed, 29 May 2019 13:49:42 -0700 Subject: [PATCH 052/133] Remove old comment --- tools/serve.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/serve.go b/tools/serve.go index c54f79b..b31a6b0 100644 --- a/tools/serve.go +++ b/tools/serve.go @@ -9,7 +9,5 @@ func main() { port := "8000" publicDir := "public" fmt.Printf("Serving Go by Example at http://127.0.0.1:%s\n", port) - - // Simple static webserver: http.ListenAndServe(":"+port, http.FileServer(http.Dir(publicDir))) } From 74ca2a7b0f812690b0e5e5198ae03667da9219a8 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:28:29 -0700 Subject: [PATCH 053/133] Addressing review comments * Renamed the example * Reworded comments * Moved it to after worker pools * Sleep for a second instead of random * Mention the new sample in worker pools --- examples.txt | 2 +- .../waitgroup.go} | 11 +--- examples/waitgroup/waitgroup.hash | 2 + .../waitgroup.sh} | 2 +- .../waiting-for-goroutines-to-finish.hash | 2 - examples/worker-pools/worker-pools.go | 55 ++++++++++--------- examples/worker-pools/worker-pools.hash | 4 +- public/channel-synchronization | 2 +- public/index.html | 4 +- public/worker-pools | 10 +++- 10 files changed, 48 insertions(+), 46 deletions(-) rename examples/{waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go => waitgroup/waitgroup.go} (70%) create mode 100644 examples/waitgroup/waitgroup.hash rename examples/{waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh => waitgroup/waitgroup.sh} (85%) delete mode 100644 examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash diff --git a/examples.txt b/examples.txt index 289ee58..6153867 100644 --- a/examples.txt +++ b/examples.txt @@ -23,7 +23,6 @@ Goroutines Channels Channel Buffering Channel Synchronization -Waiting For Goroutines To Finish Channel Directions Select Timeouts @@ -33,6 +32,7 @@ Range over Channels Timers Tickers Worker Pools +WaitGroup Rate Limiting Atomic Counters Mutexes diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go b/examples/waitgroup/waitgroup.go similarity index 70% rename from examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go rename to examples/waitgroup/waitgroup.go index db49ad4..65c4212 100644 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go +++ b/examples/waitgroup/waitgroup.go @@ -1,27 +1,22 @@ // To wait for multiple goroutines to finish, we can -// use a sync.WaitGroup. +// use a *wait group*. package main import ( "fmt" - "math/rand" "sync" "time" ) // This is the function we'll run in every goroutine. -// wg is the WaitGroup it uses to notify that it's done. // Note that a WaitGroup must be passed to functions by // pointer. func worker(id int, wg *sync.WaitGroup) { fmt.Printf("Worker %d starting\n", id) - // Sleep for a random duration between 500-700 ms - // to simulate work. See the [random numbers](random-numbers) - // example for more details on *rand*. - msToSleep := time.Duration(500 + rand.Intn(200)) - time.Sleep(msToSleep * time.Millisecond) + // Sleep to simulate an expensive task. + time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) // Notify the WaitGroup that we're done. diff --git a/examples/waitgroup/waitgroup.hash b/examples/waitgroup/waitgroup.hash new file mode 100644 index 0000000..1df8a2f --- /dev/null +++ b/examples/waitgroup/waitgroup.hash @@ -0,0 +1,2 @@ +ffc6520e73ebfa2b8c470e3ef00fee55388234e0 +8cD2V9CgI0J diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh b/examples/waitgroup/waitgroup.sh similarity index 85% rename from examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh rename to examples/waitgroup/waitgroup.sh index f68210c..13293bc 100644 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh +++ b/examples/waitgroup/waitgroup.sh @@ -1,4 +1,4 @@ -$ go run waiting-for-goroutines-to-finish.go +$ go run waitgroup.go Worker 5 starting Worker 3 starting Worker 4 starting diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash deleted file mode 100644 index 00b9360..0000000 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash +++ /dev/null @@ -1,2 +0,0 @@ -f068072d11ed9469174c18f5b7a6a7d9d8d3dafb -koKzXfbq8kg diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index 1114a22..443957e 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -12,37 +12,40 @@ import "time" // results on `results`. We'll sleep a second per job to // simulate an expensive task. func worker(id int, jobs <-chan int, results chan<- int) { - for j := range jobs { - fmt.Println("worker", id, "started job", j) - time.Sleep(time.Second) - fmt.Println("worker", id, "finished job", j) - results <- j * 2 - } + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } } func main() { - // In order to use our pool of workers we need to send - // them work and collect their results. We make 2 - // channels for this. - jobs := make(chan int, 100) - results := make(chan int, 100) + // In order to use our pool of workers we need to send + // them work and collect their results. We make 2 + // channels for this. + jobs := make(chan int, 100) + results := make(chan int, 100) - // This starts up 3 workers, initially blocked - // because there are no jobs yet. - for w := 1; w <= 3; w++ { - go worker(w, jobs, results) - } + // This starts up 3 workers, initially blocked + // because there are no jobs yet. + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } - // Here we send 5 `jobs` and then `close` that - // channel to indicate that's all the work we have. - for j := 1; j <= 5; j++ { - jobs <- j - } - close(jobs) + // Here we send 5 `jobs` and then `close` that + // channel to indicate that's all the work we have. + for j := 1; j <= 5; j++ { + jobs <- j + } + close(jobs) - // Finally we collect all the results of the work. - for a := 1; a <= 5; a++ { - <-results - } + // Finally we collect all the results of the work. + // This also ensures that the worker goroutines have + // finished. An alternative way to wait for multiple + // goroutines is to use a [WaitGroup](waitgroup). + for a := 1; a <= 5; a++ { + <-results + } } diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index 013b2de..ee8c3c7 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -1f9acf1e50be05cad73e6b085ed3294892c67d42 -RTRcHA05vV +bfd2824b3840ff67fa9a0218c7be66647b4bf3d9 +IQestAFcxLh diff --git a/public/channel-synchronization b/public/channel-synchronization index 9c26e54..e79fe04 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -171,7 +171,7 @@ started.

    - Next example: Waiting For Goroutines To Finish. + Next example: Channel Directions.

  • Channel Synchronization
  • -
  • Waiting For Goroutines To Finish
  • -
  • Channel Directions
  • Select
  • @@ -105,6 +103,8 @@
  • Worker Pools
  • +
  • WaitGroup
  • +
  • Rate Limiting
  • Atomic Counters
  • diff --git a/public/worker-pools b/public/worker-pools index baeb60a..8ff2427 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -40,7 +40,7 @@ a worker pool using goroutines and channels.

    - +
    package main
     
    @@ -147,7 +147,11 @@ channel to indicate that’s all the work we have.

    -

    Finally we collect all the results of the work.

    +

    Finally we collect all the results of the work. +This also ensures that the worker goroutines have +finished. An alternative way to wait for multiple +goroutines that’s useful in many scenarios is +to use a WaitGroup.

    @@ -207,7 +211,7 @@ there are 3 workers operating concurrently.

    - Next example: Rate Limiting. + Next example: WaitGroup.

    +

    Go by Example: WaitGroup

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    To wait for multiple goroutines to finish, we can +use a wait group.

    + +
    + + +
    + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "sync"
    +    "time"
    +)
    +
    + +
    +

    This is the function we’ll run in every goroutine. +Note that a WaitGroup must be passed to functions by +pointer.

    + +
    + +
    func worker(id int, wg *sync.WaitGroup) {
    +    fmt.Printf("Worker %d starting\n", id)
    +
    + +
    +

    Sleep to simulate an expensive task.

    + +
    + +
        time.Sleep(time.Second)
    +    fmt.Printf("Worker %d done\n", id)
    +
    + +
    +

    Notify the WaitGroup that we’re done.

    + +
    + +
        wg.Done()
    +}
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    This WaitGroup is used to wait for all the +goroutines launched here to finish.

    + +
    + +
        var wg sync.WaitGroup
    +
    + +
    +

    Launch several goroutines and increment the WorkGroup +counter for each.

    + +
    + +
        for i := 1; i <= 5; i++ {
    +        wg.Add(1)
    +        go worker(i, &wg)
    +    }
    +
    + +
    +

    Block until the WorkGroup counter goes back to 0; +all the workers notified they’re done.

    + +
    + +
        wg.Wait()
    +}
    +
    + +
    + + + + + + + + + + + + + +
    + + + +
    $ go run waitgroup.go
    +Worker 5 starting
    +Worker 3 starting
    +Worker 4 starting
    +Worker 1 starting
    +Worker 2 starting
    +Worker 4 done
    +Worker 1 done
    +Worker 2 done
    +Worker 5 done
    +Worker 3 done
    +
    + +
    +

    The order of workers starting up and finishing +is likely to be different for each invocation.

    + +
    + + +
    + + +

    + Next example: Rate Limiting. +

    + + +
    + + From 3010af04fc07dcfd1fe1637b3ccba4cdefb89d18 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:40:18 -0700 Subject: [PATCH 055/133] Rerun tools/build to reformat --- examples/worker-pools/worker-pools.go | 58 ++++++++++++------------- examples/worker-pools/worker-pools.hash | 4 +- public/worker-pools | 5 +-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index 443957e..32ce2f7 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -12,40 +12,40 @@ import "time" // results on `results`. We'll sleep a second per job to // simulate an expensive task. func worker(id int, jobs <-chan int, results chan<- int) { - for j := range jobs { - fmt.Println("worker", id, "started job", j) - time.Sleep(time.Second) - fmt.Println("worker", id, "finished job", j) - results <- j * 2 - } + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } } func main() { - // In order to use our pool of workers we need to send - // them work and collect their results. We make 2 - // channels for this. - jobs := make(chan int, 100) - results := make(chan int, 100) + // In order to use our pool of workers we need to send + // them work and collect their results. We make 2 + // channels for this. + jobs := make(chan int, 100) + results := make(chan int, 100) - // This starts up 3 workers, initially blocked - // because there are no jobs yet. - for w := 1; w <= 3; w++ { - go worker(w, jobs, results) - } + // This starts up 3 workers, initially blocked + // because there are no jobs yet. + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } - // Here we send 5 `jobs` and then `close` that - // channel to indicate that's all the work we have. - for j := 1; j <= 5; j++ { - jobs <- j - } - close(jobs) + // Here we send 5 `jobs` and then `close` that + // channel to indicate that's all the work we have. + for j := 1; j <= 5; j++ { + jobs <- j + } + close(jobs) - // Finally we collect all the results of the work. - // This also ensures that the worker goroutines have - // finished. An alternative way to wait for multiple - // goroutines is to use a [WaitGroup](waitgroup). - for a := 1; a <= 5; a++ { - <-results - } + // Finally we collect all the results of the work. + // This also ensures that the worker goroutines have + // finished. An alternative way to wait for multiple + // goroutines is to use a [WaitGroup](waitgroup). + for a := 1; a <= 5; a++ { + <-results + } } diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index ee8c3c7..4a9a3a2 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -bfd2824b3840ff67fa9a0218c7be66647b4bf3d9 -IQestAFcxLh +3f7712d470dcbfc0cdddc939bb80814baaff8bb0 +Q5r-XtrWWL- diff --git a/public/worker-pools b/public/worker-pools index 8ff2427..90f35eb 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -40,7 +40,7 @@ a worker pool using goroutines and channels.

    - +
    package main
     
    @@ -150,8 +150,7 @@ channel to indicate that’s all the work we have.

    Finally we collect all the results of the work. This also ensures that the worker goroutines have finished. An alternative way to wait for multiple -goroutines that’s useful in many scenarios is -to use a WaitGroup.

    +goroutines is to use a WaitGroup.

    From 43ff608b7e990e0eeaa76a7a57b3a46d92fde04c Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:41:16 -0700 Subject: [PATCH 056/133] Remove old location of example in public/ --- public/waiting-for-goroutines-to-finish | 223 ------------------------ 1 file changed, 223 deletions(-) delete mode 100644 public/waiting-for-goroutines-to-finish diff --git a/public/waiting-for-goroutines-to-finish b/public/waiting-for-goroutines-to-finish deleted file mode 100644 index 4f20729..0000000 --- a/public/waiting-for-goroutines-to-finish +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Go by Example: Waiting For Goroutines To Finish - - - - -
    -

    Go by Example: Waiting For Goroutines To Finish

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    To wait for multiple goroutines to finish, we can -use a sync.WaitGroup.

    - -
    - - -
    - - - -
    package main
    -
    - -
    - - - -
    import (
    -    "fmt"
    -    "math/rand"
    -    "sync"
    -    "time"
    -)
    -
    - -
    -

    This is the function we’ll run in every goroutine. -wg is the WaitGroup it uses to notify that it’s done. -Note that a WaitGroup must be passed to functions by -pointer.

    - -
    - -
    func worker(id int, wg *sync.WaitGroup) {
    -    fmt.Printf("Worker %d starting\n", id)
    -
    - -
    -

    Sleep for a random duration between 500-700 ms -to simulate work. See the random numbers -example for more details on rand.

    - -
    - -
        msToSleep := time.Duration(500 + rand.Intn(200))
    -    time.Sleep(msToSleep * time.Millisecond)
    -    fmt.Printf("Worker %d done\n", id)
    -
    - -
    -

    Notify the WaitGroup that we’re done.

    - -
    - -
        wg.Done()
    -}
    -
    - -
    - - - -
    func main() {
    -
    - -
    -

    This WaitGroup is used to wait for all the -goroutines launched here to finish.

    - -
    - -
        var wg sync.WaitGroup
    -
    - -
    -

    Launch several goroutines and increment the WorkGroup -counter for each.

    - -
    - -
        for i := 1; i <= 5; i++ {
    -        wg.Add(1)
    -        go worker(i, &wg)
    -    }
    -
    - -
    -

    Block until the WorkGroup counter goes back to 0; -all the workers notified they’re done.

    - -
    - -
        wg.Wait()
    -}
    -
    - -
    - - - - - - - - - - - - - -
    - - - -
    $ go run waiting-for-goroutines-to-finish.go
    -Worker 5 starting
    -Worker 3 starting
    -Worker 4 starting
    -Worker 1 starting
    -Worker 2 starting
    -Worker 4 done
    -Worker 1 done
    -Worker 2 done
    -Worker 5 done
    -Worker 3 done
    -
    - -
    -

    The order of workers starting up and finishing -is likely to be different for each invocation.

    - -
    - - -
    - - -

    - Next example: Channel Directions. -

    - - -
    - - From 705f713db24fff7065556cb3e2724578dbc70e60 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:53:54 -0700 Subject: [PATCH 057/133] Update examples/channel-synchronization/channel-synchronization.go Co-Authored-By: Mark McGranaghan --- examples/channel-synchronization/channel-synchronization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/channel-synchronization/channel-synchronization.go b/examples/channel-synchronization/channel-synchronization.go index 6b18be1..a9638ee 100644 --- a/examples/channel-synchronization/channel-synchronization.go +++ b/examples/channel-synchronization/channel-synchronization.go @@ -2,7 +2,7 @@ // across goroutines. Here's an example of using a // blocking receive to wait for a goroutine to finish. // When waiting for multiple goroutines to finish, -// you may prefer to [use a WaitGroup](waiting-for-goroutines-to-finish). +// you may prefer to use a [WaitGroup](waiting-for-goroutines-to-finish). package main From 2967315795d140752523d53cc2ab3623149e8aa2 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:54:10 -0700 Subject: [PATCH 058/133] Update examples/waitgroup/waitgroup.go Co-Authored-By: Mark McGranaghan --- examples/waitgroup/waitgroup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/waitgroup/waitgroup.go b/examples/waitgroup/waitgroup.go index 65c4212..a21a499 100644 --- a/examples/waitgroup/waitgroup.go +++ b/examples/waitgroup/waitgroup.go @@ -29,7 +29,7 @@ func main() { // goroutines launched here to finish. var wg sync.WaitGroup - // Launch several goroutines and increment the WorkGroup + // Launch several goroutines and increment the WaitGroup // counter for each. for i := 1; i <= 5; i++ { wg.Add(1) From c7dd69349b4bb0966c7744c15419be3c703a940c Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 05:54:32 -0700 Subject: [PATCH 059/133] Update examples/waitgroup/waitgroup.go Co-Authored-By: Mark McGranaghan --- examples/waitgroup/waitgroup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/waitgroup/waitgroup.go b/examples/waitgroup/waitgroup.go index a21a499..a1ad603 100644 --- a/examples/waitgroup/waitgroup.go +++ b/examples/waitgroup/waitgroup.go @@ -19,7 +19,7 @@ func worker(id int, wg *sync.WaitGroup) { time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) - // Notify the WaitGroup that we're done. + // Notify the WaitGroup that this worker is done. wg.Done() } From 8930aa53f3a316055e9dda4c534528ae0795e753 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 06:05:58 -0700 Subject: [PATCH 060/133] Adding a basic sanity testing tool to run during 'build'. The tool just runs 'go vet' for now; could do more later (like actually run the examples and compare to some expected output) --- tools/build | 1 + tools/test | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100755 tools/test diff --git a/tools/build b/tools/build index 829edcb..3c07db8 100755 --- a/tools/build +++ b/tools/build @@ -2,6 +2,7 @@ set -e +tools/test tools/format tools/measure tools/generate diff --git a/tools/test b/tools/test new file mode 100755 index 0000000..c0c9c55 --- /dev/null +++ b/tools/test @@ -0,0 +1,10 @@ +#!/bin/bash + +# Sanity testing of the examples. + +set -eo pipefail + +# go vet will attempt to build each example, making sure it compiles. It will +# also report known issues with the code. Disabling the -unreachable check +# because it will fire false positives for some examples demonstrating panics. +go vet -unreachable=false ./examples/... From 074571d9523fc3b4316183c1f51c540d0019b3de Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 06:07:12 -0700 Subject: [PATCH 061/133] Update examples/waitgroup/waitgroup.go Co-Authored-By: Mark McGranaghan --- examples/waitgroup/waitgroup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/waitgroup/waitgroup.go b/examples/waitgroup/waitgroup.go index a1ad603..dc8d0c1 100644 --- a/examples/waitgroup/waitgroup.go +++ b/examples/waitgroup/waitgroup.go @@ -36,7 +36,7 @@ func main() { go worker(i, &wg) } - // Block until the WorkGroup counter goes back to 0; + // Block until the WaitGroup counter goes back to 0; // all the workers notified they're done. wg.Wait() } From ec0b192e485c8ccefa34c977a95a81553116a864 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 30 May 2019 06:12:09 -0700 Subject: [PATCH 062/133] Rename waitgroup-->waitgroups --- examples.txt | 2 +- .../channel-synchronization.go | 2 +- .../channel-synchronization.hash | 4 ++-- examples/waitgroup/waitgroup.hash | 2 -- .../waitgroup.go => waitgroups/waitgroups.go} | 0 examples/waitgroups/waitgroups.hash | 2 ++ .../waitgroup.sh => waitgroups/waitgroups.sh} | 2 +- examples/worker-pools/worker-pools.go | 2 +- examples/worker-pools/worker-pools.hash | 4 ++-- public/channel-synchronization | 4 ++-- public/index.html | 2 +- public/{waitgroup => waitgroups} | 18 +++++++++--------- public/worker-pools | 6 +++--- 13 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 examples/waitgroup/waitgroup.hash rename examples/{waitgroup/waitgroup.go => waitgroups/waitgroups.go} (100%) create mode 100644 examples/waitgroups/waitgroups.hash rename examples/{waitgroup/waitgroup.sh => waitgroups/waitgroups.sh} (91%) rename public/{waitgroup => waitgroups} (92%) diff --git a/examples.txt b/examples.txt index 6153867..ddace2d 100644 --- a/examples.txt +++ b/examples.txt @@ -32,7 +32,7 @@ Range over Channels Timers Tickers Worker Pools -WaitGroup +WaitGroups Rate Limiting Atomic Counters Mutexes diff --git a/examples/channel-synchronization/channel-synchronization.go b/examples/channel-synchronization/channel-synchronization.go index a9638ee..66873a8 100644 --- a/examples/channel-synchronization/channel-synchronization.go +++ b/examples/channel-synchronization/channel-synchronization.go @@ -2,7 +2,7 @@ // across goroutines. Here's an example of using a // blocking receive to wait for a goroutine to finish. // When waiting for multiple goroutines to finish, -// you may prefer to use a [WaitGroup](waiting-for-goroutines-to-finish). +// you may prefer to use a [WaitGroup](waitgroups). package main diff --git a/examples/channel-synchronization/channel-synchronization.hash b/examples/channel-synchronization/channel-synchronization.hash index 8fba20d..e906123 100644 --- a/examples/channel-synchronization/channel-synchronization.hash +++ b/examples/channel-synchronization/channel-synchronization.hash @@ -1,2 +1,2 @@ -df90432a53832c045472981a9da23d1139fb2b5c -f6qTtt1agmN +eb022977181884c2ab0f2b69e50311769e67a509 +8lmP8beav0p diff --git a/examples/waitgroup/waitgroup.hash b/examples/waitgroup/waitgroup.hash deleted file mode 100644 index 1df8a2f..0000000 --- a/examples/waitgroup/waitgroup.hash +++ /dev/null @@ -1,2 +0,0 @@ -ffc6520e73ebfa2b8c470e3ef00fee55388234e0 -8cD2V9CgI0J diff --git a/examples/waitgroup/waitgroup.go b/examples/waitgroups/waitgroups.go similarity index 100% rename from examples/waitgroup/waitgroup.go rename to examples/waitgroups/waitgroups.go diff --git a/examples/waitgroups/waitgroups.hash b/examples/waitgroups/waitgroups.hash new file mode 100644 index 0000000..71ecfc8 --- /dev/null +++ b/examples/waitgroups/waitgroups.hash @@ -0,0 +1,2 @@ +499c7ee59b2ae06d2d3171768d9cf11762121a87 +gLLmgcR7YkP diff --git a/examples/waitgroup/waitgroup.sh b/examples/waitgroups/waitgroups.sh similarity index 91% rename from examples/waitgroup/waitgroup.sh rename to examples/waitgroups/waitgroups.sh index 13293bc..c2a6c11 100644 --- a/examples/waitgroup/waitgroup.sh +++ b/examples/waitgroups/waitgroups.sh @@ -1,4 +1,4 @@ -$ go run waitgroup.go +$ go run waitgroups.go Worker 5 starting Worker 3 starting Worker 4 starting diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index 32ce2f7..eabda7a 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -44,7 +44,7 @@ func main() { // Finally we collect all the results of the work. // This also ensures that the worker goroutines have // finished. An alternative way to wait for multiple - // goroutines is to use a [WaitGroup](waitgroup). + // goroutines is to use a [WaitGroup](waitgroups). for a := 1; a <= 5; a++ { <-results } diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index 4a9a3a2..9f101b7 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -3f7712d470dcbfc0cdddc939bb80814baaff8bb0 -Q5r-XtrWWL- +bc69c6602d438413dcb9ceac112299ee253e4575 +yuHsGf712D1 diff --git a/public/channel-synchronization b/public/channel-synchronization index e79fe04..307251a 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -29,7 +29,7 @@ across goroutines. Here’s an example of using a blocking receive to wait for a goroutine to finish. When waiting for multiple goroutines to finish, -you may prefer to use a WaitGroup.

    +you may prefer to use a WaitGroup.

    @@ -43,7 +43,7 @@ you may prefer to use a WaitGroup - +
    package main
     
    diff --git a/public/index.html b/public/index.html index d4dd0a2..347a8a3 100644 --- a/public/index.html +++ b/public/index.html @@ -103,7 +103,7 @@
  • Worker Pools
  • -
  • WaitGroup
  • +
  • WaitGroups
  • Rate Limiting
  • diff --git a/public/waitgroup b/public/waitgroups similarity index 92% rename from public/waitgroup rename to public/waitgroups index bdd3b66..7648b36 100644 --- a/public/waitgroup +++ b/public/waitgroups @@ -2,7 +2,7 @@ - Go by Example: WaitGroup + Go by Example: WaitGroups -
    -

    Go by Example: WaitGroup

    +
    +

    Go by Example: WaitGroups

    @@ -40,7 +40,7 @@ use a wait group.

    @@ -152,7 +152,7 @@ counter for each.

    @@ -175,7 +175,7 @@ all the workers notified they’re done.

    From 95e26aa537cca22124b0e5143e6de8bbcea7eeaa Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 07:42:36 -0700 Subject: [PATCH 067/133] Shorter name --- tools/{upload-site => upload} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tools/{upload-site => upload} (100%) diff --git a/tools/upload-site b/tools/upload similarity index 100% rename from tools/upload-site rename to tools/upload From 8631e99ffd2d52a8d0b361d8605a815189872159 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 12:50:28 -0700 Subject: [PATCH 068/133] Update Readme to reflect tools/upload --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c73e20..f9454ea 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ To upload the site: $ gem install aws-sdk $ export AWS_ACCESS_KEY_ID=... $ export AWS_SECRET_ACCESS_KEY=... -$ tools/upload-site +$ tools/upload ``` ### License From 9f19f86417a23af72a774e01042ab80a88ffbf18 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 12:52:51 -0700 Subject: [PATCH 069/133] Remove vestigal dot files --- .env | 2 -- .godir | 1 - 2 files changed, 3 deletions(-) delete mode 100644 .env delete mode 100644 .godir diff --git a/.env b/.env deleted file mode 100644 index c436e88..0000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -CANONICAL_HOST=127.0.0.1 -FORCE_HTTPS=0 diff --git a/.godir b/.godir deleted file mode 100644 index 067f71b..0000000 --- a/.godir +++ /dev/null @@ -1 +0,0 @@ -gobyexample From 21bba9d169c0bf291b39107e31850456a6466168 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 12:54:23 -0700 Subject: [PATCH 070/133] Whew that was a while ago --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index ccf876e..0d20b64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -.anvil *.pyc From 75abd7facb7ff09c6f2daac3eb18508456f56819 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 12:57:13 -0700 Subject: [PATCH 071/133] Update contributing guide --- CONTRIBUTING.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d70228..2366de8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,16 @@ ## Contributing -Go by Example is now in a steady state. We are maintaining it, but are not -expanding or significantly changing it any more. - -With that in mind here are some specific contribution guidelines: +Thanks for your interest in contributing to Go by Example! * If you see a typo or would like to suggest another small change, editing the .go or .sh source file should be sufficient for the PR. I can rebuild the HTML when I review the change. -* We are not going to add any more sections to the site. There are many - important topics that Go by Example doesn't cover, which we leave to other - resources. +* We're open to adding more examples to the site. They should be on things + used by many programmers and only require the standard library. If you're + interested in adding an example, _please open an issue to discuss the topic + first_. -* We are not going to change the navigation of the site, in particular adding +* We're not going to change the navigation of the site, in particular adding a "previous section" link or an "index" link other than the on the title text. From d351883ab875fd5327ea4c8ea5f13ae18e293e69 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:06:44 -0700 Subject: [PATCH 072/133] Fix whitespace and build --- examples/maps/maps.sh | 2 -- public/maps | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/maps/maps.sh b/examples/maps/maps.sh index 03e1a25..da7a841 100644 --- a/examples/maps/maps.sh +++ b/examples/maps/maps.sh @@ -7,5 +7,3 @@ len: 2 map: map[k1:7] prs: false map: map[bar:2 foo:1] - - diff --git a/public/maps b/public/maps index 4a724b1..afa0567 100644 --- a/public/maps +++ b/public/maps @@ -199,7 +199,7 @@ printed with fmt.Println.

    len: 2 map: map[k1:7] prs: false -map: map[foo:1 bar:2] +map: map[bar:2 foo:1] From dfcaebd536ade922c62b780cc23a35155ee7a572 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 31 May 2019 06:06:13 -0700 Subject: [PATCH 073/133] Basic HTTP client sample --- examples.txt | 1 + examples/http-clients/http-clients.go | 37 ++++++ examples/http-clients/http-clients.hash | 2 + examples/http-clients/http-clients.sh | 7 ++ public/environment-variables | 2 +- public/http-clients | 157 ++++++++++++++++++++++++ public/index.html | 2 + 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 examples/http-clients/http-clients.go create mode 100644 examples/http-clients/http-clients.hash create mode 100644 examples/http-clients/http-clients.sh create mode 100644 public/http-clients diff --git a/examples.txt b/examples.txt index ddace2d..9e13b51 100644 --- a/examples.txt +++ b/examples.txt @@ -60,6 +60,7 @@ Line Filters Command-Line Arguments Command-Line Flags Environment Variables +HTTP Clients Spawning Processes Exec'ing Processes Signals diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go new file mode 100644 index 0000000..170f880 --- /dev/null +++ b/examples/http-clients/http-clients.go @@ -0,0 +1,37 @@ +// The Go standard library comes with excellent support +// for HTTP clients and servers out of the box with the +// `net/http` package. In this example we'll use it to +// issue simple HTTP requests. +package main + +import ( + "bufio" + "fmt" + "net/http" +) + +func main() { + // Issue a HTTP GET request to a server. http.Get is a + // convenient shortcut around creating a http.Client + // object and calling its Get() method; it uses the + // http.DefaultClient object which has useful default + // settings. + resp, err := http.Get("http://gobyexample.com") + if err != nil { + panic(err) + } + defer resp.Body.Close() + + // Print the HTTP response status. + fmt.Println("Response status:", resp.Status) + + // Print the first 5 lines of the response body. + scanner := bufio.NewScanner(resp.Body) + for i := 0; scanner.Scan() && i < 5; i++ { + fmt.Println(scanner.Text()) + } + + if err := scanner.Err(); err != nil { + panic(err) + } +} diff --git a/examples/http-clients/http-clients.hash b/examples/http-clients/http-clients.hash new file mode 100644 index 0000000..7addbe9 --- /dev/null +++ b/examples/http-clients/http-clients.hash @@ -0,0 +1,2 @@ +afac2191f24a0861384d142ab58cc262fc47cfbf +Y92yCu1CIrI diff --git a/examples/http-clients/http-clients.sh b/examples/http-clients/http-clients.sh new file mode 100644 index 0000000..afbbb77 --- /dev/null +++ b/examples/http-clients/http-clients.sh @@ -0,0 +1,7 @@ +$ go run http-clients.go +Response status: 200 OK + + + + + Go by Example diff --git a/public/environment-variables b/public/environment-variables index 7e652d1..4d8d276 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -161,7 +161,7 @@ program picks that value up.

    - Next example: Spawning Processes. + Next example: HTTP Clients.

    +

    Go by Example: HTTP Clients

    + +
    - +
    package main
     
    @@ -95,7 +95,7 @@ pointer.

    -

    Notify the WaitGroup that we’re done.

    +

    Notify the WaitGroup that this worker is done.

    @@ -135,7 +135,7 @@ goroutines launched here to finish.

    -

    Launch several goroutines and increment the WorkGroup +

    Launch several goroutines and increment the WaitGroup counter for each.

    -

    Block until the WorkGroup counter goes back to 0; +

    Block until the WaitGroup counter goes back to 0; all the workers notified they’re done.

    -
    $ go run waitgroup.go
    +            
    $ go run waitgroups.go
     Worker 5 starting
     Worker 3 starting
     Worker 4 starting
    @@ -211,7 +211,7 @@ is likely to be different for each invocation.

    diff --git a/public/worker-pools b/public/worker-pools index 90f35eb..5762746 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -40,7 +40,7 @@ a worker pool using goroutines and channels.

    - +
    package main
     
    @@ -150,7 +150,7 @@ channel to indicate that’s all the work we have.

    Finally we collect all the results of the work. This also ensures that the worker goroutines have finished. An alternative way to wait for multiple -goroutines is to use a WaitGroup.

    +goroutines is to use a WaitGroup.

    @@ -210,7 +210,7 @@ there are 3 workers operating concurrently.

    - Next example: WaitGroup. + Next example: WaitGroups.

    - +
    package main
     
    @@ -134,12 +134,12 @@ zero value for an int is 0.

    The := syntax is shorthand for declaring and initializing a variable, e.g. for -var f string = "short" in this case.

    +var f string = "apple" in this case.

    -
        f := "short"
    +            
        f := "apple"
         fmt.Println(f)
     }
     
    From e6f596b462da9b11cf5ba8105c7f5f47b5289f17 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 06:49:07 -0700 Subject: [PATCH 064/133] Remove Google Analytics I thought I had done this a long time ago |: --- templates/404.html | 12 ------------ templates/example.tmpl | 12 ------------ templates/index.tmpl | 12 ------------ 3 files changed, 36 deletions(-) diff --git a/templates/404.html b/templates/404.html index eb35bcd..e2a089e 100644 --- a/templates/404.html +++ b/templates/404.html @@ -5,18 +5,6 @@ Go by Example: Not Found -

    Go by Example

    diff --git a/templates/example.tmpl b/templates/example.tmpl index 3952463..8eb58b5 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -5,18 +5,6 @@ Go by Example: {{.Name}} -

    Go by Example: {{.Name}}

    diff --git a/templates/index.tmpl b/templates/index.tmpl index 929d3c1..bb7cb5b 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -5,18 +5,6 @@ Go by Example -

    Go by Example

    From 616ddedf593b4345cb346eda225de105f2c7c291 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 06:55:38 -0700 Subject: [PATCH 065/133] Build for GA removal --- public/404.html | 12 ------------ public/arrays | 12 ------------ public/atomic-counters | 12 ------------ public/base64-encoding | 12 ------------ public/channel-buffering | 12 ------------ public/channel-directions | 12 ------------ public/channel-synchronization | 12 ------------ public/channels | 12 ------------ public/closing-channels | 12 ------------ public/closures | 12 ------------ public/collection-functions | 12 ------------ public/command-line-arguments | 12 ------------ public/command-line-flags | 12 ------------ public/constants | 12 ------------ public/defer | 12 ------------ public/environment-variables | 12 ------------ public/epoch | 12 ------------ public/errors | 12 ------------ public/execing-processes | 12 ------------ public/exit | 12 ------------ public/for | 12 ------------ public/functions | 12 ------------ public/goroutines | 12 ------------ public/hello-world | 12 ------------ public/if-else | 12 ------------ public/index.html | 12 ------------ public/interfaces | 12 ------------ public/json | 12 ------------ public/line-filters | 12 ------------ public/maps | 12 ------------ public/methods | 12 ------------ public/multiple-return-values | 12 ------------ public/mutexes | 12 ------------ public/non-blocking-channel-operations | 12 ------------ public/number-parsing | 12 ------------ public/panic | 12 ------------ public/pointers | 12 ------------ public/random-numbers | 12 ------------ public/range | 12 ------------ public/range-over-channels | 12 ------------ public/rate-limiting | 12 ------------ public/reading-files | 12 ------------ public/recursion | 12 ------------ public/regular-expressions | 12 ------------ public/select | 12 ------------ public/sha1-hashes | 12 ------------ public/signals | 12 ------------ public/slices | 12 ------------ public/sorting | 12 ------------ public/sorting-by-functions | 12 ------------ public/spawning-processes | 12 ------------ public/stateful-goroutines | 12 ------------ public/string-formatting | 12 ------------ public/string-functions | 12 ------------ public/structs | 12 ------------ public/switch | 12 ------------ public/tickers | 12 ------------ public/time | 12 ------------ public/time-formatting-parsing | 12 ------------ public/timeouts | 12 ------------ public/timers | 12 ------------ public/url-parsing | 12 ------------ public/values | 12 ------------ public/variables | 12 ------------ public/variadic-functions | 12 ------------ public/waitgroups | 12 ------------ public/worker-pools | 12 ------------ public/writing-files | 12 ------------ 68 files changed, 816 deletions(-) diff --git a/public/404.html b/public/404.html index eb35bcd..e2a089e 100644 --- a/public/404.html +++ b/public/404.html @@ -5,18 +5,6 @@ Go by Example: Not Found -

    Go by Example

    diff --git a/public/arrays b/public/arrays index 606ea6e..9e66c1c 100644 --- a/public/arrays +++ b/public/arrays @@ -5,18 +5,6 @@ Go by Example: Arrays -

    Go by Example: Arrays

    diff --git a/public/atomic-counters b/public/atomic-counters index 0eb8aea..2c6bd65 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -5,18 +5,6 @@ Go by Example: Atomic Counters -

    Go by Example: Atomic Counters

    diff --git a/public/base64-encoding b/public/base64-encoding index fa3528a..10b0b46 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -5,18 +5,6 @@ Go by Example: Base64 Encoding -

    Go by Example: Base64 Encoding

    diff --git a/public/channel-buffering b/public/channel-buffering index 796efe8..defe3eb 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -5,18 +5,6 @@ Go by Example: Channel Buffering -

    Go by Example: Channel Buffering

    diff --git a/public/channel-directions b/public/channel-directions index 84e130e..16483a7 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -5,18 +5,6 @@ Go by Example: Channel Directions -

    Go by Example: Channel Directions

    diff --git a/public/channel-synchronization b/public/channel-synchronization index 307251a..61f2763 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -5,18 +5,6 @@ Go by Example: Channel Synchronization -

    Go by Example: Channel Synchronization

    diff --git a/public/channels b/public/channels index 5d5d7e9..b181c4f 100644 --- a/public/channels +++ b/public/channels @@ -5,18 +5,6 @@ Go by Example: Channels -

    Go by Example: Channels

    diff --git a/public/closing-channels b/public/closing-channels index 8730c42..73c5a79 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -5,18 +5,6 @@ Go by Example: Closing Channels -

    Go by Example: Closing Channels

    diff --git a/public/closures b/public/closures index 3afcb89..6a3ebc4 100644 --- a/public/closures +++ b/public/closures @@ -5,18 +5,6 @@ Go by Example: Closures -

    Go by Example: Closures

    diff --git a/public/collection-functions b/public/collection-functions index 9b533d9..564c960 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -5,18 +5,6 @@ Go by Example: Collection Functions -

    Go by Example: Collection Functions

    diff --git a/public/command-line-arguments b/public/command-line-arguments index fa26f6c..c6193c3 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -5,18 +5,6 @@ Go by Example: Command-Line Arguments -

    Go by Example: Command-Line Arguments

    diff --git a/public/command-line-flags b/public/command-line-flags index 6c49752..88bd23c 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -5,18 +5,6 @@ Go by Example: Command-Line Flags -

    Go by Example: Command-Line Flags

    diff --git a/public/constants b/public/constants index 76a6a89..80a89c5 100644 --- a/public/constants +++ b/public/constants @@ -5,18 +5,6 @@ Go by Example: Constants -

    Go by Example: Constants

    diff --git a/public/defer b/public/defer index 57d15fb..a161789 100644 --- a/public/defer +++ b/public/defer @@ -5,18 +5,6 @@ Go by Example: Defer -

    Go by Example: Defer

    diff --git a/public/environment-variables b/public/environment-variables index e2d7849..10ab446 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -5,18 +5,6 @@ Go by Example: Environment Variables -

    Go by Example: Environment Variables

    diff --git a/public/epoch b/public/epoch index fe25dec..22014fe 100644 --- a/public/epoch +++ b/public/epoch @@ -5,18 +5,6 @@ Go by Example: Epoch -

    Go by Example: Epoch

    diff --git a/public/errors b/public/errors index 72ca49d..ee2e50c 100644 --- a/public/errors +++ b/public/errors @@ -5,18 +5,6 @@ Go by Example: Errors -

    Go by Example: Errors

    diff --git a/public/execing-processes b/public/execing-processes index 531e8f5..61871e5 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -5,18 +5,6 @@ Go by Example: Exec'ing Processes -

    Go by Example: Exec'ing Processes

    diff --git a/public/exit b/public/exit index 721fbaa..1b38aee 100644 --- a/public/exit +++ b/public/exit @@ -5,18 +5,6 @@ Go by Example: Exit -

    Go by Example: Exit

    diff --git a/public/for b/public/for index f7c841e..c854062 100644 --- a/public/for +++ b/public/for @@ -5,18 +5,6 @@ Go by Example: For -

    Go by Example: For

    diff --git a/public/functions b/public/functions index debd8cb..937f5b4 100644 --- a/public/functions +++ b/public/functions @@ -5,18 +5,6 @@ Go by Example: Functions -

    Go by Example: Functions

    diff --git a/public/goroutines b/public/goroutines index f46db9e..f1f8d18 100644 --- a/public/goroutines +++ b/public/goroutines @@ -5,18 +5,6 @@ Go by Example: Goroutines -

    Go by Example: Goroutines

    diff --git a/public/hello-world b/public/hello-world index e6a37bd..e77ae10 100644 --- a/public/hello-world +++ b/public/hello-world @@ -5,18 +5,6 @@ Go by Example: Hello World -

    Go by Example: Hello World

    diff --git a/public/if-else b/public/if-else index 499fb4c..b3415eb 100644 --- a/public/if-else +++ b/public/if-else @@ -5,18 +5,6 @@ Go by Example: If/Else -

    Go by Example: If/Else

    diff --git a/public/index.html b/public/index.html index 347a8a3..92ef12f 100644 --- a/public/index.html +++ b/public/index.html @@ -5,18 +5,6 @@ Go by Example -

    Go by Example

    diff --git a/public/interfaces b/public/interfaces index ff701bd..cf62c06 100644 --- a/public/interfaces +++ b/public/interfaces @@ -5,18 +5,6 @@ Go by Example: Interfaces -

    Go by Example: Interfaces

    diff --git a/public/json b/public/json index c23254e..4d1d210 100644 --- a/public/json +++ b/public/json @@ -5,18 +5,6 @@ Go by Example: JSON -

    Go by Example: JSON

    diff --git a/public/line-filters b/public/line-filters index 2e9a547..57c6c02 100644 --- a/public/line-filters +++ b/public/line-filters @@ -5,18 +5,6 @@ Go by Example: Line Filters -

    Go by Example: Line Filters

    diff --git a/public/maps b/public/maps index 0cbf53c..255af49 100644 --- a/public/maps +++ b/public/maps @@ -5,18 +5,6 @@ Go by Example: Maps -

    Go by Example: Maps

    diff --git a/public/methods b/public/methods index 856f473..c9f41c7 100644 --- a/public/methods +++ b/public/methods @@ -5,18 +5,6 @@ Go by Example: Methods -

    Go by Example: Methods

    diff --git a/public/multiple-return-values b/public/multiple-return-values index ca34e40..788bfa0 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -5,18 +5,6 @@ Go by Example: Multiple Return Values -

    Go by Example: Multiple Return Values

    diff --git a/public/mutexes b/public/mutexes index 9c19368..14c744f 100644 --- a/public/mutexes +++ b/public/mutexes @@ -5,18 +5,6 @@ Go by Example: Mutexes -

    Go by Example: Mutexes

    diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index d7e2c1a..0c9a02e 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -5,18 +5,6 @@ Go by Example: Non-Blocking Channel Operations -

    Go by Example: Non-Blocking Channel Operations

    diff --git a/public/number-parsing b/public/number-parsing index 288d9b7..3636f60 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -5,18 +5,6 @@ Go by Example: Number Parsing -

    Go by Example: Number Parsing

    diff --git a/public/panic b/public/panic index 27a416a..be7c598 100644 --- a/public/panic +++ b/public/panic @@ -5,18 +5,6 @@ Go by Example: Panic -

    Go by Example: Panic

    diff --git a/public/pointers b/public/pointers index 62738ba..cef55a7 100644 --- a/public/pointers +++ b/public/pointers @@ -5,18 +5,6 @@ Go by Example: Pointers -

    Go by Example: Pointers

    diff --git a/public/random-numbers b/public/random-numbers index 49f46c1..fadc00c 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -5,18 +5,6 @@ Go by Example: Random Numbers -

    Go by Example: Random Numbers

    diff --git a/public/range b/public/range index 09ab1ec..37bb665 100644 --- a/public/range +++ b/public/range @@ -5,18 +5,6 @@ Go by Example: Range -

    Go by Example: Range

    diff --git a/public/range-over-channels b/public/range-over-channels index e189190..0b54622 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -5,18 +5,6 @@ Go by Example: Range over Channels -

    Go by Example: Range over Channels

    diff --git a/public/rate-limiting b/public/rate-limiting index d635e11..7518033 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -5,18 +5,6 @@ Go by Example: Rate Limiting -

    Go by Example: Rate Limiting

    diff --git a/public/reading-files b/public/reading-files index 39e51de..b002ac9 100644 --- a/public/reading-files +++ b/public/reading-files @@ -5,18 +5,6 @@ Go by Example: Reading Files -

    Go by Example: Reading Files

    diff --git a/public/recursion b/public/recursion index 844b85f..f2048f1 100644 --- a/public/recursion +++ b/public/recursion @@ -5,18 +5,6 @@ Go by Example: Recursion -

    Go by Example: Recursion

    diff --git a/public/regular-expressions b/public/regular-expressions index f000e06..cd93713 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -5,18 +5,6 @@ Go by Example: Regular Expressions -

    Go by Example: Regular Expressions

    diff --git a/public/select b/public/select index f8ba88f..04ca348 100644 --- a/public/select +++ b/public/select @@ -5,18 +5,6 @@ Go by Example: Select -

    Go by Example: Select

    diff --git a/public/sha1-hashes b/public/sha1-hashes index 66c6d77..5b9aeed 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -5,18 +5,6 @@ Go by Example: SHA1 Hashes -

    Go by Example: SHA1 Hashes

    diff --git a/public/signals b/public/signals index 3288d91..56cc886 100644 --- a/public/signals +++ b/public/signals @@ -5,18 +5,6 @@ Go by Example: Signals -

    Go by Example: Signals

    diff --git a/public/slices b/public/slices index ba38bc0..5284efc 100644 --- a/public/slices +++ b/public/slices @@ -5,18 +5,6 @@ Go by Example: Slices -

    Go by Example: Slices

    diff --git a/public/sorting b/public/sorting index 328e32c..95e13d8 100644 --- a/public/sorting +++ b/public/sorting @@ -5,18 +5,6 @@ Go by Example: Sorting -

    Go by Example: Sorting

    diff --git a/public/sorting-by-functions b/public/sorting-by-functions index cb0f615..711c5c1 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -5,18 +5,6 @@ Go by Example: Sorting by Functions -

    Go by Example: Sorting by Functions

    diff --git a/public/spawning-processes b/public/spawning-processes index db1f72b..88c0c28 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -5,18 +5,6 @@ Go by Example: Spawning Processes -

    Go by Example: Spawning Processes

    diff --git a/public/stateful-goroutines b/public/stateful-goroutines index 69d83a8..ea7d4a1 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -5,18 +5,6 @@ Go by Example: Stateful Goroutines -

    Go by Example: Stateful Goroutines

    diff --git a/public/string-formatting b/public/string-formatting index b884639..9126fcf 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -5,18 +5,6 @@ Go by Example: String Formatting -

    Go by Example: String Formatting

    diff --git a/public/string-functions b/public/string-functions index 9594a23..440fe49 100644 --- a/public/string-functions +++ b/public/string-functions @@ -5,18 +5,6 @@ Go by Example: String Functions -

    Go by Example: String Functions

    diff --git a/public/structs b/public/structs index c9f3181..f3be51a 100644 --- a/public/structs +++ b/public/structs @@ -5,18 +5,6 @@ Go by Example: Structs -

    Go by Example: Structs

    diff --git a/public/switch b/public/switch index 32127df..c13f0fd 100644 --- a/public/switch +++ b/public/switch @@ -5,18 +5,6 @@ Go by Example: Switch -

    Go by Example: Switch

    diff --git a/public/tickers b/public/tickers index cf16820..0c38797 100644 --- a/public/tickers +++ b/public/tickers @@ -5,18 +5,6 @@ Go by Example: Tickers -

    Go by Example: Tickers

    diff --git a/public/time b/public/time index 017a30f..272d320 100644 --- a/public/time +++ b/public/time @@ -5,18 +5,6 @@ Go by Example: Time -

    Go by Example: Time

    diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index 7a154fb..16f4105 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -5,18 +5,6 @@ Go by Example: Time Formatting / Parsing -

    Go by Example: Time Formatting / Parsing

    diff --git a/public/timeouts b/public/timeouts index f19ecae..6033b7a 100644 --- a/public/timeouts +++ b/public/timeouts @@ -5,18 +5,6 @@ Go by Example: Timeouts -

    Go by Example: Timeouts

    diff --git a/public/timers b/public/timers index 4c2e27a..220d7f4 100644 --- a/public/timers +++ b/public/timers @@ -5,18 +5,6 @@ Go by Example: Timers -

    Go by Example: Timers

    diff --git a/public/url-parsing b/public/url-parsing index 4fba27c..d3e0e77 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -5,18 +5,6 @@ Go by Example: URL Parsing -

    Go by Example: URL Parsing

    diff --git a/public/values b/public/values index 5a815cd..1a052d0 100644 --- a/public/values +++ b/public/values @@ -5,18 +5,6 @@ Go by Example: Values -

    Go by Example: Values

    diff --git a/public/variables b/public/variables index ebe52cc..95db760 100644 --- a/public/variables +++ b/public/variables @@ -5,18 +5,6 @@ Go by Example: Variables -

    Go by Example: Variables

    diff --git a/public/variadic-functions b/public/variadic-functions index 5991544..e660ef3 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -5,18 +5,6 @@ Go by Example: Variadic Functions -

    Go by Example: Variadic Functions

    diff --git a/public/waitgroups b/public/waitgroups index 7648b36..1fe8966 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -5,18 +5,6 @@ Go by Example: WaitGroups -

    Go by Example: WaitGroups

    diff --git a/public/worker-pools b/public/worker-pools index 5762746..ac6909a 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -5,18 +5,6 @@ Go by Example: Worker Pools -

    Go by Example: Worker Pools

    diff --git a/public/writing-files b/public/writing-files index 21cdd86..66d254e 100644 --- a/public/writing-files +++ b/public/writing-files @@ -5,18 +5,6 @@ Go by Example: Writing Files -

    Go by Example: Writing Files

    From cf4b6762926ec7b818875a8fbac26a405c2d79ab Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 30 May 2019 07:42:20 -0700 Subject: [PATCH 066/133] Use data uri to avoid requesting tiny image --- public/arrays | 2 +- public/atomic-counters | 2 +- public/base64-encoding | 2 +- public/channel-buffering | 2 +- public/channel-directions | 2 +- public/channel-synchronization | 2 +- public/channels | 2 +- public/closing-channels | 2 +- public/closures | 2 +- public/collection-functions | 2 +- public/command-line-arguments | 2 +- public/command-line-flags | 2 +- public/constants | 2 +- public/defer | 2 +- public/environment-variables | 2 +- public/epoch | 2 +- public/errors | 2 +- public/execing-processes | 2 +- public/exit | 2 +- public/for | 2 +- public/functions | 2 +- public/goroutines | 2 +- public/hello-world | 2 +- public/if-else | 2 +- public/interfaces | 2 +- public/json | 2 +- public/line-filters | 2 +- public/maps | 2 +- public/methods | 2 +- public/multiple-return-values | 2 +- public/mutexes | 2 +- public/non-blocking-channel-operations | 2 +- public/number-parsing | 2 +- public/panic | 2 +- public/pointers | 2 +- public/random-numbers | 2 +- public/range | 2 +- public/range-over-channels | 2 +- public/rate-limiting | 2 +- public/reading-files | 2 +- public/recursion | 2 +- public/regular-expressions | 2 +- public/select | 2 +- public/sha1-hashes | 2 +- public/signals | 2 +- public/slices | 2 +- public/sorting | 2 +- public/sorting-by-functions | 2 +- public/spawning-processes | 2 +- public/stateful-goroutines | 2 +- public/string-formatting | 2 +- public/string-functions | 2 +- public/structs | 2 +- public/switch | 2 +- public/tickers | 2 +- public/time | 2 +- public/time-formatting-parsing | 2 +- public/timeouts | 2 +- public/timers | 2 +- public/url-parsing | 2 +- public/values | 2 +- public/variables | 2 +- public/variadic-functions | 2 +- public/waitgroups | 2 +- public/worker-pools | 2 +- public/writing-files | 2 +- templates/example.tmpl | 2 +- 67 files changed, 67 insertions(+), 67 deletions(-) diff --git a/public/arrays b/public/arrays index 9e66c1c..c32e5b9 100644 --- a/public/arrays +++ b/public/arrays @@ -28,7 +28,7 @@ specific length.

    - +
    package main
     
    diff --git a/public/atomic-counters b/public/atomic-counters index 2c6bd65..a9ec770 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -32,7 +32,7 @@ counters accessed by multiple goroutines.

    - +
    package main
     
    diff --git a/public/base64-encoding b/public/base64-encoding index 10b0b46..5a82f4c 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -28,7 +28,7 @@ encoding/decoding.

    - +
    package main
     
    diff --git a/public/channel-buffering b/public/channel-buffering index defe3eb..5cf8cb1 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -32,7 +32,7 @@ those values.

    - +
    package main
     
    diff --git a/public/channel-directions b/public/channel-directions index 16483a7..d989de8 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -30,7 +30,7 @@ the program.

    - +
    package main
     
    diff --git a/public/channel-synchronization b/public/channel-synchronization index 61f2763..f860261 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -31,7 +31,7 @@ you may prefer to use a WaitGroup.

    - +
    package main
     
    diff --git a/public/channels b/public/channels index b181c4f..a41776a 100644 --- a/public/channels +++ b/public/channels @@ -30,7 +30,7 @@ goroutine.

    - +
    package main
     
    diff --git a/public/closing-channels b/public/closing-channels index 73c5a79..3ad1396 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -29,7 +29,7 @@ completion to the channel’s receivers.

    - +
    package main
     
    diff --git a/public/closures b/public/closures index 6a3ebc4..5cab1c8 100644 --- a/public/closures +++ b/public/closures @@ -30,7 +30,7 @@ a function inline without having to name it.

    - +
    package main
     
    diff --git a/public/collection-functions b/public/collection-functions index 564c960..6aae10a 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -61,7 +61,7 @@ helper function.

    - +
    package main
     
    diff --git a/public/command-line-arguments b/public/command-line-arguments index c6193c3..02470c5 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -30,7 +30,7 @@ For example, go run hello.go uses run and
    - +
    package main
     
    diff --git a/public/command-line-flags b/public/command-line-flags index 88bd23c..47341d4 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -30,7 +30,7 @@ command-line flag.

    - +
    package main
     
    diff --git a/public/constants b/public/constants index 80a89c5..a53a96f 100644 --- a/public/constants +++ b/public/constants @@ -28,7 +28,7 @@ and numeric values.

    - +
    package main
     
    diff --git a/public/defer b/public/defer index a161789..6e2ed91 100644 --- a/public/defer +++ b/public/defer @@ -30,7 +30,7 @@ purposes of cleanup. defer is often used where e.g.
    - +
    package main
     
    diff --git a/public/environment-variables b/public/environment-variables index 10ab446..7e652d1 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -30,7 +30,7 @@ Let’s look at how to set, get, and list environment variables.

    - +
    package main
     
    diff --git a/public/epoch b/public/epoch index 22014fe..aff0719 100644 --- a/public/epoch +++ b/public/epoch @@ -30,7 +30,7 @@ Here’s how to do it in Go.

    - +
    package main
     
    diff --git a/public/errors b/public/errors index ee2e50c..59cfb7e 100644 --- a/public/errors +++ b/public/errors @@ -34,7 +34,7 @@ non-error tasks.

    - +
    package main
     
    diff --git a/public/execing-processes b/public/execing-processes index 61871e5..00af59f 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -35,7 +35,7 @@ function.

    - +
    package main
     
    diff --git a/public/exit b/public/exit index 1b38aee..bb8c7d8 100644 --- a/public/exit +++ b/public/exit @@ -28,7 +28,7 @@ status.

    - +
    package main
     
    diff --git a/public/for b/public/for index c854062..6dc96af 100644 --- a/public/for +++ b/public/for @@ -28,7 +28,7 @@ three basic types of for loops.

    - +
    package main
     
    diff --git a/public/functions b/public/functions index 937f5b4..7f21857 100644 --- a/public/functions +++ b/public/functions @@ -28,7 +28,7 @@ functions with a few different examples.

    - +
    package main
     
    diff --git a/public/goroutines b/public/goroutines index f1f8d18..df884f2 100644 --- a/public/goroutines +++ b/public/goroutines @@ -27,7 +27,7 @@
    - +
    package main
     
    diff --git a/public/hello-world b/public/hello-world index e77ae10..49a6220 100644 --- a/public/hello-world +++ b/public/hello-world @@ -18,7 +18,7 @@ message. Here’s the full source code.

    - +
    package main
     
    diff --git a/public/if-else b/public/if-else index b3415eb..00787c4 100644 --- a/public/if-else +++ b/public/if-else @@ -28,7 +28,7 @@ straight-forward.

    - +
    package main
     
    diff --git a/public/interfaces b/public/interfaces index cf62c06..c0f956e 100644 --- a/public/interfaces +++ b/public/interfaces @@ -28,7 +28,7 @@ signatures.

    - +
    package main
     
    diff --git a/public/json b/public/json index 4d1d210..fe40d60 100644 --- a/public/json +++ b/public/json @@ -29,7 +29,7 @@ data types.

    - +
    package main
     
    diff --git a/public/line-filters b/public/line-filters index 57c6c02..93b704a 100644 --- a/public/line-filters +++ b/public/line-filters @@ -33,7 +33,7 @@ pattern to write your own Go line filters.

    - +
    package main
     
    diff --git a/public/maps b/public/maps index 255af49..4a724b1 100644 --- a/public/maps +++ b/public/maps @@ -28,7 +28,7 @@
    - +
    package main
     
    diff --git a/public/methods b/public/methods index c9f41c7..ef53567 100644 --- a/public/methods +++ b/public/methods @@ -27,7 +27,7 @@
    - +
    package main
     
    diff --git a/public/multiple-return-values b/public/multiple-return-values index 788bfa0..3961507 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -29,7 +29,7 @@ to return both result and error values from a function.

    - +
    package main
     
    diff --git a/public/mutexes b/public/mutexes index 14c744f..6bc013e 100644 --- a/public/mutexes +++ b/public/mutexes @@ -30,7 +30,7 @@ to safely access data across multiple goroutines.

    - +
    package main
     
    diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index 0c9a02e..30c1560 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -30,7 +30,7 @@ non-blocking multi-way selects.

    - +
    package main
     
    diff --git a/public/number-parsing b/public/number-parsing index 3636f60..56c83a2 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -28,7 +28,7 @@ in many programs; here’s how to do it in Go.

    - +
    package main
     
    diff --git a/public/panic b/public/panic index be7c598..10fc46b 100644 --- a/public/panic +++ b/public/panic @@ -30,7 +30,7 @@ aren’t prepared to handle gracefully.

    - +
    package main
     
    diff --git a/public/pointers b/public/pointers index cef55a7..e24ff9b 100644 --- a/public/pointers +++ b/public/pointers @@ -29,7 +29,7 @@ within your program.

    - +
    package main
     
    diff --git a/public/random-numbers b/public/random-numbers index fadc00c..1d7ebd8 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -29,7 +29,7 @@ generation.

    - +
    package main
     
    diff --git a/public/range b/public/range index 37bb665..ead2dea 100644 --- a/public/range +++ b/public/range @@ -29,7 +29,7 @@ of the data structures we’ve already learned.

    - +
    package main
     
    diff --git a/public/range-over-channels b/public/range-over-channels index 0b54622..b6cb1a6 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -30,7 +30,7 @@ values received from a channel.

    - +
    package main
     
    diff --git a/public/rate-limiting b/public/rate-limiting index 7518033..b41c17f 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -31,7 +31,7 @@ channels, and tickers.

    - +
    package main
     
    diff --git a/public/reading-files b/public/reading-files index b002ac9..4aeef67 100644 --- a/public/reading-files +++ b/public/reading-files @@ -29,7 +29,7 @@ reading files.

    - +
    package main
     
    diff --git a/public/recursion b/public/recursion index f2048f1..2bb2a9d 100644 --- a/public/recursion +++ b/public/recursion @@ -29,7 +29,7 @@ Here’s a classic factorial example.

    - +
    package main
     
    diff --git a/public/regular-expressions b/public/regular-expressions index cd93713..0fdd469 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -29,7 +29,7 @@ in Go.

    - +
    package main
     
    diff --git a/public/select b/public/select index 04ca348..12a5aa2 100644 --- a/public/select +++ b/public/select @@ -29,7 +29,7 @@ select is a powerful feature of Go.

    - +
    package main
     
    diff --git a/public/sha1-hashes b/public/sha1-hashes index 5b9aeed..a0cb8c5 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -32,7 +32,7 @@ compute SHA1 hashes in Go.

    - +
    package main
     
    diff --git a/public/signals b/public/signals index 56cc886..f38a239 100644 --- a/public/signals +++ b/public/signals @@ -32,7 +32,7 @@ Here’s how to handle signals in Go with channels.

    - +
    package main
     
    diff --git a/public/slices b/public/slices index 5284efc..18acb11 100644 --- a/public/slices +++ b/public/slices @@ -28,7 +28,7 @@ powerful interface to sequences than arrays.

    - +
    package main
     
    diff --git a/public/sorting b/public/sorting index 95e13d8..eacc67d 100644 --- a/public/sorting +++ b/public/sorting @@ -29,7 +29,7 @@ builtins first.

    - +
    package main
     
    diff --git a/public/sorting-by-functions b/public/sorting-by-functions index 711c5c1..ca48e6f 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -31,7 +31,7 @@ in Go.

    - +
    package main
     
    diff --git a/public/spawning-processes b/public/spawning-processes index 88c0c28..eecc288 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -32,7 +32,7 @@ of spawning processes from Go.

    - +
    package main
     
    diff --git a/public/stateful-goroutines b/public/stateful-goroutines index ea7d4a1..17add47 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -34,7 +34,7 @@ by exactly 1 goroutine.

    - +
    package main
     
    diff --git a/public/string-formatting b/public/string-formatting index 9126fcf..202ca19 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -29,7 +29,7 @@ common string formatting tasks.

    - +
    package main
     
    diff --git a/public/string-functions b/public/string-functions index 440fe49..bcf2866 100644 --- a/public/string-functions +++ b/public/string-functions @@ -29,7 +29,7 @@ to give you a sense of the package.

    - +
    package main
     
    diff --git a/public/structs b/public/structs index f3be51a..f42c329 100644 --- a/public/structs +++ b/public/structs @@ -29,7 +29,7 @@ records.

    - +
    package main
     
    diff --git a/public/switch b/public/switch index c13f0fd..37200b3 100644 --- a/public/switch +++ b/public/switch @@ -28,7 +28,7 @@ branches.

    - +
    package main
     
    diff --git a/public/tickers b/public/tickers index 0c38797..0ea1840 100644 --- a/public/tickers +++ b/public/tickers @@ -31,7 +31,7 @@ periodically until we stop it.

    - +
    package main
     
    diff --git a/public/time b/public/time index 272d320..cfd8b5c 100644 --- a/public/time +++ b/public/time @@ -28,7 +28,7 @@ here are some examples.

    - +
    package main
     
    diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index 16f4105..6e79f33 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -28,7 +28,7 @@ pattern-based layouts.

    - +
    package main
     
    diff --git a/public/timeouts b/public/timeouts index 6033b7a..aa20120 100644 --- a/public/timeouts +++ b/public/timeouts @@ -30,7 +30,7 @@ elegant thanks to channels and select.

    - +
    package main
     
    diff --git a/public/timers b/public/timers index 220d7f4..7a11306 100644 --- a/public/timers +++ b/public/timers @@ -31,7 +31,7 @@ at tickers.

    - +
    package main
     
    diff --git a/public/url-parsing b/public/url-parsing index d3e0e77..efe547c 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -28,7 +28,7 @@ Here’s how to parse URLs in Go.

    - +
    package main
     
    diff --git a/public/values b/public/values index 1a052d0..057fa53 100644 --- a/public/values +++ b/public/values @@ -29,7 +29,7 @@ basic examples.

    - +
    package main
     
    diff --git a/public/variables b/public/variables index 95db760..a02f89a 100644 --- a/public/variables +++ b/public/variables @@ -29,7 +29,7 @@ calls.

    - +
    package main
     
    diff --git a/public/variadic-functions b/public/variadic-functions index e660ef3..b789f72 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -30,7 +30,7 @@ function.

    - +
    package main
     
    diff --git a/public/waitgroups b/public/waitgroups index 1fe8966..d2d6b2e 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -28,7 +28,7 @@ use a wait group.

    - +
    package main
     
    diff --git a/public/worker-pools b/public/worker-pools index ac6909a..5d14690 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -28,7 +28,7 @@ a worker pool using goroutines and channels.

    - +
    package main
     
    diff --git a/public/writing-files b/public/writing-files index 66d254e..4280238 100644 --- a/public/writing-files +++ b/public/writing-files @@ -28,7 +28,7 @@ ones we saw earlier for reading.

    - +
    package main
     
    diff --git a/templates/example.tmpl b/templates/example.tmpl index 8eb58b5..b31f742 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -16,7 +16,7 @@ {{.DocsRendered}}
    - {{if .CodeRun}}{{end}} + {{if .CodeRun}}{{end}} {{.CodeRendered}}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    The Go standard library comes with excellent support +for HTTP clients and servers out of the box with the +net/http package. In this example we’ll use it to +issue simple HTTP requests.

    + +
    + +
    package main
    +
    + +
    + + + +
    import (
    +    "bufio"
    +    "fmt"
    +    "net/http"
    +)
    +
    + +
    +

    Issue a HTTP GET request to a server. http.Get is a +convenient shortcut around creating a http.Client +object and calling its Get() method; it uses the +http.DefaultClient object which has useful default +settings.

    + +
    + +
    func main() {
    +
    + +
    + + + +
        resp, err := http.Get("http://gobyexample.com")
    +    if err != nil {
    +        panic(err)
    +    }
    +    defer resp.Body.Close()
    +
    + +
    +

    Print the HTTP response status.

    + +
    + +
        fmt.Println("Response status:", resp.Status)
    +
    + +
    +

    Print the first 5 lines of the response body.

    + +
    + +
        scanner := bufio.NewScanner(resp.Body)
    +    for i := 0; scanner.Scan() && i < 5; i++ {
    +        fmt.Println(scanner.Text())
    +    }
    +
    + +
    + + + +
        if err := scanner.Err(); err != nil {
    +        panic(err)
    +    }
    +}
    +
    + +
    + + + + + + + + +
    + + + +
    $ go run http-clients.go
    +Response status: 200 OK
    +<!DOCTYPE html>
    +<html>
    +  <head>
    +    <meta charset="utf-8">
    +    <title>Go by Example</title>
    +
    + +
    + + +

    + Next example: Spawning Processes. +

    + + +
    + + diff --git a/public/index.html b/public/index.html index 92ef12f..6b5727f 100644 --- a/public/index.html +++ b/public/index.html @@ -147,6 +147,8 @@
  • Environment Variables
  • +
  • HTTP Clients
  • +
  • Spawning Processes
  • Exec'ing Processes
  • From d2d9a542087356c98dd23289a0ab391e4ca69332 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:10:33 -0700 Subject: [PATCH 074/133] Use fewer words in HTTP Clients intro "out of the box" is implied by "standard library". --- examples/http-clients/http-clients.go | 6 +++--- examples/http-clients/http-clients.hash | 4 ++-- public/http-clients | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go index 170f880..6ff5281 100644 --- a/examples/http-clients/http-clients.go +++ b/examples/http-clients/http-clients.go @@ -1,7 +1,7 @@ // The Go standard library comes with excellent support -// for HTTP clients and servers out of the box with the -// `net/http` package. In this example we'll use it to -// issue simple HTTP requests. +// for HTTP clients and servers in the `net/http` +// package. In this example we'll use it to issue simple +// HTTP requests. package main import ( diff --git a/examples/http-clients/http-clients.hash b/examples/http-clients/http-clients.hash index 7addbe9..0e85307 100644 --- a/examples/http-clients/http-clients.hash +++ b/examples/http-clients/http-clients.hash @@ -1,2 +1,2 @@ -afac2191f24a0861384d142ab58cc262fc47cfbf -Y92yCu1CIrI +cdcaa6f2e1e8596e882dd3eb460e633cfe3dd07c +nXc8J7KyUKd diff --git a/public/http-clients b/public/http-clients index c1dadf0..9bf3077 100644 --- a/public/http-clients +++ b/public/http-clients @@ -14,13 +14,13 @@

    The Go standard library comes with excellent support -for HTTP clients and servers out of the box with the -net/http package. In this example we’ll use it to -issue simple HTTP requests.

    +for HTTP clients and servers in the net/http +package. In this example we’ll use it to issue simple +HTTP requests.

    - +
    package main
     
    From 60bed1aa0d666bf4cb7bf82427f552fa8ab967f0 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:11:24 -0700 Subject: [PATCH 075/133] Update whitespace so comment aligns with relevant code --- examples/http-clients/http-clients.go | 1 + examples/http-clients/http-clients.hash | 4 ++-- public/http-clients | 16 ++++++++-------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go index 6ff5281..e986748 100644 --- a/examples/http-clients/http-clients.go +++ b/examples/http-clients/http-clients.go @@ -11,6 +11,7 @@ import ( ) func main() { + // Issue a HTTP GET request to a server. http.Get is a // convenient shortcut around creating a http.Client // object and calling its Get() method; it uses the diff --git a/examples/http-clients/http-clients.hash b/examples/http-clients/http-clients.hash index 0e85307..bd99392 100644 --- a/examples/http-clients/http-clients.hash +++ b/examples/http-clients/http-clients.hash @@ -1,2 +1,2 @@ -cdcaa6f2e1e8596e882dd3eb460e633cfe3dd07c -nXc8J7KyUKd +991df79b50b0d512a034ec929339a06a1e6230ee +lz5Z7oVYqyF diff --git a/public/http-clients b/public/http-clients index 9bf3077..76419d8 100644 --- a/public/http-clients +++ b/public/http-clients @@ -20,7 +20,7 @@ HTTP requests.

    - +
    package main
     
    @@ -45,12 +45,7 @@ HTTP requests.

    -

    Issue a HTTP GET request to a server. http.Get is a -convenient shortcut around creating a http.Client -object and calling its Get() method; it uses the -http.DefaultClient object which has useful default -settings.

    - +
    @@ -62,7 +57,12 @@ settings.

    - +

    Issue a HTTP GET request to a server. http.Get is a +convenient shortcut around creating a http.Client +object and calling its Get() method; it uses the +http.DefaultClient object which has useful default +settings.

    +
    From c209145948f604fe8a2751efee837a78ed5c1f43 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:14:54 -0700 Subject: [PATCH 076/133] "An HTTP" This could go either way, but my pronunciation of HTTP dictates "an" (: https://www.quora.com/A-http-or-an-http-which-is-the-correct-grammatical-usage --- examples/http-clients/http-clients.go | 4 ++-- examples/http-clients/http-clients.hash | 4 ++-- public/http-clients | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go index e986748..b1e6db2 100644 --- a/examples/http-clients/http-clients.go +++ b/examples/http-clients/http-clients.go @@ -12,8 +12,8 @@ import ( func main() { - // Issue a HTTP GET request to a server. http.Get is a - // convenient shortcut around creating a http.Client + // Issue an HTTP GET request to a server. http.Get is a + // convenient shortcut around creating an http.Client // object and calling its Get() method; it uses the // http.DefaultClient object which has useful default // settings. diff --git a/examples/http-clients/http-clients.hash b/examples/http-clients/http-clients.hash index bd99392..3057f1d 100644 --- a/examples/http-clients/http-clients.hash +++ b/examples/http-clients/http-clients.hash @@ -1,2 +1,2 @@ -991df79b50b0d512a034ec929339a06a1e6230ee -lz5Z7oVYqyF +84f4d5d6264837f07a84c27a09f14e429e8daf94 +HDsvgdX4tGg diff --git a/public/http-clients b/public/http-clients index 76419d8..5e482e4 100644 --- a/public/http-clients +++ b/public/http-clients @@ -20,7 +20,7 @@ HTTP requests.

    - +
    package main
     
    @@ -57,8 +57,8 @@ HTTP requests.

    -

    Issue a HTTP GET request to a server. http.Get is a -convenient shortcut around creating a http.Client +

    Issue an HTTP GET request to a server. http.Get is a +convenient shortcut around creating an http.Client object and calling its Get() method; it uses the http.DefaultClient object which has useful default settings.

    From 41d6630bdd716f4c97a93e676732374245899b8c Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Fri, 31 May 2019 12:18:58 -0700 Subject: [PATCH 077/133] Normalize code fragment typography Per convention, code fragments get monotype and methods in the text don't get parens or parameters. --- examples/http-clients/http-clients.go | 8 ++++---- examples/http-clients/http-clients.hash | 4 ++-- public/http-clients | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go index b1e6db2..56be133 100644 --- a/examples/http-clients/http-clients.go +++ b/examples/http-clients/http-clients.go @@ -12,10 +12,10 @@ import ( func main() { - // Issue an HTTP GET request to a server. http.Get is a - // convenient shortcut around creating an http.Client - // object and calling its Get() method; it uses the - // http.DefaultClient object which has useful default + // Issue an HTTP GET request to a server. `http.Get` is a + // convenient shortcut around creating an `http.Client` + // object and calling its `Get` method; it uses the + // `http.DefaultClient` object which has useful default // settings. resp, err := http.Get("http://gobyexample.com") if err != nil { diff --git a/examples/http-clients/http-clients.hash b/examples/http-clients/http-clients.hash index 3057f1d..e550dd5 100644 --- a/examples/http-clients/http-clients.hash +++ b/examples/http-clients/http-clients.hash @@ -1,2 +1,2 @@ -84f4d5d6264837f07a84c27a09f14e429e8daf94 -HDsvgdX4tGg +ec8fd69aa19e54a7ea05d2a911f09d3a98f0396c +VxYIifr_UuH diff --git a/public/http-clients b/public/http-clients index 5e482e4..21779dd 100644 --- a/public/http-clients +++ b/public/http-clients @@ -20,7 +20,7 @@ HTTP requests.

    - +
    package main
     
    @@ -57,10 +57,10 @@ HTTP requests.

    -

    Issue an HTTP GET request to a server. http.Get is a -convenient shortcut around creating an http.Client -object and calling its Get() method; it uses the -http.DefaultClient object which has useful default +

    Issue an HTTP GET request to a server. http.Get is a +convenient shortcut around creating an http.Client +object and calling its Get method; it uses the +http.DefaultClient object which has useful default settings.

    - +
    package main
     
    @@ -81,7 +81,7 @@ save us some space below.

    Go supports both standard and URL-compatible base64. Here’s how to encode using the standard encoder. The encoder requires a []byte so we -cast our string to that type.

    +convert our string to that type.

    diff --git a/public/constants b/public/constants index a53a96f..bdf3a2f 100644 --- a/public/constants +++ b/public/constants @@ -28,7 +28,7 @@ and numeric values.

    - +
    package main
     
    @@ -106,7 +106,7 @@ arbitrary precision.

    A numeric constant has no type until it’s given -one, such as by an explicit cast.

    +one, such as by an explicit conversion.

    diff --git a/public/json b/public/json index fe40d60..61fe8bc 100644 --- a/public/json +++ b/public/json @@ -29,7 +29,7 @@ data types.

    - +
    package main
     
    @@ -259,8 +259,8 @@ associated errors.

    In order to use the values in the decoded map, -we’ll need to cast them to their appropriate type. -For example here we cast the value in num to +we’ll need to convert them to their appropriate type. +For example here we convert the value in num to the expected float64 type.

    Accessing nested data requires a series of -casts.

    +conversions.

    diff --git a/public/sorting-by-functions b/public/sorting-by-functions index ca48e6f..5daf9d4 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -31,7 +31,7 @@ in Go.

    - +
    package main
     
    @@ -97,8 +97,8 @@ we use len(s[i]) and len(s[j]) here.

    With all of this in place, we can now implement our -custom sort by casting the original fruits slice to -byLength, and then use sort.Sort on that typed +custom sort by converting the original fruits slice +to byLength, and then use sort.Sort on that typed slice.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Some command-line tools, like the go tool or git +have many subcommands, each with its own set of +flags. For example, go build and go get are two +different subcommands of the go tool. +The flag package lets us easily define simple +subcommands that have their own flags.

    + +
    + + +
    + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "flag"
    +    "fmt"
    +    "os"
    +)
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    We declare a subcommand using the NewFlagSet +function, and proceed to define new flags specific +for this subcommand.

    + +
    + +
        fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
    +    fooEnable := fooCmd.Bool("enable", false, "enable")
    +    fooName := fooCmd.String("name", "", "name")
    +
    + +
    +

    For a different subcommand we can define different +supported flags.

    + +
    + +
        barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
    +    barLevel := barCmd.Int("level", 0, "level")
    +
    + +
    +

    The subcommand is expected as the first argument +to the program.

    + +
    + +
        if len(os.Args) < 2 {
    +        fmt.Println("expected 'foo' or 'bar' subcommands")
    +        os.Exit(1)
    +    }
    +
    + +
    +

    Check which subcommand is invoked.

    + +
    + +
        switch os.Args[1] {
    +    case "foo":
    +
    + +
    +

    For every subcommand, we parse its own flags and +have access to trailing positional arguments.

    + +
    + +
            fooCmd.Parse(os.Args[2:])
    +        fmt.Println("subcommand 'foo'")
    +        fmt.Println("  enable:", *fooEnable)
    +        fmt.Println("  name:", *fooName)
    +        fmt.Println("  tail:", fooCmd.Args())
    +    case "bar":
    +        barCmd.Parse(os.Args[2:])
    +        fmt.Println("subcommand 'bar'")
    +        fmt.Println("  level:", *barLevel)
    +        fmt.Println("  tail:", barCmd.Args())
    +    default:
    +        fmt.Println("expected 'foo' or 'bar' subcommands")
    +        os.Exit(1)
    +    }
    +}
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    $ go build command-line-subcommands.go 
    +
    + +
    +

    First invoke the foo subcommand

    + +
    + +
    $ ./command-line-subcommands foo -enable -name=joe a1 a2
    +subcommand 'foo'
    +  enable: true
    +  name: joe
    +  tail: [a1 a2]
    +
    + +
    +

    Now try bar

    + +
    + +
    $ ./command-line-subcommands bar -level 8 a1
    +subcommand 'bar'
    +  level: 8
    +  tail: [a1]
    +
    + +
    +

    But bar won’t accept foo’s flags

    + +
    + +
    $ ./command-line-subcommands bar -enable a1
    +flag provided but not defined: -enable
    +Usage of bar:
    +  -level int
    +    	bar level
    +
    + +
    + + +

    + Next example: Environment Variables. +

    + + +
    + + diff --git a/public/index.html b/public/index.html index 6b5727f..ca79490 100644 --- a/public/index.html +++ b/public/index.html @@ -145,6 +145,8 @@
  • Command-Line Flags
  • +
  • Command-Line Subcommands
  • +
  • Environment Variables
  • HTTP Clients
  • From c00fa9dc79c4fe718c3ca79b9aba2d73403498a1 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 05:49:54 -0700 Subject: [PATCH 081/133] Rebuild for apple --- public/variables | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/variables b/public/variables index a02f89a..a10e9c0 100644 --- a/public/variables +++ b/public/variables @@ -150,7 +150,7 @@ initializing a variable, e.g. for 1 2 true 0 -short +apple
    From af633e81f3d4b1087d743752fd83d298379b5f32 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:25:49 -0700 Subject: [PATCH 082/133] Presentation tweak --- .../command-line-subcommands/command-line-subcommands.go | 6 +++--- .../command-line-subcommands.hash | 4 ++-- public/command-line-subcommands | 8 ++++---- public/variables | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/command-line-subcommands/command-line-subcommands.go b/examples/command-line-subcommands/command-line-subcommands.go index 132c9ec..af57b21 100644 --- a/examples/command-line-subcommands/command-line-subcommands.go +++ b/examples/command-line-subcommands/command-line-subcommands.go @@ -36,10 +36,10 @@ func main() { // Check which subcommand is invoked. switch os.Args[1] { - case "foo": - // For every subcommand, we parse its own flags and - // have access to trailing positional arguments. + // For every subcommand, we parse its own flags and + // have access to trailing positional arguments. + case "foo": fooCmd.Parse(os.Args[2:]) fmt.Println("subcommand 'foo'") fmt.Println(" enable:", *fooEnable) diff --git a/examples/command-line-subcommands/command-line-subcommands.hash b/examples/command-line-subcommands/command-line-subcommands.hash index b26ba5f..f22bcc8 100644 --- a/examples/command-line-subcommands/command-line-subcommands.hash +++ b/examples/command-line-subcommands/command-line-subcommands.hash @@ -1,2 +1,2 @@ -673d7811734cfd8f8f5bcb411e12def1e158cf0b -V7xR3wMkquz +5a0ec258e4992e9b93b11d48f2f249092ff3db66 +gtgSAg76N4I diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 190970c..f53c19f 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -32,7 +32,7 @@ subcommands that have their own flags.

    - +
    package main
     
    @@ -124,7 +124,6 @@ to the program.

        switch os.Args[1] {
    -    case "foo":
     
    @@ -138,7 +137,8 @@ have access to trailing positional arguments.

    -
            fooCmd.Parse(os.Args[2:])
    +            
        case "foo":
    +        fooCmd.Parse(os.Args[2:])
             fmt.Println("subcommand 'foo'")
             fmt.Println("  enable:", *fooEnable)
             fmt.Println("  name:", *fooName)
    @@ -218,7 +218,7 @@ have access to trailing positional arguments.

    flag provided but not defined: -enable Usage of bar: -level int - bar level + level
    diff --git a/public/variables b/public/variables index a02f89a..a10e9c0 100644 --- a/public/variables +++ b/public/variables @@ -150,7 +150,7 @@ initializing a variable, e.g. for 1 2 true 0 -short +apple
    From 7c160440be5b7d6b70da2a56d610546564b8f83c Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 1 Jun 2019 06:04:32 -0700 Subject: [PATCH 083/133] Use tabs as the canonical source indentation in git Space conversion is done during generation only. Fixes #192 --- examples/arrays/arrays.go | 56 +++--- examples/arrays/arrays.hash | 2 +- examples/atomic-counters/atomic-counters.go | 58 +++--- examples/base64-encoding/base64-encoding.go | 40 ++--- .../channel-buffering/channel-buffering.go | 22 +-- .../channel-buffering/channel-buffering.hash | 2 +- .../channel-directions/channel-directions.go | 16 +- .../channel-directions.hash | 2 +- .../channel-synchronization.go | 24 +-- examples/channels/channels.go | 24 +-- examples/channels/channels.hash | 2 +- examples/closing-channels/closing-channels.go | 66 +++---- .../closing-channels/closing-channels.hash | 2 +- examples/closures/closures.go | 38 ++-- .../collection-functions.go | 96 +++++----- .../command-line-arguments.go | 22 +-- .../command-line-arguments.hash | 2 +- .../command-line-flags/command-line-flags.go | 58 +++--- .../command-line-flags.hash | 2 +- examples/constants/constants.go | 32 ++-- examples/defer/defer.go | 36 ++-- examples/defer/defer.hash | 2 +- .../environment-variables.go | 32 ++-- .../environment-variables.hash | 2 +- examples/epoch/epoch.go | 36 ++-- examples/epoch/epoch.hash | 2 +- examples/errors/errors.go | 90 +++++----- .../execing-processes/execing-processes.go | 52 +++--- .../execing-processes/execing-processes.hash | 2 +- examples/exit/exit.go | 10 +- examples/exit/exit.hash | 2 +- examples/for/for.go | 50 +++--- examples/for/for.hash | 2 +- examples/functions/functions.go | 22 +-- examples/functions/functions.hash | 2 +- examples/goroutines/goroutines.go | 44 ++--- examples/hello-world/hello-world.go | 2 +- examples/hello-world/hello-world.hash | 2 +- examples/http-clients/http-clients.go | 46 ++--- examples/if-else/if-else.go | 40 ++--- examples/if-else/if-else.hash | 2 +- examples/interfaces/interfaces.go | 38 ++-- examples/interfaces/interfaces.hash | 2 +- examples/json/json.go | 170 +++++++++--------- examples/line-filters/line-filters.go | 44 ++--- examples/line-filters/line-filters.hash | 2 +- examples/maps/maps.go | 66 +++---- examples/methods/methods.go | 30 ++-- examples/methods/methods.hash | 2 +- .../multiple-return-values.go | 20 +-- .../multiple-return-values.hash | 2 +- examples/mutexes/mutexes.go | 126 ++++++------- .../non-blocking-channel-operations.go | 70 ++++---- examples/number-parsing/number-parsing.go | 44 ++--- examples/number-parsing/number-parsing.hash | 2 +- examples/panic/panic.go | 24 +-- examples/panic/panic.hash | 2 +- examples/pointers/pointers.go | 24 +-- examples/pointers/pointers.hash | 2 +- examples/random-numbers/random-numbers.go | 72 ++++---- examples/random-numbers/random-numbers.hash | 2 +- .../range-over-channels.go | 24 +-- .../range-over-channels.hash | 2 +- examples/range/range.go | 66 +++---- examples/range/range.hash | 2 +- examples/rate-limiting/rate-limiting.go | 98 +++++----- examples/reading-files/reading-files.go | 118 ++++++------ examples/reading-files/reading-files.hash | 2 +- examples/recursion/recursion.go | 10 +- examples/recursion/recursion.hash | 2 +- .../regular-expressions.go | 110 ++++++------ .../regular-expressions.hash | 2 +- examples/select/select.go | 48 ++--- examples/sha1-hashes/sha1-hashes.go | 34 ++-- examples/sha1-hashes/sha1-hashes.hash | 2 +- examples/signals/signals.go | 48 ++--- examples/signals/signals.hash | 2 +- examples/slices/slices.go | 114 ++++++------ .../sorting-by-functions.go | 12 +- examples/sorting/sorting.go | 30 ++-- examples/sorting/sorting.hash | 2 +- .../spawning-processes/spawning-processes.go | 100 +++++------ .../spawning-processes.hash | 2 +- .../stateful-goroutines.go | 158 ++++++++-------- .../string-formatting/string-formatting.go | 144 +++++++-------- .../string-formatting/string-formatting.hash | 2 +- examples/string-functions/string-functions.go | 50 +++--- .../string-functions/string-functions.hash | 2 +- examples/structs/structs.go | 40 ++--- examples/structs/structs.hash | 2 +- examples/switch/switch.go | 94 +++++----- examples/tickers/tickers.go | 32 ++-- .../time-formatting-parsing.go | 70 ++++---- .../time-formatting-parsing.hash | 2 +- examples/time/time.go | 86 ++++----- examples/time/time.hash | 2 +- examples/timeouts/timeouts.go | 66 +++---- examples/timers/timers.go | 46 ++--- examples/url-parsing/url-parsing.go | 74 ++++---- examples/values/values.go | 18 +- examples/values/values.hash | 2 +- examples/variables/variables.go | 38 ++-- .../variadic-functions/variadic-functions.go | 30 ++-- examples/waitgroups/waitgroups.go | 42 ++--- examples/worker-pools/worker-pools.go | 58 +++--- examples/writing-files/writing-files.go | 72 ++++---- examples/writing-files/writing-files.hash | 2 +- public/arrays | 2 +- public/channel-buffering | 2 +- public/channel-directions | 2 +- public/channels | 2 +- public/closing-channels | 2 +- public/command-line-arguments | 2 +- public/command-line-flags | 2 +- public/defer | 2 +- public/environment-variables | 2 +- public/epoch | 2 +- public/execing-processes | 2 +- public/exit | 2 +- public/for | 2 +- public/functions | 2 +- public/hello-world | 4 +- public/if-else | 2 +- public/interfaces | 2 +- public/line-filters | 2 +- public/methods | 2 +- public/multiple-return-values | 2 +- public/number-parsing | 2 +- public/panic | 4 +- public/pointers | 2 +- public/random-numbers | 2 +- public/range | 2 +- public/range-over-channels | 2 +- public/reading-files | 2 +- public/recursion | 2 +- public/regular-expressions | 2 +- public/select | 2 +- public/sha1-hashes | 2 +- public/signals | 2 +- public/sorting | 2 +- public/spawning-processes | 2 +- public/string-formatting | 2 +- public/string-functions | 2 +- public/structs | 2 +- public/time | 2 +- public/time-formatting-parsing | 2 +- public/values | 2 +- public/worker-pools | 2 +- public/writing-files | 2 +- tools/format | 18 -- tools/generate.go | 9 +- tools/measure.go | 3 + 152 files changed, 1929 insertions(+), 1939 deletions(-) diff --git a/examples/arrays/arrays.go b/examples/arrays/arrays.go index b0464bd..54bff09 100644 --- a/examples/arrays/arrays.go +++ b/examples/arrays/arrays.go @@ -7,36 +7,36 @@ import "fmt" func main() { - // Here we create an array `a` that will hold exactly - // 5 `int`s. The type of elements and length are both - // part of the array's type. By default an array is - // zero-valued, which for `int`s means `0`s. - var a [5]int - fmt.Println("emp:", a) + // Here we create an array `a` that will hold exactly + // 5 `int`s. The type of elements and length are both + // part of the array's type. By default an array is + // zero-valued, which for `int`s means `0`s. + var a [5]int + fmt.Println("emp:", a) - // We can set a value at an index using the - // `array[index] = value` syntax, and get a value with - // `array[index]`. - a[4] = 100 - fmt.Println("set:", a) - fmt.Println("get:", a[4]) + // We can set a value at an index using the + // `array[index] = value` syntax, and get a value with + // `array[index]`. + a[4] = 100 + fmt.Println("set:", a) + fmt.Println("get:", a[4]) - // The builtin `len` returns the length of an array. - fmt.Println("len:", len(a)) + // The builtin `len` returns the length of an array. + fmt.Println("len:", len(a)) - // Use this syntax to declare and initialize an array - // in one line. - b := [5]int{1, 2, 3, 4, 5} - fmt.Println("dcl:", b) + // Use this syntax to declare and initialize an array + // in one line. + b := [5]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) - // Array types are one-dimensional, but you can - // compose types to build multi-dimensional data - // structures. - var twoD [2][3]int - for i := 0; i < 2; i++ { - for j := 0; j < 3; j++ { - twoD[i][j] = i + j - } - } - fmt.Println("2d: ", twoD) + // Array types are one-dimensional, but you can + // compose types to build multi-dimensional data + // structures. + var twoD [2][3]int + for i := 0; i < 2; i++ { + for j := 0; j < 3; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) } diff --git a/examples/arrays/arrays.hash b/examples/arrays/arrays.hash index 516ae70..cae0e0d 100644 --- a/examples/arrays/arrays.hash +++ b/examples/arrays/arrays.hash @@ -1,2 +1,2 @@ 305975d13d24223181d13f042b290906d86c1a0e -l-A8eBnwio +W7NwfDq8Vdw diff --git a/examples/atomic-counters/atomic-counters.go b/examples/atomic-counters/atomic-counters.go index 0f3a52e..9df3276 100644 --- a/examples/atomic-counters/atomic-counters.go +++ b/examples/atomic-counters/atomic-counters.go @@ -13,37 +13,37 @@ import "sync/atomic" func main() { - // We'll use an unsigned integer to represent our - // (always-positive) counter. - var ops uint64 + // We'll use an unsigned integer to represent our + // (always-positive) counter. + var ops uint64 - // To simulate concurrent updates, we'll start 50 - // goroutines that each increment the counter about - // once a millisecond. - for i := 0; i < 50; i++ { - go func() { - for { - // To atomically increment the counter we - // use `AddUint64`, giving it the memory - // address of our `ops` counter with the - // `&` syntax. - atomic.AddUint64(&ops, 1) + // To simulate concurrent updates, we'll start 50 + // goroutines that each increment the counter about + // once a millisecond. + for i := 0; i < 50; i++ { + go func() { + for { + // To atomically increment the counter we + // use `AddUint64`, giving it the memory + // address of our `ops` counter with the + // `&` syntax. + atomic.AddUint64(&ops, 1) - // Wait a bit between increments. - time.Sleep(time.Millisecond) - } - }() - } + // Wait a bit between increments. + time.Sleep(time.Millisecond) + } + }() + } - // Wait a second to allow some ops to accumulate. - time.Sleep(time.Second) + // Wait a second to allow some ops to accumulate. + time.Sleep(time.Second) - // In order to safely use the counter while it's still - // being updated by other goroutines, we extract a - // copy of the current value into `opsFinal` via - // `LoadUint64`. As above we need to give this - // function the memory address `&ops` from which to - // fetch the value. - opsFinal := atomic.LoadUint64(&ops) - fmt.Println("ops:", opsFinal) + // In order to safely use the counter while it's still + // being updated by other goroutines, we extract a + // copy of the current value into `opsFinal` via + // `LoadUint64`. As above we need to give this + // function the memory address `&ops` from which to + // fetch the value. + opsFinal := atomic.LoadUint64(&ops) + fmt.Println("ops:", opsFinal) } diff --git a/examples/base64-encoding/base64-encoding.go b/examples/base64-encoding/base64-encoding.go index d428ae5..4bdeaf1 100644 --- a/examples/base64-encoding/base64-encoding.go +++ b/examples/base64-encoding/base64-encoding.go @@ -11,27 +11,27 @@ import "fmt" func main() { - // Here's the `string` we'll encode/decode. - data := "abc123!?$*&()'-=@~" + // Here's the `string` we'll encode/decode. + data := "abc123!?$*&()'-=@~" - // Go supports both standard and URL-compatible - // base64. Here's how to encode using the standard - // encoder. The encoder requires a `[]byte` so we - // convert our `string` to that type. - sEnc := b64.StdEncoding.EncodeToString([]byte(data)) - fmt.Println(sEnc) + // Go supports both standard and URL-compatible + // base64. Here's how to encode using the standard + // encoder. The encoder requires a `[]byte` so we + // convert our `string` to that type. + sEnc := b64.StdEncoding.EncodeToString([]byte(data)) + fmt.Println(sEnc) - // Decoding may return an error, which you can check - // if you don't already know the input to be - // well-formed. - sDec, _ := b64.StdEncoding.DecodeString(sEnc) - fmt.Println(string(sDec)) - fmt.Println() + // Decoding may return an error, which you can check + // if you don't already know the input to be + // well-formed. + sDec, _ := b64.StdEncoding.DecodeString(sEnc) + fmt.Println(string(sDec)) + fmt.Println() - // This encodes/decodes using a URL-compatible base64 - // format. - uEnc := b64.URLEncoding.EncodeToString([]byte(data)) - fmt.Println(uEnc) - uDec, _ := b64.URLEncoding.DecodeString(uEnc) - fmt.Println(string(uDec)) + // This encodes/decodes using a URL-compatible base64 + // format. + uEnc := b64.URLEncoding.EncodeToString([]byte(data)) + fmt.Println(uEnc) + uDec, _ := b64.URLEncoding.DecodeString(uEnc) + fmt.Println(string(uDec)) } diff --git a/examples/channel-buffering/channel-buffering.go b/examples/channel-buffering/channel-buffering.go index d6ee52e..d2e8d8f 100644 --- a/examples/channel-buffering/channel-buffering.go +++ b/examples/channel-buffering/channel-buffering.go @@ -11,17 +11,17 @@ import "fmt" func main() { - // Here we `make` a channel of strings buffering up to - // 2 values. - messages := make(chan string, 2) + // Here we `make` a channel of strings buffering up to + // 2 values. + messages := make(chan string, 2) - // Because this channel is buffered, we can send these - // values into the channel without a corresponding - // concurrent receive. - messages <- "buffered" - messages <- "channel" + // Because this channel is buffered, we can send these + // values into the channel without a corresponding + // concurrent receive. + messages <- "buffered" + messages <- "channel" - // Later we can receive these two values as usual. - fmt.Println(<-messages) - fmt.Println(<-messages) + // Later we can receive these two values as usual. + fmt.Println(<-messages) + fmt.Println(<-messages) } diff --git a/examples/channel-buffering/channel-buffering.hash b/examples/channel-buffering/channel-buffering.hash index c82a990..6956e03 100644 --- a/examples/channel-buffering/channel-buffering.hash +++ b/examples/channel-buffering/channel-buffering.hash @@ -1,2 +1,2 @@ 122140f7ad1bc5cff4fcd7a9e7245b87aaca3ec5 -34PVHwO6Bn +mPoF-Xi-rip diff --git a/examples/channel-directions/channel-directions.go b/examples/channel-directions/channel-directions.go index becb45d..5f2786c 100644 --- a/examples/channel-directions/channel-directions.go +++ b/examples/channel-directions/channel-directions.go @@ -11,20 +11,20 @@ import "fmt" // values. It would be a compile-time error to try to // receive on this channel. func ping(pings chan<- string, msg string) { - pings <- msg + pings <- msg } // The `pong` function accepts one channel for receives // (`pings`) and a second for sends (`pongs`). func pong(pings <-chan string, pongs chan<- string) { - msg := <-pings - pongs <- msg + msg := <-pings + pongs <- msg } func main() { - pings := make(chan string, 1) - pongs := make(chan string, 1) - ping(pings, "passed message") - pong(pings, pongs) - fmt.Println(<-pongs) + pings := make(chan string, 1) + pongs := make(chan string, 1) + ping(pings, "passed message") + pong(pings, pongs) + fmt.Println(<-pongs) } diff --git a/examples/channel-directions/channel-directions.hash b/examples/channel-directions/channel-directions.hash index e881c47..fb68662 100644 --- a/examples/channel-directions/channel-directions.hash +++ b/examples/channel-directions/channel-directions.hash @@ -1,2 +1,2 @@ 635cc13dfe33123ac188e01e3002d3aa935d765f -P9Fujfpa1f +Jnn9_9hC48c diff --git a/examples/channel-synchronization/channel-synchronization.go b/examples/channel-synchronization/channel-synchronization.go index 66873a8..79ceafe 100644 --- a/examples/channel-synchronization/channel-synchronization.go +++ b/examples/channel-synchronization/channel-synchronization.go @@ -13,22 +13,22 @@ import "time" // `done` channel will be used to notify another // goroutine that this function's work is done. func worker(done chan bool) { - fmt.Print("working...") - time.Sleep(time.Second) - fmt.Println("done") + fmt.Print("working...") + time.Sleep(time.Second) + fmt.Println("done") - // Send a value to notify that we're done. - done <- true + // Send a value to notify that we're done. + done <- true } func main() { - // Start a worker goroutine, giving it the channel to - // notify on. - done := make(chan bool, 1) - go worker(done) + // Start a worker goroutine, giving it the channel to + // notify on. + done := make(chan bool, 1) + go worker(done) - // Block until we receive a notification from the - // worker on the channel. - <-done + // Block until we receive a notification from the + // worker on the channel. + <-done } diff --git a/examples/channels/channels.go b/examples/channels/channels.go index 94fb458..7a5ac9a 100644 --- a/examples/channels/channels.go +++ b/examples/channels/channels.go @@ -9,18 +9,18 @@ import "fmt" func main() { - // Create a new channel with `make(chan val-type)`. - // Channels are typed by the values they convey. - messages := make(chan string) + // Create a new channel with `make(chan val-type)`. + // Channels are typed by the values they convey. + messages := make(chan string) - // _Send_ a value into a channel using the `channel <-` - // syntax. Here we send `"ping"` to the `messages` - // channel we made above, from a new goroutine. - go func() { messages <- "ping" }() + // _Send_ a value into a channel using the `channel <-` + // syntax. Here we send `"ping"` to the `messages` + // channel we made above, from a new goroutine. + go func() { messages <- "ping" }() - // The `<-channel` syntax _receives_ a value from the - // channel. Here we'll receive the `"ping"` message - // we sent above and print it out. - msg := <-messages - fmt.Println(msg) + // The `<-channel` syntax _receives_ a value from the + // channel. Here we'll receive the `"ping"` message + // we sent above and print it out. + msg := <-messages + fmt.Println(msg) } diff --git a/examples/channels/channels.hash b/examples/channels/channels.hash index 4f8f90e..92301ce 100644 --- a/examples/channels/channels.hash +++ b/examples/channels/channels.hash @@ -1,2 +1,2 @@ 926212c784ab820648906c96f6ab21afbc161526 -Kd8B0T_JGK +bRGMAqinovA diff --git a/examples/closing-channels/closing-channels.go b/examples/closing-channels/closing-channels.go index 575b4e9..926d9b5 100644 --- a/examples/closing-channels/closing-channels.go +++ b/examples/closing-channels/closing-channels.go @@ -11,40 +11,40 @@ import "fmt" // to a worker goroutine. When we have no more jobs for // the worker we'll `close` the `jobs` channel. func main() { - jobs := make(chan int, 5) - done := make(chan bool) + jobs := make(chan int, 5) + done := make(chan bool) - // Here's the worker goroutine. It repeatedly receives - // from `jobs` with `j, more := <-jobs`. In this - // special 2-value form of receive, the `more` value - // will be `false` if `jobs` has been `close`d and all - // values in the channel have already been received. - // We use this to notify on `done` when we've worked - // all our jobs. - go func() { - for { - j, more := <-jobs - if more { - fmt.Println("received job", j) - } else { - fmt.Println("received all jobs") - done <- true - return - } - } - }() + // Here's the worker goroutine. It repeatedly receives + // from `jobs` with `j, more := <-jobs`. In this + // special 2-value form of receive, the `more` value + // will be `false` if `jobs` has been `close`d and all + // values in the channel have already been received. + // We use this to notify on `done` when we've worked + // all our jobs. + go func() { + for { + j, more := <-jobs + if more { + fmt.Println("received job", j) + } else { + fmt.Println("received all jobs") + done <- true + return + } + } + }() - // This sends 3 jobs to the worker over the `jobs` - // channel, then closes it. - for j := 1; j <= 3; j++ { - jobs <- j - fmt.Println("sent job", j) - } - close(jobs) - fmt.Println("sent all jobs") + // This sends 3 jobs to the worker over the `jobs` + // channel, then closes it. + for j := 1; j <= 3; j++ { + jobs <- j + fmt.Println("sent job", j) + } + close(jobs) + fmt.Println("sent all jobs") - // We await the worker using the - // [synchronization](channel-synchronization) approach - // we saw earlier. - <-done + // We await the worker using the + // [synchronization](channel-synchronization) approach + // we saw earlier. + <-done } diff --git a/examples/closing-channels/closing-channels.hash b/examples/closing-channels/closing-channels.hash index b6f3076..007751f 100644 --- a/examples/closing-channels/closing-channels.hash +++ b/examples/closing-channels/closing-channels.hash @@ -1,2 +1,2 @@ 5205898a520533e46ea24c849848d19ebc2d08a9 -eFZ2SeKswH +mkz69rVMHs6 diff --git a/examples/closures/closures.go b/examples/closures/closures.go index 195a1ef..90dc2eb 100644 --- a/examples/closures/closures.go +++ b/examples/closures/closures.go @@ -12,29 +12,29 @@ import "fmt" // returned function _closes over_ the variable `i` to // form a closure. func intSeq() func() int { - i := 0 - return func() int { - i++ - return i - } + i := 0 + return func() int { + i++ + return i + } } func main() { - // We call `intSeq`, assigning the result (a function) - // to `nextInt`. This function value captures its - // own `i` value, which will be updated each time - // we call `nextInt`. - nextInt := intSeq() + // We call `intSeq`, assigning the result (a function) + // to `nextInt`. This function value captures its + // own `i` value, which will be updated each time + // we call `nextInt`. + nextInt := intSeq() - // See the effect of the closure by calling `nextInt` - // a few times. - fmt.Println(nextInt()) - fmt.Println(nextInt()) - fmt.Println(nextInt()) + // See the effect of the closure by calling `nextInt` + // a few times. + fmt.Println(nextInt()) + fmt.Println(nextInt()) + fmt.Println(nextInt()) - // To confirm that the state is unique to that - // particular function, create and test a new one. - newInts := intSeq() - fmt.Println(newInts()) + // To confirm that the state is unique to that + // particular function, create and test a new one. + newInts := intSeq() + fmt.Println(newInts()) } diff --git a/examples/collection-functions/collection-functions.go b/examples/collection-functions/collection-functions.go index 1e217d5..b6ff547 100644 --- a/examples/collection-functions/collection-functions.go +++ b/examples/collection-functions/collection-functions.go @@ -24,88 +24,88 @@ import "fmt" // Index returns the first index of the target string `t`, or // -1 if no match is found. func Index(vs []string, t string) int { - for i, v := range vs { - if v == t { - return i - } - } - return -1 + for i, v := range vs { + if v == t { + return i + } + } + return -1 } // Include returns `true` if the target string t is in the // slice. func Include(vs []string, t string) bool { - return Index(vs, t) >= 0 + return Index(vs, t) >= 0 } // Any returns `true` if one of the strings in the slice // satisfies the predicate `f`. func Any(vs []string, f func(string) bool) bool { - for _, v := range vs { - if f(v) { - return true - } - } - return false + for _, v := range vs { + if f(v) { + return true + } + } + return false } // All returns `true` if all of the strings in the slice // satisfy the predicate `f`. func All(vs []string, f func(string) bool) bool { - for _, v := range vs { - if !f(v) { - return false - } - } - return true + for _, v := range vs { + if !f(v) { + return false + } + } + return true } // Filter returns a new slice containing all strings in the // slice that satisfy the predicate `f`. func Filter(vs []string, f func(string) bool) []string { - vsf := make([]string, 0) - for _, v := range vs { - if f(v) { - vsf = append(vsf, v) - } - } - return vsf + vsf := make([]string, 0) + for _, v := range vs { + if f(v) { + vsf = append(vsf, v) + } + } + return vsf } // Map returns a new slice containing the results of applying // 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 { - vsm[i] = f(v) - } - return vsm + vsm := make([]string, len(vs)) + for i, v := range vs { + vsm[i] = f(v) + } + return vsm } func main() { - // Here we try out our various collection functions. - var strs = []string{"peach", "apple", "pear", "plum"} + // Here we try out our various collection functions. + var strs = []string{"peach", "apple", "pear", "plum"} - fmt.Println(Index(strs, "pear")) + fmt.Println(Index(strs, "pear")) - fmt.Println(Include(strs, "grape")) + fmt.Println(Include(strs, "grape")) - fmt.Println(Any(strs, func(v string) bool { - return strings.HasPrefix(v, "p") - })) + fmt.Println(Any(strs, func(v string) bool { + return strings.HasPrefix(v, "p") + })) - fmt.Println(All(strs, func(v string) bool { - return strings.HasPrefix(v, "p") - })) + fmt.Println(All(strs, func(v string) bool { + return strings.HasPrefix(v, "p") + })) - fmt.Println(Filter(strs, func(v string) bool { - return strings.Contains(v, "e") - })) + fmt.Println(Filter(strs, func(v string) bool { + return strings.Contains(v, "e") + })) - // The above examples all used anonymous functions, - // but you can also use named functions of the correct - // type. - fmt.Println(Map(strs, strings.ToUpper)) + // The above examples all used anonymous functions, + // but you can also use named functions of the correct + // type. + fmt.Println(Map(strs, strings.ToUpper)) } diff --git a/examples/command-line-arguments/command-line-arguments.go b/examples/command-line-arguments/command-line-arguments.go index 275a6f7..e000e13 100644 --- a/examples/command-line-arguments/command-line-arguments.go +++ b/examples/command-line-arguments/command-line-arguments.go @@ -10,17 +10,17 @@ import "fmt" func main() { - // `os.Args` provides access to raw command-line - // arguments. Note that the first value in this slice - // is the path to the program, and `os.Args[1:]` - // holds the arguments to the program. - argsWithProg := os.Args - argsWithoutProg := os.Args[1:] + // `os.Args` provides access to raw command-line + // arguments. Note that the first value in this slice + // is the path to the program, and `os.Args[1:]` + // holds the arguments to the program. + argsWithProg := os.Args + argsWithoutProg := os.Args[1:] - // You can get individual args with normal indexing. - arg := os.Args[3] + // You can get individual args with normal indexing. + arg := os.Args[3] - fmt.Println(argsWithProg) - fmt.Println(argsWithoutProg) - fmt.Println(arg) + fmt.Println(argsWithProg) + fmt.Println(argsWithoutProg) + fmt.Println(arg) } diff --git a/examples/command-line-arguments/command-line-arguments.hash b/examples/command-line-arguments/command-line-arguments.hash index 4fd8561..5bf53c7 100644 --- a/examples/command-line-arguments/command-line-arguments.hash +++ b/examples/command-line-arguments/command-line-arguments.hash @@ -1,2 +1,2 @@ 41c970a1ef29ad2a05307e6c783ff52ab80eaccd -44uyYt_TRl +6pFdjf800jj diff --git a/examples/command-line-flags/command-line-flags.go b/examples/command-line-flags/command-line-flags.go index 717a8fb..ab9c1b7 100644 --- a/examples/command-line-flags/command-line-flags.go +++ b/examples/command-line-flags/command-line-flags.go @@ -13,37 +13,37 @@ import "fmt" func main() { - // Basic flag declarations are available for string, - // integer, and boolean options. Here we declare a - // string flag `word` with a default value `"foo"` - // and a short description. This `flag.String` function - // returns a string pointer (not a string value); - // we'll see how to use this pointer below. - wordPtr := flag.String("word", "foo", "a string") + // Basic flag declarations are available for string, + // integer, and boolean options. Here we declare a + // string flag `word` with a default value `"foo"` + // and a short description. This `flag.String` function + // returns a string pointer (not a string value); + // we'll see how to use this pointer below. + wordPtr := flag.String("word", "foo", "a string") - // This declares `numb` and `fork` flags, using a - // similar approach to the `word` flag. - numbPtr := flag.Int("numb", 42, "an int") - boolPtr := flag.Bool("fork", false, "a bool") + // This declares `numb` and `fork` flags, using a + // similar approach to the `word` flag. + numbPtr := flag.Int("numb", 42, "an int") + boolPtr := flag.Bool("fork", false, "a bool") - // It's also possible to declare an option that uses an - // existing var declared elsewhere in the program. - // Note that we need to pass in a pointer to the flag - // declaration function. - var svar string - flag.StringVar(&svar, "svar", "bar", "a string var") + // It's also possible to declare an option that uses an + // existing var declared elsewhere in the program. + // Note that we need to pass in a pointer to the flag + // declaration function. + var svar string + flag.StringVar(&svar, "svar", "bar", "a string var") - // Once all flags are declared, call `flag.Parse()` - // to execute the command-line parsing. - flag.Parse() + // Once all flags are declared, call `flag.Parse()` + // to execute the command-line parsing. + flag.Parse() - // Here we'll just dump out the parsed options and - // any trailing positional arguments. Note that we - // need to dereference the pointers with e.g. `*wordPtr` - // to get the actual option values. - fmt.Println("word:", *wordPtr) - fmt.Println("numb:", *numbPtr) - fmt.Println("fork:", *boolPtr) - fmt.Println("svar:", svar) - fmt.Println("tail:", flag.Args()) + // Here we'll just dump out the parsed options and + // any trailing positional arguments. Note that we + // need to dereference the pointers with e.g. `*wordPtr` + // to get the actual option values. + fmt.Println("word:", *wordPtr) + fmt.Println("numb:", *numbPtr) + fmt.Println("fork:", *boolPtr) + fmt.Println("svar:", svar) + fmt.Println("tail:", flag.Args()) } diff --git a/examples/command-line-flags/command-line-flags.hash b/examples/command-line-flags/command-line-flags.hash index e3f2d05..1b8f3ac 100644 --- a/examples/command-line-flags/command-line-flags.hash +++ b/examples/command-line-flags/command-line-flags.hash @@ -1,2 +1,2 @@ e2ba0461c090789168c712cc7ed0f66aab09a8c8 -NASEOq2R3n +klFR5DitrCy diff --git a/examples/constants/constants.go b/examples/constants/constants.go index ed4b56a..50ce8f2 100644 --- a/examples/constants/constants.go +++ b/examples/constants/constants.go @@ -10,24 +10,24 @@ import "math" const s string = "constant" func main() { - fmt.Println(s) + fmt.Println(s) - // A `const` statement can appear anywhere a `var` - // statement can. - const n = 500000000 + // A `const` statement can appear anywhere a `var` + // statement can. + const n = 500000000 - // Constant expressions perform arithmetic with - // arbitrary precision. - const d = 3e20 / n - fmt.Println(d) + // Constant expressions perform arithmetic with + // arbitrary precision. + const d = 3e20 / n + fmt.Println(d) - // A numeric constant has no type until it's given - // one, such as by an explicit conversion. - fmt.Println(int64(d)) + // A numeric constant has no type until it's given + // one, such as by an explicit conversion. + fmt.Println(int64(d)) - // A number can be given a type by using it in a - // context that requires one, such as a variable - // assignment or function call. For example, here - // `math.Sin` expects a `float64`. - fmt.Println(math.Sin(n)) + // A number can be given a type by using it in a + // context that requires one, such as a variable + // assignment or function call. For example, here + // `math.Sin` expects a `float64`. + fmt.Println(math.Sin(n)) } diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 46b8e67..06c827f 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -13,32 +13,32 @@ import "os" // do that with `defer`. func main() { - // Immediately after getting a file object with - // `createFile`, we defer the closing of that file - // with `closeFile`. This will be executed at the end - // of the enclosing function (`main`), after - // `writeFile` has finished. - f := createFile("/tmp/defer.txt") - defer closeFile(f) - writeFile(f) + // Immediately after getting a file object with + // `createFile`, we defer the closing of that file + // with `closeFile`. This will be executed at the end + // of the enclosing function (`main`), after + // `writeFile` has finished. + f := createFile("/tmp/defer.txt") + defer closeFile(f) + writeFile(f) } func createFile(p string) *os.File { - fmt.Println("creating") - f, err := os.Create(p) - if err != nil { - panic(err) - } - return f + fmt.Println("creating") + f, err := os.Create(p) + if err != nil { + panic(err) + } + return f } func writeFile(f *os.File) { - fmt.Println("writing") - fmt.Fprintln(f, "data") + fmt.Println("writing") + fmt.Fprintln(f, "data") } func closeFile(f *os.File) { - fmt.Println("closing") - f.Close() + fmt.Println("closing") + f.Close() } diff --git a/examples/defer/defer.hash b/examples/defer/defer.hash index 726cb8c..2994617 100644 --- a/examples/defer/defer.hash +++ b/examples/defer/defer.hash @@ -1,2 +1,2 @@ 570699fc50a1d39e9d0ad6a4461aef3248b080e1 -9aoHwzHcAo +xPbQ5SGkH2O diff --git a/examples/environment-variables/environment-variables.go b/examples/environment-variables/environment-variables.go index 41852ac..beca4e7 100644 --- a/examples/environment-variables/environment-variables.go +++ b/examples/environment-variables/environment-variables.go @@ -11,21 +11,21 @@ import "fmt" func main() { - // To set a key/value pair, use `os.Setenv`. To get a - // value for a key, use `os.Getenv`. This will return - // an empty string if the key isn't present in the - // environment. - os.Setenv("FOO", "1") - fmt.Println("FOO:", os.Getenv("FOO")) - fmt.Println("BAR:", os.Getenv("BAR")) + // To set a key/value pair, use `os.Setenv`. To get a + // value for a key, use `os.Getenv`. This will return + // an empty string if the key isn't present in the + // environment. + os.Setenv("FOO", "1") + fmt.Println("FOO:", os.Getenv("FOO")) + fmt.Println("BAR:", os.Getenv("BAR")) - // Use `os.Environ` to list all key/value pairs in the - // environment. This returns a slice of strings in the - // form `KEY=value`. You can `strings.Split` them to - // get the key and value. Here we print all the keys. - fmt.Println() - for _, e := range os.Environ() { - pair := strings.Split(e, "=") - fmt.Println(pair[0]) - } + // Use `os.Environ` to list all key/value pairs in the + // environment. This returns a slice of strings in the + // form `KEY=value`. You can `strings.Split` them to + // get the key and value. Here we print all the keys. + fmt.Println() + for _, e := range os.Environ() { + pair := strings.Split(e, "=") + fmt.Println(pair[0]) + } } diff --git a/examples/environment-variables/environment-variables.hash b/examples/environment-variables/environment-variables.hash index ef39f96..81632ac 100644 --- a/examples/environment-variables/environment-variables.hash +++ b/examples/environment-variables/environment-variables.hash @@ -1,2 +1,2 @@ 4d0832c5a1ddd4e95474791e8802c15452358214 -kfqLhpmEpw +CZJ4R_uu6Uu diff --git a/examples/epoch/epoch.go b/examples/epoch/epoch.go index 1e196f1..63cffbb 100644 --- a/examples/epoch/epoch.go +++ b/examples/epoch/epoch.go @@ -10,24 +10,24 @@ import "time" func main() { - // Use `time.Now` with `Unix` or `UnixNano` to get - // elapsed time since the Unix epoch in seconds or - // nanoseconds, respectively. - now := time.Now() - secs := now.Unix() - nanos := now.UnixNano() - fmt.Println(now) + // Use `time.Now` with `Unix` or `UnixNano` to get + // elapsed time since the Unix epoch in seconds or + // nanoseconds, respectively. + now := time.Now() + secs := now.Unix() + nanos := now.UnixNano() + fmt.Println(now) - // Note that there is no `UnixMillis`, so to get the - // milliseconds since epoch you'll need to manually - // divide from nanoseconds. - millis := nanos / 1000000 - fmt.Println(secs) - fmt.Println(millis) - fmt.Println(nanos) + // Note that there is no `UnixMillis`, so to get the + // milliseconds since epoch you'll need to manually + // divide from nanoseconds. + millis := nanos / 1000000 + fmt.Println(secs) + fmt.Println(millis) + fmt.Println(nanos) - // You can also convert integer seconds or nanoseconds - // since the epoch into the corresponding `time`. - fmt.Println(time.Unix(secs, 0)) - fmt.Println(time.Unix(0, nanos)) + // You can also convert integer seconds or nanoseconds + // since the epoch into the corresponding `time`. + fmt.Println(time.Unix(secs, 0)) + fmt.Println(time.Unix(0, nanos)) } diff --git a/examples/epoch/epoch.hash b/examples/epoch/epoch.hash index 66c1160..3899c7f 100644 --- a/examples/epoch/epoch.hash +++ b/examples/epoch/epoch.hash @@ -1,2 +1,2 @@ 61a498229c8878a97d729cfdd215e5f3960f87ac -GP_zEjhlWk +eN1Qv2ATB-C diff --git a/examples/errors/errors.go b/examples/errors/errors.go index 72a20b0..0b69bad 100644 --- a/examples/errors/errors.go +++ b/examples/errors/errors.go @@ -15,17 +15,17 @@ import "fmt" // By convention, errors are the last return value and // have type `error`, a built-in interface. func f1(arg int) (int, error) { - if arg == 42 { + if arg == 42 { - // `errors.New` constructs a basic `error` value - // with the given error message. - return -1, errors.New("can't work with 42") + // `errors.New` constructs a basic `error` value + // with the given error message. + return -1, errors.New("can't work with 42") - } + } - // A `nil` value in the error position indicates that - // there was no error. - return arg + 3, nil + // A `nil` value in the error position indicates that + // there was no error. + return arg + 3, nil } // It's possible to use custom types as `error`s by @@ -33,53 +33,53 @@ func f1(arg int) (int, error) { // variant on the example above that uses a custom type // to explicitly represent an argument error. type argError struct { - arg int - prob string + arg int + prob string } func (e *argError) Error() string { - return fmt.Sprintf("%d - %s", e.arg, e.prob) + return fmt.Sprintf("%d - %s", e.arg, e.prob) } func f2(arg int) (int, error) { - if arg == 42 { + if arg == 42 { - // In this case we use `&argError` syntax to build - // a new struct, supplying values for the two - // fields `arg` and `prob`. - return -1, &argError{arg, "can't work with it"} - } - return arg + 3, nil + // In this case we use `&argError` syntax to build + // a new struct, supplying values for the two + // fields `arg` and `prob`. + return -1, &argError{arg, "can't work with it"} + } + return arg + 3, nil } func main() { - // The two loops below test out each of our - // error-returning functions. Note that the use of an - // inline error check on the `if` line is a common - // idiom in Go code. - for _, i := range []int{7, 42} { - if r, e := f1(i); e != nil { - fmt.Println("f1 failed:", e) - } else { - fmt.Println("f1 worked:", r) - } - } - for _, i := range []int{7, 42} { - if r, e := f2(i); e != nil { - fmt.Println("f2 failed:", e) - } else { - fmt.Println("f2 worked:", r) - } - } + // The two loops below test out each of our + // error-returning functions. Note that the use of an + // inline error check on the `if` line is a common + // idiom in Go code. + for _, i := range []int{7, 42} { + if r, e := f1(i); e != nil { + fmt.Println("f1 failed:", e) + } else { + fmt.Println("f1 worked:", r) + } + } + for _, i := range []int{7, 42} { + if r, e := f2(i); e != nil { + fmt.Println("f2 failed:", e) + } else { + fmt.Println("f2 worked:", r) + } + } - // If you want to programmatically use the data in - // a custom error, you'll need to get the error as an - // instance of the custom error type via type - // assertion. - _, e := f2(42) - if ae, ok := e.(*argError); ok { - fmt.Println(ae.arg) - fmt.Println(ae.prob) - } + // If you want to programmatically use the data in + // a custom error, you'll need to get the error as an + // instance of the custom error type via type + // assertion. + _, e := f2(42) + if ae, ok := e.(*argError); ok { + fmt.Println(ae.arg) + fmt.Println(ae.prob) + } } diff --git a/examples/execing-processes/execing-processes.go b/examples/execing-processes/execing-processes.go index 5963fe5..b9caed1 100644 --- a/examples/execing-processes/execing-processes.go +++ b/examples/execing-processes/execing-processes.go @@ -16,33 +16,33 @@ import "os/exec" func main() { - // For our example we'll exec `ls`. Go requires an - // absolute path to the binary we want to execute, so - // we'll use `exec.LookPath` to find it (probably - // `/bin/ls`). - binary, lookErr := exec.LookPath("ls") - if lookErr != nil { - panic(lookErr) - } + // For our example we'll exec `ls`. Go requires an + // absolute path to the binary we want to execute, so + // we'll use `exec.LookPath` to find it (probably + // `/bin/ls`). + binary, lookErr := exec.LookPath("ls") + if lookErr != nil { + panic(lookErr) + } - // `Exec` requires arguments in slice form (as - // apposed to one big string). We'll give `ls` a few - // common arguments. Note that the first argument should - // be the program name. - args := []string{"ls", "-a", "-l", "-h"} + // `Exec` requires arguments in slice form (as + // apposed to one big string). We'll give `ls` a few + // common arguments. Note that the first argument should + // be the program name. + args := []string{"ls", "-a", "-l", "-h"} - // `Exec` also needs a set of [environment variables](environment-variables) - // to use. Here we just provide our current - // environment. - env := os.Environ() + // `Exec` also needs a set of [environment variables](environment-variables) + // to use. Here we just provide our current + // environment. + env := os.Environ() - // Here's the actual `syscall.Exec` call. If this call is - // successful, the execution of our process will end - // here and be replaced by the `/bin/ls -a -l -h` - // process. If there is an error we'll get a return - // value. - execErr := syscall.Exec(binary, args, env) - if execErr != nil { - panic(execErr) - } + // Here's the actual `syscall.Exec` call. If this call is + // successful, the execution of our process will end + // here and be replaced by the `/bin/ls -a -l -h` + // process. If there is an error we'll get a return + // value. + execErr := syscall.Exec(binary, args, env) + if execErr != nil { + panic(execErr) + } } diff --git a/examples/execing-processes/execing-processes.hash b/examples/execing-processes/execing-processes.hash index ae5a08a..4701404 100644 --- a/examples/execing-processes/execing-processes.hash +++ b/examples/execing-processes/execing-processes.hash @@ -1,2 +1,2 @@ b527bbb76a42dd4bae541b73a7377b7e83e79905 -neqdJ51KLN +bf11ADw-2Ho diff --git a/examples/exit/exit.go b/examples/exit/exit.go index 2563b86..d1e3646 100644 --- a/examples/exit/exit.go +++ b/examples/exit/exit.go @@ -8,12 +8,12 @@ import "os" func main() { - // `defer`s will _not_ be run when using `os.Exit`, so - // this `fmt.Println` will never be called. - defer fmt.Println("!") + // `defer`s will _not_ be run when using `os.Exit`, so + // this `fmt.Println` will never be called. + defer fmt.Println("!") - // Exit with status 3. - os.Exit(3) + // Exit with status 3. + os.Exit(3) } // Note that unlike e.g. C, Go does not use an integer diff --git a/examples/exit/exit.hash b/examples/exit/exit.hash index cb4c6a9..988b8f3 100644 --- a/examples/exit/exit.hash +++ b/examples/exit/exit.hash @@ -1,2 +1,2 @@ dc0bb3eaafa045d6aa05e88aff39322a1ccf822e -CDiAh9SXRM +vDaM0-MGJ_k diff --git a/examples/for/for.go b/examples/for/for.go index 1b1a2d7..7c4aa04 100644 --- a/examples/for/for.go +++ b/examples/for/for.go @@ -7,32 +7,32 @@ import "fmt" func main() { - // The most basic type, with a single condition. - i := 1 - for i <= 3 { - fmt.Println(i) - i = i + 1 - } + // The most basic type, with a single condition. + i := 1 + for i <= 3 { + fmt.Println(i) + i = i + 1 + } - // A classic initial/condition/after `for` loop. - for j := 7; j <= 9; j++ { - fmt.Println(j) - } + // A classic initial/condition/after `for` loop. + for j := 7; j <= 9; j++ { + fmt.Println(j) + } - // `for` without a condition will loop repeatedly - // until you `break` out of the loop or `return` from - // the enclosing function. - for { - fmt.Println("loop") - break - } + // `for` without a condition will loop repeatedly + // until you `break` out of the loop or `return` from + // the enclosing function. + for { + fmt.Println("loop") + break + } - // You can also `continue` to the next iteration of - // the loop. - for n := 0; n <= 5; n++ { - if n%2 == 0 { - continue - } - fmt.Println(n) - } + // You can also `continue` to the next iteration of + // the loop. + for n := 0; n <= 5; n++ { + if n%2 == 0 { + continue + } + fmt.Println(n) + } } diff --git a/examples/for/for.hash b/examples/for/for.hash index b2dfc13..7852dec 100644 --- a/examples/for/for.hash +++ b/examples/for/for.hash @@ -1,2 +1,2 @@ 33056d6b36f9894fb6359c9cf2ef8725bbdafa19 -KNLLSX4Io_ +lGYfUJwiGfi diff --git a/examples/functions/functions.go b/examples/functions/functions.go index 1895fc8..bf3e844 100644 --- a/examples/functions/functions.go +++ b/examples/functions/functions.go @@ -9,10 +9,10 @@ import "fmt" // their sum as an `int`. func plus(a int, b int) int { - // Go requires explicit returns, i.e. it won't - // automatically return the value of the last - // expression. - return a + b + // Go requires explicit returns, i.e. it won't + // automatically return the value of the last + // expression. + return a + b } // When you have multiple consecutive parameters of @@ -20,16 +20,16 @@ func plus(a int, b int) int { // like-typed parameters up to the final parameter that // declares the type. func plusPlus(a, b, c int) int { - return a + b + c + return a + b + c } func main() { - // Call a function just as you'd expect, with - // `name(args)`. - res := plus(1, 2) - fmt.Println("1+2 =", res) + // Call a function just as you'd expect, with + // `name(args)`. + res := plus(1, 2) + fmt.Println("1+2 =", res) - res = plusPlus(1, 2, 3) - fmt.Println("1+2+3 =", res) + res = plusPlus(1, 2, 3) + fmt.Println("1+2+3 =", res) } diff --git a/examples/functions/functions.hash b/examples/functions/functions.hash index 693c858..85d4e8f 100644 --- a/examples/functions/functions.hash +++ b/examples/functions/functions.hash @@ -1,2 +1,2 @@ ae669923c20e5ebf4a7b4b11b8fdf2972accf9e2 -9Nky-Dn49f +hzGUvK6iJNm diff --git a/examples/goroutines/goroutines.go b/examples/goroutines/goroutines.go index eed6ee2..c2bdde8 100644 --- a/examples/goroutines/goroutines.go +++ b/examples/goroutines/goroutines.go @@ -5,33 +5,33 @@ package main import "fmt" func f(from string) { - for i := 0; i < 3; i++ { - fmt.Println(from, ":", i) - } + for i := 0; i < 3; i++ { + fmt.Println(from, ":", i) + } } func main() { - // Suppose we have a function call `f(s)`. Here's how - // we'd call that in the usual way, running it - // synchronously. - f("direct") + // Suppose we have a function call `f(s)`. Here's how + // we'd call that in the usual way, running it + // synchronously. + f("direct") - // To invoke this function in a goroutine, use - // `go f(s)`. This new goroutine will execute - // concurrently with the calling one. - go f("goroutine") + // To invoke this function in a goroutine, use + // `go f(s)`. This new goroutine will execute + // concurrently with the calling one. + go f("goroutine") - // You can also start a goroutine for an anonymous - // function call. - go func(msg string) { - fmt.Println(msg) - }("going") + // You can also start a goroutine for an anonymous + // function call. + go func(msg string) { + fmt.Println(msg) + }("going") - // Our two function calls are running asynchronously in - // separate goroutines now, so execution falls through - // to here. This `Scanln` requires we press a key - // before the program exits. - fmt.Scanln() - fmt.Println("done") + // Our two function calls are running asynchronously in + // separate goroutines now, so execution falls through + // to here. This `Scanln` requires we press a key + // before the program exits. + fmt.Scanln() + fmt.Println("done") } diff --git a/examples/hello-world/hello-world.go b/examples/hello-world/hello-world.go index 18d23c2..4db5bfb 100644 --- a/examples/hello-world/hello-world.go +++ b/examples/hello-world/hello-world.go @@ -5,5 +5,5 @@ package main import "fmt" func main() { - fmt.Println("hello world") + fmt.Println("hello world") } diff --git a/examples/hello-world/hello-world.hash b/examples/hello-world/hello-world.hash index ced1ecb..df7b0e0 100644 --- a/examples/hello-world/hello-world.hash +++ b/examples/hello-world/hello-world.hash @@ -1,2 +1,2 @@ c98395a44701add5bf84e2f3a63e300fc1bc4bfe -2C7wwJ6nxG +mp1ENMU6ZYu diff --git a/examples/http-clients/http-clients.go b/examples/http-clients/http-clients.go index 56be133..7cd71ef 100644 --- a/examples/http-clients/http-clients.go +++ b/examples/http-clients/http-clients.go @@ -5,34 +5,34 @@ package main import ( - "bufio" - "fmt" - "net/http" + "bufio" + "fmt" + "net/http" ) func main() { - // Issue an HTTP GET request to a server. `http.Get` is a - // convenient shortcut around creating an `http.Client` - // object and calling its `Get` method; it uses the - // `http.DefaultClient` object which has useful default - // settings. - resp, err := http.Get("http://gobyexample.com") - if err != nil { - panic(err) - } - defer resp.Body.Close() + // Issue an HTTP GET request to a server. `http.Get` is a + // convenient shortcut around creating an `http.Client` + // object and calling its `Get` method; it uses the + // `http.DefaultClient` object which has useful default + // settings. + resp, err := http.Get("http://gobyexample.com") + if err != nil { + panic(err) + } + defer resp.Body.Close() - // Print the HTTP response status. - fmt.Println("Response status:", resp.Status) + // Print the HTTP response status. + fmt.Println("Response status:", resp.Status) - // Print the first 5 lines of the response body. - scanner := bufio.NewScanner(resp.Body) - for i := 0; scanner.Scan() && i < 5; i++ { - fmt.Println(scanner.Text()) - } + // Print the first 5 lines of the response body. + scanner := bufio.NewScanner(resp.Body) + for i := 0; scanner.Scan() && i < 5; i++ { + fmt.Println(scanner.Text()) + } - if err := scanner.Err(); err != nil { - panic(err) - } + if err := scanner.Err(); err != nil { + panic(err) + } } diff --git a/examples/if-else/if-else.go b/examples/if-else/if-else.go index 3ed9586..1f2a403 100644 --- a/examples/if-else/if-else.go +++ b/examples/if-else/if-else.go @@ -7,28 +7,28 @@ import "fmt" func main() { - // Here's a basic example. - if 7%2 == 0 { - fmt.Println("7 is even") - } else { - fmt.Println("7 is odd") - } + // Here's a basic example. + if 7%2 == 0 { + fmt.Println("7 is even") + } else { + fmt.Println("7 is odd") + } - // You can have an `if` statement without an else. - if 8%4 == 0 { - fmt.Println("8 is divisible by 4") - } + // You can have an `if` statement without an else. + if 8%4 == 0 { + fmt.Println("8 is divisible by 4") + } - // A statement can precede conditionals; any variables - // declared in this statement are available in all - // branches. - if num := 9; num < 0 { - fmt.Println(num, "is negative") - } else if num < 10 { - fmt.Println(num, "has 1 digit") - } else { - fmt.Println(num, "has multiple digits") - } + // A statement can precede conditionals; any variables + // declared in this statement are available in all + // branches. + if num := 9; num < 0 { + fmt.Println(num, "is negative") + } else if num < 10 { + fmt.Println(num, "has 1 digit") + } else { + fmt.Println(num, "has multiple digits") + } } // Note that you don't need parentheses around conditions diff --git a/examples/if-else/if-else.hash b/examples/if-else/if-else.hash index aefc6f9..844700f 100644 --- a/examples/if-else/if-else.hash +++ b/examples/if-else/if-else.hash @@ -1,2 +1,2 @@ 89b78f3378e1a574ddfd0260a0404a962852eff8 -g-aqMz0Ivf +p6-WKTqEks4 diff --git a/examples/interfaces/interfaces.go b/examples/interfaces/interfaces.go index 2df7234..2ac30bd 100644 --- a/examples/interfaces/interfaces.go +++ b/examples/interfaces/interfaces.go @@ -8,35 +8,35 @@ import "math" // Here's a basic interface for geometric shapes. type geometry interface { - area() float64 - perim() float64 + area() float64 + perim() float64 } // For our example we'll implement this interface on // `rect` and `circle` types. type rect struct { - width, height float64 + width, height float64 } type circle struct { - radius float64 + radius float64 } // To implement an interface in Go, we just need to // implement all the methods in the interface. Here we // implement `geometry` on `rect`s. func (r rect) area() float64 { - return r.width * r.height + return r.width * r.height } func (r rect) perim() float64 { - return 2*r.width + 2*r.height + return 2*r.width + 2*r.height } // The implementation for `circle`s. func (c circle) area() float64 { - return math.Pi * c.radius * c.radius + return math.Pi * c.radius * c.radius } func (c circle) perim() float64 { - return 2 * math.Pi * c.radius + return 2 * math.Pi * c.radius } // If a variable has an interface type, then we can call @@ -44,19 +44,19 @@ func (c circle) perim() float64 { // generic `measure` function taking advantage of this // to work on any `geometry`. func measure(g geometry) { - fmt.Println(g) - fmt.Println(g.area()) - fmt.Println(g.perim()) + fmt.Println(g) + fmt.Println(g.area()) + fmt.Println(g.perim()) } func main() { - r := rect{width: 3, height: 4} - c := circle{radius: 5} + r := rect{width: 3, height: 4} + c := circle{radius: 5} - // The `circle` and `rect` struct types both - // implement the `geometry` interface so we can use - // instances of - // these structs as arguments to `measure`. - measure(r) - measure(c) + // The `circle` and `rect` struct types both + // implement the `geometry` interface so we can use + // instances of + // these structs as arguments to `measure`. + measure(r) + measure(c) } diff --git a/examples/interfaces/interfaces.hash b/examples/interfaces/interfaces.hash index aa81b50..d9daece 100644 --- a/examples/interfaces/interfaces.hash +++ b/examples/interfaces/interfaces.hash @@ -1,2 +1,2 @@ 3547b935d1e0322c0fb696726c27cae53a275e0a -313UebA3rD +0EwsqIn3TTi diff --git a/examples/json/json.go b/examples/json/json.go index ff777a1..62bc1ea 100644 --- a/examples/json/json.go +++ b/examples/json/json.go @@ -11,109 +11,109 @@ import "os" // We'll use these two structs to demonstrate encoding and // decoding of custom types below. type response1 struct { - Page int - Fruits []string + Page int + Fruits []string } type response2 struct { - Page int `json:"page"` - Fruits []string `json:"fruits"` + Page int `json:"page"` + Fruits []string `json:"fruits"` } func main() { - // First we'll look at encoding basic data types to - // JSON strings. Here are some examples for atomic - // values. - bolB, _ := json.Marshal(true) - fmt.Println(string(bolB)) + // First we'll look at encoding basic data types to + // JSON strings. Here are some examples for atomic + // values. + bolB, _ := json.Marshal(true) + fmt.Println(string(bolB)) - intB, _ := json.Marshal(1) - fmt.Println(string(intB)) + intB, _ := json.Marshal(1) + fmt.Println(string(intB)) - fltB, _ := json.Marshal(2.34) - fmt.Println(string(fltB)) + fltB, _ := json.Marshal(2.34) + fmt.Println(string(fltB)) - strB, _ := json.Marshal("gopher") - fmt.Println(string(strB)) + strB, _ := json.Marshal("gopher") + fmt.Println(string(strB)) - // And here are some for slices and maps, which encode - // to JSON arrays and objects as you'd expect. - slcD := []string{"apple", "peach", "pear"} - slcB, _ := json.Marshal(slcD) - fmt.Println(string(slcB)) + // And here are some for slices and maps, which encode + // to JSON arrays and objects as you'd expect. + slcD := []string{"apple", "peach", "pear"} + slcB, _ := json.Marshal(slcD) + fmt.Println(string(slcB)) - mapD := map[string]int{"apple": 5, "lettuce": 7} - mapB, _ := json.Marshal(mapD) - fmt.Println(string(mapB)) + mapD := map[string]int{"apple": 5, "lettuce": 7} + mapB, _ := json.Marshal(mapD) + fmt.Println(string(mapB)) - // The JSON package can automatically encode your - // custom data types. It will only include exported - // fields in the encoded output and will by default - // use those names as the JSON keys. - res1D := &response1{ - Page: 1, - Fruits: []string{"apple", "peach", "pear"}} - res1B, _ := json.Marshal(res1D) - fmt.Println(string(res1B)) + // The JSON package can automatically encode your + // custom data types. It will only include exported + // fields in the encoded output and will by default + // use those names as the JSON keys. + res1D := &response1{ + Page: 1, + Fruits: []string{"apple", "peach", "pear"}} + res1B, _ := json.Marshal(res1D) + fmt.Println(string(res1B)) - // You can use tags on struct field declarations - // to customize the encoded JSON key names. Check the - // definition of `response2` above to see an example - // of such tags. - res2D := &response2{ - Page: 1, - Fruits: []string{"apple", "peach", "pear"}} - res2B, _ := json.Marshal(res2D) - fmt.Println(string(res2B)) + // You can use tags on struct field declarations + // to customize the encoded JSON key names. Check the + // definition of `response2` above to see an example + // of such tags. + res2D := &response2{ + Page: 1, + Fruits: []string{"apple", "peach", "pear"}} + res2B, _ := json.Marshal(res2D) + fmt.Println(string(res2B)) - // Now let's look at decoding JSON data into Go - // values. Here's an example for a generic data - // structure. - byt := []byte(`{"num":6.13,"strs":["a","b"]}`) + // Now let's look at decoding JSON data into Go + // values. Here's an example for a generic data + // structure. + byt := []byte(`{"num":6.13,"strs":["a","b"]}`) - // We need to provide a variable where the JSON - // package can put the decoded data. This - // `map[string]interface{}` will hold a map of strings - // to arbitrary data types. - var dat map[string]interface{} + // We need to provide a variable where the JSON + // package can put the decoded data. This + // `map[string]interface{}` will hold a map of strings + // to arbitrary data types. + var dat map[string]interface{} - // Here's the actual decoding, and a check for - // associated errors. - if err := json.Unmarshal(byt, &dat); err != nil { - panic(err) - } - fmt.Println(dat) + // Here's the actual decoding, and a check for + // associated errors. + if err := json.Unmarshal(byt, &dat); err != nil { + panic(err) + } + fmt.Println(dat) - // In order to use the values in the decoded map, - // we'll need to convert them to their appropriate type. - // For example here we convert the value in `num` to - // the expected `float64` type. - num := dat["num"].(float64) - fmt.Println(num) + // In order to use the values in the decoded map, + // we'll need to convert them to their appropriate type. + // For example here we convert the value in `num` to + // the expected `float64` type. + num := dat["num"].(float64) + fmt.Println(num) - // Accessing nested data requires a series of - // conversions. - strs := dat["strs"].([]interface{}) - str1 := strs[0].(string) - fmt.Println(str1) + // Accessing nested data requires a series of + // conversions. + strs := dat["strs"].([]interface{}) + str1 := strs[0].(string) + fmt.Println(str1) - // We can also decode JSON into custom data types. - // This has the advantages of adding additional - // type-safety to our programs and eliminating the - // need for type assertions when accessing the decoded - // data. - str := `{"page": 1, "fruits": ["apple", "peach"]}` - res := response2{} - json.Unmarshal([]byte(str), &res) - fmt.Println(res) - fmt.Println(res.Fruits[0]) + // We can also decode JSON into custom data types. + // This has the advantages of adding additional + // type-safety to our programs and eliminating the + // need for type assertions when accessing the decoded + // data. + str := `{"page": 1, "fruits": ["apple", "peach"]}` + res := response2{} + json.Unmarshal([]byte(str), &res) + fmt.Println(res) + fmt.Println(res.Fruits[0]) - // In the examples above we always used bytes and - // strings as intermediates between the data and - // JSON representation on standard out. We can also - // stream JSON encodings directly to `os.Writer`s like - // `os.Stdout` or even HTTP response bodies. - enc := json.NewEncoder(os.Stdout) - d := map[string]int{"apple": 5, "lettuce": 7} - enc.Encode(d) + // In the examples above we always used bytes and + // strings as intermediates between the data and + // JSON representation on standard out. We can also + // stream JSON encodings directly to `os.Writer`s like + // `os.Stdout` or even HTTP response bodies. + enc := json.NewEncoder(os.Stdout) + d := map[string]int{"apple": 5, "lettuce": 7} + enc.Encode(d) } diff --git a/examples/line-filters/line-filters.go b/examples/line-filters/line-filters.go index 25b13da..abcdf96 100644 --- a/examples/line-filters/line-filters.go +++ b/examples/line-filters/line-filters.go @@ -9,33 +9,33 @@ package main import ( - "bufio" - "fmt" - "os" - "strings" + "bufio" + "fmt" + "os" + "strings" ) func main() { - // Wrapping the unbuffered `os.Stdin` with a buffered - // scanner gives us a convenient `Scan` method that - // advances the scanner to the next token; which is - // the next line in the default scanner. - scanner := bufio.NewScanner(os.Stdin) + // Wrapping the unbuffered `os.Stdin` with a buffered + // scanner gives us a convenient `Scan` method that + // advances the scanner to the next token; which is + // the next line in the default scanner. + scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - // `Text` returns the current token, here the next line, - // from the input. - ucl := strings.ToUpper(scanner.Text()) + for scanner.Scan() { + // `Text` returns the current token, here the next line, + // from the input. + ucl := strings.ToUpper(scanner.Text()) - // Write out the uppercased line. - fmt.Println(ucl) - } + // Write out the uppercased line. + fmt.Println(ucl) + } - // Check for errors during `Scan`. End of file is - // expected and not reported by `Scan` as an error. - if err := scanner.Err(); err != nil { - fmt.Fprintln(os.Stderr, "error:", err) - os.Exit(1) - } + // Check for errors during `Scan`. End of file is + // expected and not reported by `Scan` as an error. + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "error:", err) + os.Exit(1) + } } diff --git a/examples/line-filters/line-filters.hash b/examples/line-filters/line-filters.hash index d36a15d..d62fbff 100644 --- a/examples/line-filters/line-filters.hash +++ b/examples/line-filters/line-filters.hash @@ -1,2 +1,2 @@ 87f4a67edf741979f8ff6da85947aa177547f9ef -mpYwOHj2ma +hnaOIaQAjKF diff --git a/examples/maps/maps.go b/examples/maps/maps.go index 2ed1363..3346270 100644 --- a/examples/maps/maps.go +++ b/examples/maps/maps.go @@ -7,44 +7,44 @@ import "fmt" func main() { - // To create an empty map, use the builtin `make`: - // `make(map[key-type]val-type)`. - m := make(map[string]int) + // To create an empty map, use the builtin `make`: + // `make(map[key-type]val-type)`. + m := make(map[string]int) - // Set key/value pairs using typical `name[key] = val` - // syntax. - m["k1"] = 7 - m["k2"] = 13 + // Set key/value pairs using typical `name[key] = val` + // syntax. + m["k1"] = 7 + m["k2"] = 13 - // Printing a map with e.g. `fmt.Println` will show all of - // its key/value pairs. - fmt.Println("map:", m) + // Printing a map with e.g. `fmt.Println` will show all of + // its key/value pairs. + fmt.Println("map:", m) - // Get a value for a key with `name[key]`. - v1 := m["k1"] - fmt.Println("v1: ", v1) + // Get a value for a key with `name[key]`. + v1 := m["k1"] + fmt.Println("v1: ", v1) - // The builtin `len` returns the number of key/value - // pairs when called on a map. - fmt.Println("len:", len(m)) + // The builtin `len` returns the number of key/value + // pairs when called on a map. + fmt.Println("len:", len(m)) - // The builtin `delete` removes key/value pairs from - // a map. - delete(m, "k2") - fmt.Println("map:", m) + // The builtin `delete` removes key/value pairs from + // a map. + delete(m, "k2") + fmt.Println("map:", m) - // The optional second return value when getting a - // value from a map indicates if the key was present - // in the map. This can be used to disambiguate - // between missing keys and keys with zero values - // like `0` or `""`. Here we didn't need the value - // itself, so we ignored it with the _blank identifier_ - // `_`. - _, prs := m["k2"] - fmt.Println("prs:", prs) + // The optional second return value when getting a + // value from a map indicates if the key was present + // in the map. This can be used to disambiguate + // between missing keys and keys with zero values + // like `0` or `""`. Here we didn't need the value + // itself, so we ignored it with the _blank identifier_ + // `_`. + _, prs := m["k2"] + fmt.Println("prs:", prs) - // You can also declare and initialize a new map in - // the same line with this syntax. - n := map[string]int{"foo": 1, "bar": 2} - fmt.Println("map:", n) + // You can also declare and initialize a new map in + // the same line with this syntax. + n := map[string]int{"foo": 1, "bar": 2} + fmt.Println("map:", n) } diff --git a/examples/methods/methods.go b/examples/methods/methods.go index 0f006a4..e56cb6f 100644 --- a/examples/methods/methods.go +++ b/examples/methods/methods.go @@ -5,33 +5,33 @@ package main import "fmt" type rect struct { - width, height int + width, height int } // This `area` method has a _receiver type_ of `*rect`. func (r *rect) area() int { - return r.width * r.height + return r.width * r.height } // Methods can be defined for either pointer or value // receiver types. Here's an example of a value receiver. func (r rect) perim() int { - return 2*r.width + 2*r.height + return 2*r.width + 2*r.height } func main() { - r := rect{width: 10, height: 5} + r := rect{width: 10, height: 5} - // Here we call the 2 methods defined for our struct. - fmt.Println("area: ", r.area()) - fmt.Println("perim:", r.perim()) + // Here we call the 2 methods defined for our struct. + fmt.Println("area: ", r.area()) + fmt.Println("perim:", r.perim()) - // Go automatically handles conversion between values - // and pointers for method calls. You may want to use - // a pointer receiver type to avoid copying on method - // calls or to allow the method to mutate the - // receiving struct. - rp := &r - fmt.Println("area: ", rp.area()) - fmt.Println("perim:", rp.perim()) + // Go automatically handles conversion between values + // and pointers for method calls. You may want to use + // a pointer receiver type to avoid copying on method + // calls or to allow the method to mutate the + // receiving struct. + rp := &r + fmt.Println("area: ", rp.area()) + fmt.Println("perim:", rp.perim()) } diff --git a/examples/methods/methods.hash b/examples/methods/methods.hash index bcb0099..00c7c28 100644 --- a/examples/methods/methods.hash +++ b/examples/methods/methods.hash @@ -1,2 +1,2 @@ 24cfb9ad45e43c2d49163149bc55925a4e1b3c7a -254m_9Yjwa +ffMb0txGnYB diff --git a/examples/multiple-return-values/multiple-return-values.go b/examples/multiple-return-values/multiple-return-values.go index 9b970a6..cb541c4 100644 --- a/examples/multiple-return-values/multiple-return-values.go +++ b/examples/multiple-return-values/multiple-return-values.go @@ -9,19 +9,19 @@ import "fmt" // The `(int, int)` in this function signature shows that // the function returns 2 `int`s. func vals() (int, int) { - return 3, 7 + return 3, 7 } func main() { - // Here we use the 2 different return values from the - // call with _multiple assignment_. - a, b := vals() - fmt.Println(a) - fmt.Println(b) + // Here we use the 2 different return values from the + // call with _multiple assignment_. + a, b := vals() + fmt.Println(a) + fmt.Println(b) - // If you only want a subset of the returned values, - // use the blank identifier `_`. - _, c := vals() - fmt.Println(c) + // If you only want a subset of the returned values, + // use the blank identifier `_`. + _, c := vals() + fmt.Println(c) } diff --git a/examples/multiple-return-values/multiple-return-values.hash b/examples/multiple-return-values/multiple-return-values.hash index 0e13a88..73f9fa8 100644 --- a/examples/multiple-return-values/multiple-return-values.hash +++ b/examples/multiple-return-values/multiple-return-values.hash @@ -1,2 +1,2 @@ 5063ce3d3c70c6bd70f4b709de24bb93d0f24e0c -chwFmr5dG1 +FZoIB5LXQGZ diff --git a/examples/mutexes/mutexes.go b/examples/mutexes/mutexes.go index 1e7f3da..79b0c31 100644 --- a/examples/mutexes/mutexes.go +++ b/examples/mutexes/mutexes.go @@ -6,80 +6,80 @@ package main import ( - "fmt" - "math/rand" - "sync" - "sync/atomic" - "time" + "fmt" + "math/rand" + "sync" + "sync/atomic" + "time" ) func main() { - // For our example the `state` will be a map. - var state = make(map[int]int) + // For our example the `state` will be a map. + var state = make(map[int]int) - // This `mutex` will synchronize access to `state`. - var mutex = &sync.Mutex{} + // This `mutex` will synchronize access to `state`. + var mutex = &sync.Mutex{} - // We'll keep track of how many read and write - // operations we do. - var readOps uint64 - var writeOps uint64 + // We'll keep track of how many read and write + // operations we do. + var readOps uint64 + var writeOps uint64 - // Here we start 100 goroutines to execute repeated - // reads against the state, once per millisecond in - // each goroutine. - for r := 0; r < 100; r++ { - go func() { - total := 0 - for { + // Here we start 100 goroutines to execute repeated + // reads against the state, once per millisecond in + // each goroutine. + for r := 0; r < 100; r++ { + go func() { + total := 0 + for { - // For each read we pick a key to access, - // `Lock()` the `mutex` to ensure - // exclusive access to the `state`, read - // the value at the chosen key, - // `Unlock()` the mutex, and increment - // the `readOps` count. - key := rand.Intn(5) - mutex.Lock() - total += state[key] - mutex.Unlock() - atomic.AddUint64(&readOps, 1) + // For each read we pick a key to access, + // `Lock()` the `mutex` to ensure + // exclusive access to the `state`, read + // the value at the chosen key, + // `Unlock()` the mutex, and increment + // the `readOps` count. + key := rand.Intn(5) + mutex.Lock() + total += state[key] + mutex.Unlock() + atomic.AddUint64(&readOps, 1) - // Wait a bit between reads. - time.Sleep(time.Millisecond) - } - }() - } + // Wait a bit between reads. + time.Sleep(time.Millisecond) + } + }() + } - // We'll also start 10 goroutines to simulate writes, - // using the same pattern we did for reads. - for w := 0; w < 10; w++ { - go func() { - for { - key := rand.Intn(5) - val := rand.Intn(100) - mutex.Lock() - state[key] = val - mutex.Unlock() - atomic.AddUint64(&writeOps, 1) - time.Sleep(time.Millisecond) - } - }() - } + // We'll also start 10 goroutines to simulate writes, + // using the same pattern we did for reads. + for w := 0; w < 10; w++ { + go func() { + for { + key := rand.Intn(5) + val := rand.Intn(100) + mutex.Lock() + state[key] = val + mutex.Unlock() + atomic.AddUint64(&writeOps, 1) + time.Sleep(time.Millisecond) + } + }() + } - // Let the 10 goroutines work on the `state` and - // `mutex` for a second. - time.Sleep(time.Second) + // Let the 10 goroutines work on the `state` and + // `mutex` for a second. + time.Sleep(time.Second) - // Take and report final operation counts. - readOpsFinal := atomic.LoadUint64(&readOps) - fmt.Println("readOps:", readOpsFinal) - writeOpsFinal := atomic.LoadUint64(&writeOps) - fmt.Println("writeOps:", writeOpsFinal) + // Take and report final operation counts. + readOpsFinal := atomic.LoadUint64(&readOps) + fmt.Println("readOps:", readOpsFinal) + writeOpsFinal := atomic.LoadUint64(&writeOps) + fmt.Println("writeOps:", writeOpsFinal) - // With a final lock of `state`, show how it ended up. - mutex.Lock() - fmt.Println("state:", state) - mutex.Unlock() + // With a final lock of `state`, show how it ended up. + mutex.Lock() + fmt.Println("state:", state) + mutex.Unlock() } diff --git a/examples/non-blocking-channel-operations/non-blocking-channel-operations.go b/examples/non-blocking-channel-operations/non-blocking-channel-operations.go index dfd0516..2429da1 100644 --- a/examples/non-blocking-channel-operations/non-blocking-channel-operations.go +++ b/examples/non-blocking-channel-operations/non-blocking-channel-operations.go @@ -8,42 +8,42 @@ package main import "fmt" func main() { - messages := make(chan string) - signals := make(chan bool) + messages := make(chan string) + signals := make(chan bool) - // Here's a non-blocking receive. If a value is - // available on `messages` then `select` will take - // the `<-messages` `case` with that value. If not - // it will immediately take the `default` case. - select { - case msg := <-messages: - fmt.Println("received message", msg) - default: - fmt.Println("no message received") - } + // Here's a non-blocking receive. If a value is + // available on `messages` then `select` will take + // the `<-messages` `case` with that value. If not + // it will immediately take the `default` case. + select { + case msg := <-messages: + fmt.Println("received message", msg) + default: + fmt.Println("no message received") + } - // A non-blocking send works similarly. Here `msg` - // cannot be sent to the `messages` channel, because - // the channel has no buffer and there is no receiver. - // Therefore the `default` case is selected. - msg := "hi" - select { - case messages <- msg: - fmt.Println("sent message", msg) - default: - fmt.Println("no message sent") - } + // A non-blocking send works similarly. Here `msg` + // cannot be sent to the `messages` channel, because + // the channel has no buffer and there is no receiver. + // Therefore the `default` case is selected. + msg := "hi" + select { + case messages <- msg: + fmt.Println("sent message", msg) + default: + fmt.Println("no message sent") + } - // We can use multiple `case`s above the `default` - // clause to implement a multi-way non-blocking - // select. Here we attempt non-blocking receives - // on both `messages` and `signals`. - select { - case msg := <-messages: - fmt.Println("received message", msg) - case sig := <-signals: - fmt.Println("received signal", sig) - default: - fmt.Println("no activity") - } + // We can use multiple `case`s above the `default` + // clause to implement a multi-way non-blocking + // select. Here we attempt non-blocking receives + // on both `messages` and `signals`. + select { + case msg := <-messages: + fmt.Println("received message", msg) + case sig := <-signals: + fmt.Println("received signal", sig) + default: + fmt.Println("no activity") + } } diff --git a/examples/number-parsing/number-parsing.go b/examples/number-parsing/number-parsing.go index c7751cf..15a03bf 100644 --- a/examples/number-parsing/number-parsing.go +++ b/examples/number-parsing/number-parsing.go @@ -10,31 +10,31 @@ import "fmt" func main() { - // With `ParseFloat`, this `64` tells how many bits of - // precision to parse. - f, _ := strconv.ParseFloat("1.234", 64) - fmt.Println(f) + // With `ParseFloat`, this `64` tells how many bits of + // precision to parse. + f, _ := strconv.ParseFloat("1.234", 64) + fmt.Println(f) - // For `ParseInt`, the `0` means infer the base from - // the string. `64` requires that the result fit in 64 - // bits. - i, _ := strconv.ParseInt("123", 0, 64) - fmt.Println(i) + // For `ParseInt`, the `0` means infer the base from + // the string. `64` requires that the result fit in 64 + // bits. + i, _ := strconv.ParseInt("123", 0, 64) + fmt.Println(i) - // `ParseInt` will recognize hex-formatted numbers. - d, _ := strconv.ParseInt("0x1c8", 0, 64) - fmt.Println(d) + // `ParseInt` will recognize hex-formatted numbers. + d, _ := strconv.ParseInt("0x1c8", 0, 64) + fmt.Println(d) - // A `ParseUint` is also available. - u, _ := strconv.ParseUint("789", 0, 64) - fmt.Println(u) + // A `ParseUint` is also available. + u, _ := strconv.ParseUint("789", 0, 64) + fmt.Println(u) - // `Atoi` is a convenience function for basic base-10 - // `int` parsing. - k, _ := strconv.Atoi("135") - fmt.Println(k) + // `Atoi` is a convenience function for basic base-10 + // `int` parsing. + k, _ := strconv.Atoi("135") + fmt.Println(k) - // Parse functions return an error on bad input. - _, e := strconv.Atoi("wat") - fmt.Println(e) + // Parse functions return an error on bad input. + _, e := strconv.Atoi("wat") + fmt.Println(e) } diff --git a/examples/number-parsing/number-parsing.hash b/examples/number-parsing/number-parsing.hash index 714860f..3249903 100644 --- a/examples/number-parsing/number-parsing.hash +++ b/examples/number-parsing/number-parsing.hash @@ -1,2 +1,2 @@ 0d2155e9863a73c098d44637e92403d7f5e8e965 -N90EppECFk +NZh4LjhguvN diff --git a/examples/panic/panic.go b/examples/panic/panic.go index c06f3b6..27e72f0 100644 --- a/examples/panic/panic.go +++ b/examples/panic/panic.go @@ -9,17 +9,17 @@ import "os" func main() { - // We'll use panic throughout this site to check for - // unexpected errors. This is the only program on the - // site designed to panic. - panic("a problem") + // We'll use panic throughout this site to check for + // unexpected errors. This is the only program on the + // site designed to panic. + panic("a problem") - // A common use of panic is to abort if a function - // returns an error value that we don't know how to - // (or want to) handle. Here's an example of - // `panic`king if we get an unexpected error when creating a new file. - _, err := os.Create("/tmp/file") - if err != nil { - panic(err) - } + // A common use of panic is to abort if a function + // returns an error value that we don't know how to + // (or want to) handle. Here's an example of + // `panic`king if we get an unexpected error when creating a new file. + _, err := os.Create("/tmp/file") + if err != nil { + panic(err) + } } diff --git a/examples/panic/panic.hash b/examples/panic/panic.hash index 5c411f6..bd32ff3 100644 --- a/examples/panic/panic.hash +++ b/examples/panic/panic.hash @@ -1,2 +1,2 @@ 91639bbcfcc6ed088295a9ee6b1c36ab35ae402a -c86oXzfQOt +91HXbZZZopt diff --git a/examples/pointers/pointers.go b/examples/pointers/pointers.go index bb64a38..5574997 100644 --- a/examples/pointers/pointers.go +++ b/examples/pointers/pointers.go @@ -12,7 +12,7 @@ import "fmt" // value. `zeroval` will get a copy of `ival` distinct // from the one in the calling function. func zeroval(ival int) { - ival = 0 + ival = 0 } // `zeroptr` in contrast has an `*int` parameter, meaning @@ -22,21 +22,21 @@ func zeroval(ival int) { // Assigning a value to a dereferenced pointer changes the // value at the referenced address. func zeroptr(iptr *int) { - *iptr = 0 + *iptr = 0 } func main() { - i := 1 - fmt.Println("initial:", i) + i := 1 + fmt.Println("initial:", i) - zeroval(i) - fmt.Println("zeroval:", i) + zeroval(i) + fmt.Println("zeroval:", i) - // The `&i` syntax gives the memory address of `i`, - // i.e. a pointer to `i`. - zeroptr(&i) - fmt.Println("zeroptr:", i) + // The `&i` syntax gives the memory address of `i`, + // i.e. a pointer to `i`. + zeroptr(&i) + fmt.Println("zeroptr:", i) - // Pointers can be printed too. - fmt.Println("pointer:", &i) + // Pointers can be printed too. + fmt.Println("pointer:", &i) } diff --git a/examples/pointers/pointers.hash b/examples/pointers/pointers.hash index 6cb7efd..a0c5985 100644 --- a/examples/pointers/pointers.hash +++ b/examples/pointers/pointers.hash @@ -1,2 +1,2 @@ 85cff3345d2f22b65a5d54eb8f7aa8f508f27887 -KdE4TBbUL2 +fnQkHp4hriG diff --git a/examples/random-numbers/random-numbers.go b/examples/random-numbers/random-numbers.go index 34b065c..b27c200 100644 --- a/examples/random-numbers/random-numbers.go +++ b/examples/random-numbers/random-numbers.go @@ -10,45 +10,45 @@ import "math/rand" func main() { - // For example, `rand.Intn` returns a random `int` n, - // `0 <= n < 100`. - fmt.Print(rand.Intn(100), ",") - fmt.Print(rand.Intn(100)) - fmt.Println() + // For example, `rand.Intn` returns a random `int` n, + // `0 <= n < 100`. + fmt.Print(rand.Intn(100), ",") + fmt.Print(rand.Intn(100)) + fmt.Println() - // `rand.Float64` returns a `float64` `f`, - // `0.0 <= f < 1.0`. - fmt.Println(rand.Float64()) + // `rand.Float64` returns a `float64` `f`, + // `0.0 <= f < 1.0`. + fmt.Println(rand.Float64()) - // This can be used to generate random floats in - // other ranges, for example `5.0 <= f' < 10.0`. - fmt.Print((rand.Float64()*5)+5, ",") - fmt.Print((rand.Float64() * 5) + 5) - fmt.Println() + // This can be used to generate random floats in + // other ranges, for example `5.0 <= f' < 10.0`. + fmt.Print((rand.Float64()*5)+5, ",") + fmt.Print((rand.Float64() * 5) + 5) + fmt.Println() - // The default number generator is deterministic, so it'll - // produce the same sequence of numbers each time by default. - // To produce varying sequences, give it a seed that changes. - // Note that this is not safe to use for random numbers you - // intend to be secret, use `crypto/rand` for those. - s1 := rand.NewSource(time.Now().UnixNano()) - r1 := rand.New(s1) + // The default number generator is deterministic, so it'll + // produce the same sequence of numbers each time by default. + // To produce varying sequences, give it a seed that changes. + // Note that this is not safe to use for random numbers you + // intend to be secret, use `crypto/rand` for those. + s1 := rand.NewSource(time.Now().UnixNano()) + r1 := rand.New(s1) - // Call the resulting `rand.Rand` just like the - // functions on the `rand` package. - fmt.Print(r1.Intn(100), ",") - fmt.Print(r1.Intn(100)) - fmt.Println() + // Call the resulting `rand.Rand` just like the + // functions on the `rand` package. + fmt.Print(r1.Intn(100), ",") + fmt.Print(r1.Intn(100)) + fmt.Println() - // If you seed a source with the same number, it - // produces the same sequence of random numbers. - s2 := rand.NewSource(42) - r2 := rand.New(s2) - fmt.Print(r2.Intn(100), ",") - fmt.Print(r2.Intn(100)) - fmt.Println() - s3 := rand.NewSource(42) - r3 := rand.New(s3) - fmt.Print(r3.Intn(100), ",") - fmt.Print(r3.Intn(100)) + // If you seed a source with the same number, it + // produces the same sequence of random numbers. + s2 := rand.NewSource(42) + r2 := rand.New(s2) + fmt.Print(r2.Intn(100), ",") + fmt.Print(r2.Intn(100)) + fmt.Println() + s3 := rand.NewSource(42) + r3 := rand.New(s3) + fmt.Print(r3.Intn(100), ",") + fmt.Print(r3.Intn(100)) } diff --git a/examples/random-numbers/random-numbers.hash b/examples/random-numbers/random-numbers.hash index fa0ec46..87959ee 100644 --- a/examples/random-numbers/random-numbers.hash +++ b/examples/random-numbers/random-numbers.hash @@ -1,2 +1,2 @@ 8e97de760147b061dd09939db294c892211b6b80 -ZdFpbahgC1 +jiJaIjxL2sP diff --git a/examples/range-over-channels/range-over-channels.go b/examples/range-over-channels/range-over-channels.go index 05bb2eb..d8aa729 100644 --- a/examples/range-over-channels/range-over-channels.go +++ b/examples/range-over-channels/range-over-channels.go @@ -9,17 +9,17 @@ import "fmt" func main() { - // We'll iterate over 2 values in the `queue` channel. - queue := make(chan string, 2) - queue <- "one" - queue <- "two" - close(queue) + // We'll iterate over 2 values in the `queue` channel. + queue := make(chan string, 2) + queue <- "one" + queue <- "two" + close(queue) - // This `range` iterates over each element as it's - // received from `queue`. Because we `close`d the - // channel above, the iteration terminates after - // receiving the 2 elements. - for elem := range queue { - fmt.Println(elem) - } + // This `range` iterates over each element as it's + // received from `queue`. Because we `close`d the + // channel above, the iteration terminates after + // receiving the 2 elements. + for elem := range queue { + fmt.Println(elem) + } } diff --git a/examples/range-over-channels/range-over-channels.hash b/examples/range-over-channels/range-over-channels.hash index fa6f095..f0ffe62 100644 --- a/examples/range-over-channels/range-over-channels.hash +++ b/examples/range-over-channels/range-over-channels.hash @@ -1,2 +1,2 @@ 8b5d8a77e84c34771c5b14af014ecef3f88b2a6c -I63ge2ISDs +QnARPm-ddFB diff --git a/examples/range/range.go b/examples/range/range.go index 7ae540d..011af67 100644 --- a/examples/range/range.go +++ b/examples/range/range.go @@ -8,41 +8,41 @@ import "fmt" func main() { - // Here we use `range` to sum the numbers in a slice. - // Arrays work like this too. - nums := []int{2, 3, 4} - sum := 0 - for _, num := range nums { - sum += num - } - fmt.Println("sum:", sum) + // Here we use `range` to sum the numbers in a slice. + // Arrays work like this too. + nums := []int{2, 3, 4} + sum := 0 + for _, num := range nums { + sum += num + } + fmt.Println("sum:", sum) - // `range` on arrays and slices provides both the - // index and value for each entry. Above we didn't - // need the index, so we ignored it with the - // blank identifier `_`. Sometimes we actually want - // the indexes though. - for i, num := range nums { - if num == 3 { - fmt.Println("index:", i) - } - } + // `range` on arrays and slices provides both the + // index and value for each entry. Above we didn't + // need the index, so we ignored it with the + // blank identifier `_`. Sometimes we actually want + // the indexes though. + for i, num := range nums { + if num == 3 { + fmt.Println("index:", i) + } + } - // `range` on map iterates over key/value pairs. - kvs := map[string]string{"a": "apple", "b": "banana"} - for k, v := range kvs { - fmt.Printf("%s -> %s\n", k, v) - } + // `range` on map iterates over key/value pairs. + kvs := map[string]string{"a": "apple", "b": "banana"} + for k, v := range kvs { + fmt.Printf("%s -> %s\n", k, v) + } - // `range` can also iterate over just the keys of a map. - for k := range kvs { - fmt.Println("key:", k) - } + // `range` can also iterate over just the keys of a map. + for k := range kvs { + fmt.Println("key:", k) + } - // `range` on strings iterates over Unicode code - // points. The first value is the starting byte index - // of the `rune` and the second the `rune` itself. - for i, c := range "go" { - fmt.Println(i, c) - } + // `range` on strings iterates over Unicode code + // points. The first value is the starting byte index + // of the `rune` and the second the `rune` itself. + for i, c := range "go" { + fmt.Println(i, c) + } } diff --git a/examples/range/range.hash b/examples/range/range.hash index 571157c..2f8d0da 100644 --- a/examples/range/range.hash +++ b/examples/range/range.hash @@ -1,2 +1,2 @@ ebe328a57f3d34708709ca99d3304af1733592d9 -SkL_AS-1Jd +JTY1VAUjfBw diff --git a/examples/rate-limiting/rate-limiting.go b/examples/rate-limiting/rate-limiting.go index f5eea19..175bbcc 100644 --- a/examples/rate-limiting/rate-limiting.go +++ b/examples/rate-limiting/rate-limiting.go @@ -11,59 +11,59 @@ import "fmt" func main() { - // First we'll look at basic rate limiting. Suppose - // we want to limit our handling of incoming requests. - // We'll serve these requests off a channel of the - // same name. - requests := make(chan int, 5) - for i := 1; i <= 5; i++ { - requests <- i - } - close(requests) + // First we'll look at basic rate limiting. Suppose + // we want to limit our handling of incoming requests. + // We'll serve these requests off a channel of the + // same name. + requests := make(chan int, 5) + for i := 1; i <= 5; i++ { + requests <- i + } + close(requests) - // This `limiter` channel will receive a value - // every 200 milliseconds. This is the regulator in - // our rate limiting scheme. - limiter := time.Tick(200 * time.Millisecond) + // This `limiter` channel will receive a value + // every 200 milliseconds. This is the regulator in + // our rate limiting scheme. + limiter := time.Tick(200 * time.Millisecond) - // By blocking on a receive from the `limiter` channel - // before serving each request, we limit ourselves to - // 1 request every 200 milliseconds. - for req := range requests { - <-limiter - fmt.Println("request", req, time.Now()) - } + // By blocking on a receive from the `limiter` channel + // before serving each request, we limit ourselves to + // 1 request every 200 milliseconds. + for req := range requests { + <-limiter + fmt.Println("request", req, time.Now()) + } - // We may want to allow short bursts of requests in - // our rate limiting scheme while preserving the - // overall rate limit. We can accomplish this by - // buffering our limiter channel. This `burstyLimiter` - // channel will allow bursts of up to 3 events. - burstyLimiter := make(chan time.Time, 3) + // We may want to allow short bursts of requests in + // our rate limiting scheme while preserving the + // overall rate limit. We can accomplish this by + // buffering our limiter channel. This `burstyLimiter` + // channel will allow bursts of up to 3 events. + burstyLimiter := make(chan time.Time, 3) - // Fill up the channel to represent allowed bursting. - for i := 0; i < 3; i++ { - burstyLimiter <- time.Now() - } + // Fill up the channel to represent allowed bursting. + for i := 0; i < 3; i++ { + burstyLimiter <- time.Now() + } - // Every 200 milliseconds we'll try to add a new - // value to `burstyLimiter`, up to its limit of 3. - go func() { - for t := range time.Tick(200 * time.Millisecond) { - burstyLimiter <- t - } - }() + // Every 200 milliseconds we'll try to add a new + // value to `burstyLimiter`, up to its limit of 3. + go func() { + for t := range time.Tick(200 * time.Millisecond) { + burstyLimiter <- t + } + }() - // Now simulate 5 more incoming requests. The first - // 3 of these will benefit from the burst capability - // of `burstyLimiter`. - burstyRequests := make(chan int, 5) - for i := 1; i <= 5; i++ { - burstyRequests <- i - } - close(burstyRequests) - for req := range burstyRequests { - <-burstyLimiter - fmt.Println("request", req, time.Now()) - } + // Now simulate 5 more incoming requests. The first + // 3 of these will benefit from the burst capability + // of `burstyLimiter`. + burstyRequests := make(chan int, 5) + for i := 1; i <= 5; i++ { + burstyRequests <- i + } + close(burstyRequests) + for req := range burstyRequests { + <-burstyLimiter + fmt.Println("request", req, time.Now()) + } } diff --git a/examples/reading-files/reading-files.go b/examples/reading-files/reading-files.go index 807195f..bcff7fe 100644 --- a/examples/reading-files/reading-files.go +++ b/examples/reading-files/reading-files.go @@ -5,80 +5,80 @@ package main import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "os" + "bufio" + "fmt" + "io" + "io/ioutil" + "os" ) // Reading files requires checking most calls for errors. // This helper will streamline our error checks below. func check(e error) { - if e != nil { - panic(e) - } + if e != nil { + panic(e) + } } func main() { - // Perhaps the most basic file reading task is - // slurping a file's entire contents into memory. - dat, err := ioutil.ReadFile("/tmp/dat") - check(err) - fmt.Print(string(dat)) + // Perhaps the most basic file reading task is + // slurping a file's entire contents into memory. + dat, err := ioutil.ReadFile("/tmp/dat") + check(err) + fmt.Print(string(dat)) - // You'll often want more control over how and what - // parts of a file are read. For these tasks, start - // by `Open`ing a file to obtain an `os.File` value. - f, err := os.Open("/tmp/dat") - check(err) + // You'll often want more control over how and what + // parts of a file are read. For these tasks, start + // by `Open`ing a file to obtain an `os.File` value. + f, err := os.Open("/tmp/dat") + check(err) - // Read some bytes from the beginning of the file. - // Allow up to 5 to be read but also note how many - // actually were read. - b1 := make([]byte, 5) - n1, err := f.Read(b1) - check(err) - fmt.Printf("%d bytes: %s\n", n1, string(b1)) + // Read some bytes from the beginning of the file. + // Allow up to 5 to be read but also note how many + // actually were read. + b1 := make([]byte, 5) + n1, err := f.Read(b1) + check(err) + fmt.Printf("%d bytes: %s\n", n1, string(b1)) - // You can also `Seek` to a known location in the file - // and `Read` from there. - o2, err := f.Seek(6, 0) - check(err) - b2 := make([]byte, 2) - n2, err := f.Read(b2) - check(err) - fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) + // You can also `Seek` to a known location in the file + // and `Read` from there. + o2, err := f.Seek(6, 0) + check(err) + b2 := make([]byte, 2) + n2, err := f.Read(b2) + check(err) + fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) - // The `io` package provides some functions that may - // be helpful for file reading. For example, reads - // like the ones above can be more robustly - // implemented with `ReadAtLeast`. - o3, err := f.Seek(6, 0) - check(err) - b3 := make([]byte, 2) - n3, err := io.ReadAtLeast(f, b3, 2) - check(err) - fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3)) + // The `io` package provides some functions that may + // be helpful for file reading. For example, reads + // like the ones above can be more robustly + // implemented with `ReadAtLeast`. + o3, err := f.Seek(6, 0) + check(err) + b3 := make([]byte, 2) + n3, err := io.ReadAtLeast(f, b3, 2) + check(err) + fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3)) - // There is no built-in rewind, but `Seek(0, 0)` - // accomplishes this. - _, err = f.Seek(0, 0) - check(err) + // There is no built-in rewind, but `Seek(0, 0)` + // accomplishes this. + _, err = f.Seek(0, 0) + check(err) - // The `bufio` package implements a buffered - // reader that may be useful both for its efficiency - // with many small reads and because of the additional - // reading methods it provides. - r4 := bufio.NewReader(f) - b4, err := r4.Peek(5) - check(err) - fmt.Printf("5 bytes: %s\n", string(b4)) + // The `bufio` package implements a buffered + // reader that may be useful both for its efficiency + // with many small reads and because of the additional + // reading methods it provides. + r4 := bufio.NewReader(f) + b4, err := r4.Peek(5) + check(err) + fmt.Printf("5 bytes: %s\n", string(b4)) - // Close the file when you're done (usually this would - // be scheduled immediately after `Open`ing with - // `defer`). - f.Close() + // Close the file when you're done (usually this would + // be scheduled immediately after `Open`ing with + // `defer`). + f.Close() } diff --git a/examples/reading-files/reading-files.hash b/examples/reading-files/reading-files.hash index c56535c..f687f38 100644 --- a/examples/reading-files/reading-files.hash +++ b/examples/reading-files/reading-files.hash @@ -1,2 +1,2 @@ 2aa7a2e248065cebfa6f8eece3234b5ffa710273 -2kEKXq-kUV +GQgp-I3dLb2 diff --git a/examples/recursion/recursion.go b/examples/recursion/recursion.go index 417b3d8..a88b1e5 100644 --- a/examples/recursion/recursion.go +++ b/examples/recursion/recursion.go @@ -9,12 +9,12 @@ import "fmt" // This `fact` function calls itself until it reaches the // base case of `fact(0)`. func fact(n int) int { - if n == 0 { - return 1 - } - return n * fact(n-1) + if n == 0 { + return 1 + } + return n * fact(n-1) } func main() { - fmt.Println(fact(7)) + fmt.Println(fact(7)) } diff --git a/examples/recursion/recursion.hash b/examples/recursion/recursion.hash index b867f04..2ebf561 100644 --- a/examples/recursion/recursion.hash +++ b/examples/recursion/recursion.hash @@ -1,2 +1,2 @@ 5d1ba6b03a50ccae2a0f46865eb72c587e11857c -RFn-rf42ap +4yUp5wLVyiG diff --git a/examples/regular-expressions/regular-expressions.go b/examples/regular-expressions/regular-expressions.go index fa66f83..5d5ee8c 100644 --- a/examples/regular-expressions/regular-expressions.go +++ b/examples/regular-expressions/regular-expressions.go @@ -10,72 +10,72 @@ import "regexp" func main() { - // This tests whether a pattern matches a string. - match, _ := regexp.MatchString("p([a-z]+)ch", "peach") - fmt.Println(match) + // This tests whether a pattern matches a string. + match, _ := regexp.MatchString("p([a-z]+)ch", "peach") + fmt.Println(match) - // Above we used a string pattern directly, but for - // other regexp tasks you'll need to `Compile` an - // optimized `Regexp` struct. - r, _ := regexp.Compile("p([a-z]+)ch") + // Above we used a string pattern directly, but for + // other regexp tasks you'll need to `Compile` an + // optimized `Regexp` struct. + r, _ := regexp.Compile("p([a-z]+)ch") - // Many methods are available on these structs. Here's - // a match test like we saw earlier. - fmt.Println(r.MatchString("peach")) + // Many methods are available on these structs. Here's + // a match test like we saw earlier. + fmt.Println(r.MatchString("peach")) - // This finds the match for the regexp. - fmt.Println(r.FindString("peach punch")) + // This finds the match for the regexp. + fmt.Println(r.FindString("peach punch")) - // This also finds the first match but returns the - // start and end indexes for the match instead of the - // matching text. - fmt.Println(r.FindStringIndex("peach punch")) + // This also finds the first match but returns the + // start and end indexes for the match instead of the + // matching text. + fmt.Println(r.FindStringIndex("peach punch")) - // The `Submatch` variants include information about - // both the whole-pattern matches and the submatches - // within those matches. For example this will return - // information for both `p([a-z]+)ch` and `([a-z]+)`. - fmt.Println(r.FindStringSubmatch("peach punch")) + // The `Submatch` variants include information about + // both the whole-pattern matches and the submatches + // within those matches. For example this will return + // information for both `p([a-z]+)ch` and `([a-z]+)`. + fmt.Println(r.FindStringSubmatch("peach punch")) - // Similarly this will return information about the - // indexes of matches and submatches. - fmt.Println(r.FindStringSubmatchIndex("peach punch")) + // Similarly this will return information about the + // indexes of matches and submatches. + fmt.Println(r.FindStringSubmatchIndex("peach punch")) - // The `All` variants of these functions apply to all - // matches in the input, not just the first. For - // example to find all matches for a regexp. - fmt.Println(r.FindAllString("peach punch pinch", -1)) + // The `All` variants of these functions apply to all + // matches in the input, not just the first. For + // example to find all matches for a regexp. + fmt.Println(r.FindAllString("peach punch pinch", -1)) - // These `All` variants are available for the other - // functions we saw above as well. - fmt.Println(r.FindAllStringSubmatchIndex( - "peach punch pinch", -1)) + // These `All` variants are available for the other + // functions we saw above as well. + fmt.Println(r.FindAllStringSubmatchIndex( + "peach punch pinch", -1)) - // Providing a non-negative integer as the second - // argument to these functions will limit the number - // of matches. - fmt.Println(r.FindAllString("peach punch pinch", 2)) + // Providing a non-negative integer as the second + // argument to these functions will limit the number + // of matches. + fmt.Println(r.FindAllString("peach punch pinch", 2)) - // Our examples above had string arguments and used - // names like `MatchString`. We can also provide - // `[]byte` arguments and drop `String` from the - // function name. - fmt.Println(r.Match([]byte("peach"))) + // Our examples above had string arguments and used + // names like `MatchString`. We can also provide + // `[]byte` arguments and drop `String` from the + // function name. + fmt.Println(r.Match([]byte("peach"))) - // When creating constants with regular expressions - // you can use the `MustCompile` variation of - // `Compile`. A plain `Compile` won't work for - // constants because it has 2 return values. - r = regexp.MustCompile("p([a-z]+)ch") - fmt.Println(r) + // When creating constants with regular expressions + // you can use the `MustCompile` variation of + // `Compile`. A plain `Compile` won't work for + // constants because it has 2 return values. + r = regexp.MustCompile("p([a-z]+)ch") + fmt.Println(r) - // The `regexp` package can also be used to replace - // subsets of strings with other values. - fmt.Println(r.ReplaceAllString("a peach", "")) + // The `regexp` package can also be used to replace + // subsets of strings with other values. + fmt.Println(r.ReplaceAllString("a peach", "")) - // The `Func` variant allows you to transform matched - // text with a given function. - in := []byte("a peach") - out := r.ReplaceAllFunc(in, bytes.ToUpper) - fmt.Println(string(out)) + // The `Func` variant allows you to transform matched + // text with a given function. + in := []byte("a peach") + out := r.ReplaceAllFunc(in, bytes.ToUpper) + fmt.Println(string(out)) } diff --git a/examples/regular-expressions/regular-expressions.hash b/examples/regular-expressions/regular-expressions.hash index 9e3526c..abc14cd 100644 --- a/examples/regular-expressions/regular-expressions.hash +++ b/examples/regular-expressions/regular-expressions.hash @@ -1,2 +1,2 @@ 7cde6b9af5cf6c47606001dd54eee468a6c61dbb -YeSiBTfhFq +qR5gn2l0AGa diff --git a/examples/select/select.go b/examples/select/select.go index cd9e418..c05aacb 100644 --- a/examples/select/select.go +++ b/examples/select/select.go @@ -9,30 +9,30 @@ import "fmt" func main() { - // For our example we'll select across two channels. - c1 := make(chan string) - c2 := make(chan string) + // For our example we'll select across two channels. + c1 := make(chan string) + c2 := make(chan string) - // Each channel will receive a value after some amount - // of time, to simulate e.g. blocking RPC operations - // executing in concurrent goroutines. - go func() { - time.Sleep(1 * time.Second) - c1 <- "one" - }() - go func() { - time.Sleep(2 * time.Second) - c2 <- "two" - }() + // Each channel will receive a value after some amount + // of time, to simulate e.g. blocking RPC operations + // executing in concurrent goroutines. + go func() { + time.Sleep(1 * time.Second) + c1 <- "one" + }() + go func() { + time.Sleep(2 * time.Second) + c2 <- "two" + }() - // We'll use `select` to await both of these values - // simultaneously, printing each one as it arrives. - for i := 0; i < 2; i++ { - select { - case msg1 := <-c1: - fmt.Println("received", msg1) - case msg2 := <-c2: - fmt.Println("received", msg2) - } - } + // We'll use `select` to await both of these values + // simultaneously, printing each one as it arrives. + for i := 0; i < 2; i++ { + select { + case msg1 := <-c1: + fmt.Println("received", msg1) + case msg2 := <-c2: + fmt.Println("received", msg2) + } + } } diff --git a/examples/sha1-hashes/sha1-hashes.go b/examples/sha1-hashes/sha1-hashes.go index df0ee7d..db8bb39 100644 --- a/examples/sha1-hashes/sha1-hashes.go +++ b/examples/sha1-hashes/sha1-hashes.go @@ -13,25 +13,25 @@ import "crypto/sha1" import "fmt" func main() { - s := "sha1 this string" + s := "sha1 this string" - // The pattern for generating a hash is `sha1.New()`, - // `sha1.Write(bytes)`, then `sha1.Sum([]byte{})`. - // Here we start with a new hash. - h := sha1.New() + // The pattern for generating a hash is `sha1.New()`, + // `sha1.Write(bytes)`, then `sha1.Sum([]byte{})`. + // Here we start with a new hash. + h := sha1.New() - // `Write` expects bytes. If you have a string `s`, - // use `[]byte(s)` to coerce it to bytes. - h.Write([]byte(s)) + // `Write` expects bytes. If you have a string `s`, + // use `[]byte(s)` to coerce it to bytes. + h.Write([]byte(s)) - // This gets the finalized hash result as a byte - // slice. The argument to `Sum` can be used to append - // to an existing byte slice: it usually isn't needed. - bs := h.Sum(nil) + // This gets the finalized hash result as a byte + // slice. The argument to `Sum` can be used to append + // to an existing byte slice: it usually isn't needed. + bs := h.Sum(nil) - // SHA1 values are often printed in hex, for example - // in git commits. Use the `%x` format verb to convert - // a hash results to a hex string. - fmt.Println(s) - fmt.Printf("%x\n", bs) + // SHA1 values are often printed in hex, for example + // in git commits. Use the `%x` format verb to convert + // a hash results to a hex string. + fmt.Println(s) + fmt.Printf("%x\n", bs) } diff --git a/examples/sha1-hashes/sha1-hashes.hash b/examples/sha1-hashes/sha1-hashes.hash index 081d3d7..e56a014 100644 --- a/examples/sha1-hashes/sha1-hashes.hash +++ b/examples/sha1-hashes/sha1-hashes.hash @@ -1,2 +1,2 @@ 6a896270e34f2696b881a8fa7e68bfff57dee51f -YUaWWEeB4U +1oT-5GBUkLr diff --git a/examples/signals/signals.go b/examples/signals/signals.go index b664ba1..38e17ad 100644 --- a/examples/signals/signals.go +++ b/examples/signals/signals.go @@ -14,31 +14,31 @@ import "syscall" func main() { - // Go signal notification works by sending `os.Signal` - // values on a channel. We'll create a channel to - // receive these notifications (we'll also make one to - // notify us when the program can exit). - sigs := make(chan os.Signal, 1) - done := make(chan bool, 1) + // Go signal notification works by sending `os.Signal` + // values on a channel. We'll create a channel to + // receive these notifications (we'll also make one to + // notify us when the program can exit). + sigs := make(chan os.Signal, 1) + done := make(chan bool, 1) - // `signal.Notify` registers the given channel to - // receive notifications of the specified signals. - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + // `signal.Notify` registers the given channel to + // receive notifications of the specified signals. + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - // This goroutine executes a blocking receive for - // signals. When it gets one it'll print it out - // and then notify the program that it can finish. - go func() { - sig := <-sigs - fmt.Println() - fmt.Println(sig) - done <- true - }() + // This goroutine executes a blocking receive for + // signals. When it gets one it'll print it out + // and then notify the program that it can finish. + go func() { + sig := <-sigs + fmt.Println() + fmt.Println(sig) + done <- true + }() - // The program will wait here until it gets the - // expected signal (as indicated by the goroutine - // above sending a value on `done`) and then exit. - fmt.Println("awaiting signal") - <-done - fmt.Println("exiting") + // The program will wait here until it gets the + // expected signal (as indicated by the goroutine + // above sending a value on `done`) and then exit. + fmt.Println("awaiting signal") + <-done + fmt.Println("exiting") } diff --git a/examples/signals/signals.hash b/examples/signals/signals.hash index b445924..94e8edb 100644 --- a/examples/signals/signals.hash +++ b/examples/signals/signals.hash @@ -1,2 +1,2 @@ 9720d747e3ab2893df508a70cbb341c90fdd7ca1 -BlkqAtKsxo +9koJAW1raI5 diff --git a/examples/slices/slices.go b/examples/slices/slices.go index 521d1af..914a327 100644 --- a/examples/slices/slices.go +++ b/examples/slices/slices.go @@ -7,70 +7,70 @@ import "fmt" func main() { - // Unlike arrays, slices are typed only by the - // elements they contain (not the number of elements). - // To create an empty slice with non-zero length, use - // the builtin `make`. Here we make a slice of - // `string`s of length `3` (initially zero-valued). - s := make([]string, 3) - fmt.Println("emp:", s) + // Unlike arrays, slices are typed only by the + // elements they contain (not the number of elements). + // To create an empty slice with non-zero length, use + // the builtin `make`. Here we make a slice of + // `string`s of length `3` (initially zero-valued). + s := make([]string, 3) + fmt.Println("emp:", s) - // We can set and get just like with arrays. - s[0] = "a" - s[1] = "b" - s[2] = "c" - fmt.Println("set:", s) - fmt.Println("get:", s[2]) + // We can set and get just like with arrays. + s[0] = "a" + s[1] = "b" + s[2] = "c" + fmt.Println("set:", s) + fmt.Println("get:", s[2]) - // `len` returns the length of the slice as expected. - fmt.Println("len:", len(s)) + // `len` returns the length of the slice as expected. + fmt.Println("len:", len(s)) - // In addition to these basic operations, slices - // support several more that make them richer than - // arrays. One is the builtin `append`, which - // returns a slice containing one or more new values. - // Note that we need to accept a return value from - // `append` as we may get a new slice value. - s = append(s, "d") - s = append(s, "e", "f") - fmt.Println("apd:", s) + // In addition to these basic operations, slices + // support several more that make them richer than + // arrays. One is the builtin `append`, which + // returns a slice containing one or more new values. + // Note that we need to accept a return value from + // `append` as we may get a new slice value. + s = append(s, "d") + s = append(s, "e", "f") + fmt.Println("apd:", s) - // Slices can also be `copy`'d. Here we create an - // empty slice `c` of the same length as `s` and copy - // into `c` from `s`. - c := make([]string, len(s)) - copy(c, s) - fmt.Println("cpy:", c) + // Slices can also be `copy`'d. Here we create an + // empty slice `c` of the same length as `s` and copy + // into `c` from `s`. + c := make([]string, len(s)) + copy(c, s) + fmt.Println("cpy:", c) - // Slices support a "slice" operator with the syntax - // `slice[low:high]`. For example, this gets a slice - // of the elements `s[2]`, `s[3]`, and `s[4]`. - l := s[2:5] - fmt.Println("sl1:", l) + // Slices support a "slice" operator with the syntax + // `slice[low:high]`. For example, this gets a slice + // of the elements `s[2]`, `s[3]`, and `s[4]`. + l := s[2:5] + fmt.Println("sl1:", l) - // This slices up to (but excluding) `s[5]`. - l = s[:5] - fmt.Println("sl2:", l) + // This slices up to (but excluding) `s[5]`. + l = s[:5] + fmt.Println("sl2:", l) - // And this slices up from (and including) `s[2]`. - l = s[2:] - fmt.Println("sl3:", l) + // And this slices up from (and including) `s[2]`. + l = s[2:] + fmt.Println("sl3:", l) - // We can declare and initialize a variable for slice - // in a single line as well. - t := []string{"g", "h", "i"} - fmt.Println("dcl:", t) + // We can declare and initialize a variable for slice + // in a single line as well. + t := []string{"g", "h", "i"} + fmt.Println("dcl:", t) - // Slices can be composed into multi-dimensional data - // structures. The length of the inner slices can - // vary, unlike with multi-dimensional arrays. - twoD := make([][]int, 3) - for i := 0; i < 3; i++ { - innerLen := i + 1 - twoD[i] = make([]int, innerLen) - for j := 0; j < innerLen; j++ { - twoD[i][j] = i + j - } - } - fmt.Println("2d: ", twoD) + // Slices can be composed into multi-dimensional data + // structures. The length of the inner slices can + // vary, unlike with multi-dimensional arrays. + twoD := make([][]int, 3) + for i := 0; i < 3; i++ { + innerLen := i + 1 + twoD[i] = make([]int, innerLen) + for j := 0; j < innerLen; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) } diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index e01bdcc..b880564 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -23,13 +23,13 @@ type byLength []string // want to sort in order of increasing string length, so // we use `len(s[i])` and `len(s[j])` here. func (s byLength) Len() int { - return len(s) + return len(s) } func (s byLength) Swap(i, j int) { - s[i], s[j] = s[j], s[i] + s[i], s[j] = s[j], s[i] } func (s byLength) Less(i, j int) bool { - return len(s[i]) < len(s[j]) + return len(s[i]) < len(s[j]) } // With all of this in place, we can now implement our @@ -37,7 +37,7 @@ func (s byLength) Less(i, j int) bool { // to `byLength`, and then use `sort.Sort` on that typed // slice. func main() { - fruits := []string{"peach", "banana", "kiwi"} - sort.Sort(byLength(fruits)) - fmt.Println(fruits) + fruits := []string{"peach", "banana", "kiwi"} + sort.Sort(byLength(fruits)) + fmt.Println(fruits) } diff --git a/examples/sorting/sorting.go b/examples/sorting/sorting.go index 7478806..b6317ed 100644 --- a/examples/sorting/sorting.go +++ b/examples/sorting/sorting.go @@ -9,21 +9,21 @@ import "sort" func main() { - // Sort methods are specific to the builtin type; - // here's an example for strings. Note that sorting is - // in-place, so it changes the given slice and doesn't - // return a new one. - strs := []string{"c", "a", "b"} - sort.Strings(strs) - fmt.Println("Strings:", strs) + // Sort methods are specific to the builtin type; + // here's an example for strings. Note that sorting is + // in-place, so it changes the given slice and doesn't + // return a new one. + strs := []string{"c", "a", "b"} + sort.Strings(strs) + fmt.Println("Strings:", strs) - // An example of sorting `int`s. - ints := []int{7, 2, 4} - sort.Ints(ints) - fmt.Println("Ints: ", ints) + // An example of sorting `int`s. + ints := []int{7, 2, 4} + sort.Ints(ints) + fmt.Println("Ints: ", ints) - // We can also use `sort` to check if a slice is - // already in sorted order. - s := sort.IntsAreSorted(ints) - fmt.Println("Sorted: ", s) + // We can also use `sort` to check if a slice is + // already in sorted order. + s := sort.IntsAreSorted(ints) + fmt.Println("Sorted: ", s) } diff --git a/examples/sorting/sorting.hash b/examples/sorting/sorting.hash index ffb7712..ae5e449 100644 --- a/examples/sorting/sorting.hash +++ b/examples/sorting/sorting.hash @@ -1,2 +1,2 @@ 4e576421f2bdbd11847c367d223bd30d0e301990 -roQOJXtqAb +e6hp3Rn-oH6 diff --git a/examples/spawning-processes/spawning-processes.go b/examples/spawning-processes/spawning-processes.go index 14f3dac..98e0f65 100644 --- a/examples/spawning-processes/spawning-processes.go +++ b/examples/spawning-processes/spawning-processes.go @@ -13,59 +13,59 @@ import "os/exec" func main() { - // We'll start with a simple command that takes no - // arguments or input and just prints something to - // stdout. The `exec.Command` helper creates an object - // to represent this external process. - dateCmd := exec.Command("date") + // We'll start with a simple command that takes no + // arguments or input and just prints something to + // stdout. The `exec.Command` helper creates an object + // to represent this external process. + dateCmd := exec.Command("date") - // `.Output` is another helper that handles the common - // case of running a command, waiting for it to finish, - // and collecting its output. If there were no errors, - // `dateOut` will hold bytes with the date info. - dateOut, err := dateCmd.Output() - if err != nil { - panic(err) - } - fmt.Println("> date") - fmt.Println(string(dateOut)) + // `.Output` is another helper that handles the common + // case of running a command, waiting for it to finish, + // and collecting its output. If there were no errors, + // `dateOut` will hold bytes with the date info. + dateOut, err := dateCmd.Output() + if err != nil { + panic(err) + } + fmt.Println("> date") + fmt.Println(string(dateOut)) - // Next we'll look at a slightly more involved case - // where we pipe data to the external process on its - // `stdin` and collect the results from its `stdout`. - grepCmd := exec.Command("grep", "hello") + // Next we'll look at a slightly more involved case + // where we pipe data to the external process on its + // `stdin` and collect the results from its `stdout`. + grepCmd := exec.Command("grep", "hello") - // Here we explicitly grab input/output pipes, start - // the process, write some input to it, read the - // resulting output, and finally wait for the process - // to exit. - grepIn, _ := grepCmd.StdinPipe() - grepOut, _ := grepCmd.StdoutPipe() - grepCmd.Start() - grepIn.Write([]byte("hello grep\ngoodbye grep")) - grepIn.Close() - grepBytes, _ := ioutil.ReadAll(grepOut) - grepCmd.Wait() + // Here we explicitly grab input/output pipes, start + // the process, write some input to it, read the + // resulting output, and finally wait for the process + // to exit. + grepIn, _ := grepCmd.StdinPipe() + grepOut, _ := grepCmd.StdoutPipe() + grepCmd.Start() + grepIn.Write([]byte("hello grep\ngoodbye grep")) + grepIn.Close() + grepBytes, _ := ioutil.ReadAll(grepOut) + grepCmd.Wait() - // We ommited error checks in the above example, but - // you could use the usual `if err != nil` pattern for - // all of them. We also only collect the `StdoutPipe` - // results, but you could collect the `StderrPipe` in - // exactly the same way. - fmt.Println("> grep hello") - fmt.Println(string(grepBytes)) + // We ommited error checks in the above example, but + // you could use the usual `if err != nil` pattern for + // all of them. We also only collect the `StdoutPipe` + // results, but you could collect the `StderrPipe` in + // exactly the same way. + fmt.Println("> grep hello") + fmt.Println(string(grepBytes)) - // Note that when spawning commands we need to - // provide an explicitly delineated command and - // argument array, vs. being able to just pass in one - // command-line string. If you want to spawn a full - // command with a string, you can use `bash`'s `-c` - // option: - lsCmd := exec.Command("bash", "-c", "ls -a -l -h") - lsOut, err := lsCmd.Output() - if err != nil { - panic(err) - } - fmt.Println("> ls -a -l -h") - fmt.Println(string(lsOut)) + // Note that when spawning commands we need to + // provide an explicitly delineated command and + // argument array, vs. being able to just pass in one + // command-line string. If you want to spawn a full + // command with a string, you can use `bash`'s `-c` + // option: + lsCmd := exec.Command("bash", "-c", "ls -a -l -h") + lsOut, err := lsCmd.Output() + if err != nil { + panic(err) + } + fmt.Println("> ls -a -l -h") + fmt.Println(string(lsOut)) } diff --git a/examples/spawning-processes/spawning-processes.hash b/examples/spawning-processes/spawning-processes.hash index 1cb6249..dd1b749 100644 --- a/examples/spawning-processes/spawning-processes.hash +++ b/examples/spawning-processes/spawning-processes.hash @@ -1,2 +1,2 @@ 0b676b93e41ac5434003c194bc038d5f3ce76bc8 -y6SB6Mf2VQ +6HRWVK5gPYU diff --git a/examples/stateful-goroutines/stateful-goroutines.go b/examples/stateful-goroutines/stateful-goroutines.go index 20b0923..598c4a9 100644 --- a/examples/stateful-goroutines/stateful-goroutines.go +++ b/examples/stateful-goroutines/stateful-goroutines.go @@ -10,10 +10,10 @@ package main import ( - "fmt" - "math/rand" - "sync/atomic" - "time" + "fmt" + "math/rand" + "sync/atomic" + "time" ) // In this example our state will be owned by a single @@ -25,91 +25,91 @@ import ( // encapsulate those requests and a way for the owning // goroutine to respond. type readOp struct { - key int - resp chan int + key int + resp chan int } type writeOp struct { - key int - val int - resp chan bool + key int + val int + resp chan bool } func main() { - // As before we'll count how many operations we perform. - var readOps uint64 - var writeOps uint64 + // As before we'll count how many operations we perform. + var readOps uint64 + var writeOps uint64 - // The `reads` and `writes` channels will be used by - // other goroutines to issue read and write requests, - // respectively. - reads := make(chan *readOp) - writes := make(chan *writeOp) + // The `reads` and `writes` channels will be used by + // other goroutines to issue read and write requests, + // respectively. + reads := make(chan *readOp) + writes := make(chan *writeOp) - // Here is the goroutine that owns the `state`, which - // is a map as in the previous example but now private - // to the stateful goroutine. This goroutine repeatedly - // selects on the `reads` and `writes` channels, - // responding to requests as they arrive. A response - // is executed by first performing the requested - // operation and then sending a value on the response - // channel `resp` to indicate success (and the desired - // value in the case of `reads`). - go func() { - var state = make(map[int]int) - for { - select { - case read := <-reads: - read.resp <- state[read.key] - case write := <-writes: - state[write.key] = write.val - write.resp <- true - } - } - }() + // Here is the goroutine that owns the `state`, which + // is a map as in the previous example but now private + // to the stateful goroutine. This goroutine repeatedly + // selects on the `reads` and `writes` channels, + // responding to requests as they arrive. A response + // is executed by first performing the requested + // operation and then sending a value on the response + // channel `resp` to indicate success (and the desired + // value in the case of `reads`). + go func() { + var state = make(map[int]int) + for { + select { + case read := <-reads: + read.resp <- state[read.key] + case write := <-writes: + state[write.key] = write.val + write.resp <- true + } + } + }() - // This starts 100 goroutines to issue reads to the - // state-owning goroutine via the `reads` channel. - // Each read requires constructing a `readOp`, sending - // it over the `reads` channel, and the receiving the - // result over the provided `resp` channel. - for r := 0; r < 100; r++ { - go func() { - for { - read := &readOp{ - key: rand.Intn(5), - resp: make(chan int)} - reads <- read - <-read.resp - atomic.AddUint64(&readOps, 1) - time.Sleep(time.Millisecond) - } - }() - } + // This starts 100 goroutines to issue reads to the + // state-owning goroutine via the `reads` channel. + // Each read requires constructing a `readOp`, sending + // it over the `reads` channel, and the receiving the + // result over the provided `resp` channel. + for r := 0; r < 100; r++ { + go func() { + for { + read := &readOp{ + key: rand.Intn(5), + resp: make(chan int)} + reads <- read + <-read.resp + atomic.AddUint64(&readOps, 1) + time.Sleep(time.Millisecond) + } + }() + } - // We start 10 writes as well, using a similar - // approach. - for w := 0; w < 10; w++ { - go func() { - for { - write := &writeOp{ - key: rand.Intn(5), - val: rand.Intn(100), - resp: make(chan bool)} - writes <- write - <-write.resp - atomic.AddUint64(&writeOps, 1) - time.Sleep(time.Millisecond) - } - }() - } + // We start 10 writes as well, using a similar + // approach. + for w := 0; w < 10; w++ { + go func() { + for { + write := &writeOp{ + key: rand.Intn(5), + val: rand.Intn(100), + resp: make(chan bool)} + writes <- write + <-write.resp + atomic.AddUint64(&writeOps, 1) + time.Sleep(time.Millisecond) + } + }() + } - // Let the goroutines work for a second. - time.Sleep(time.Second) + // Let the goroutines work for a second. + time.Sleep(time.Second) - // Finally, capture and report the op counts. - readOpsFinal := atomic.LoadUint64(&readOps) - fmt.Println("readOps:", readOpsFinal) - writeOpsFinal := atomic.LoadUint64(&writeOps) - fmt.Println("writeOps:", writeOpsFinal) + // Finally, capture and report the op counts. + readOpsFinal := atomic.LoadUint64(&readOps) + fmt.Println("readOps:", readOpsFinal) + writeOpsFinal := atomic.LoadUint64(&writeOps) + fmt.Println("writeOps:", writeOpsFinal) } diff --git a/examples/string-formatting/string-formatting.go b/examples/string-formatting/string-formatting.go index ac5f57c..de7c285 100644 --- a/examples/string-formatting/string-formatting.go +++ b/examples/string-formatting/string-formatting.go @@ -8,101 +8,101 @@ import "fmt" import "os" type point struct { - x, y int + x, y int } func main() { - // Go offers several printing "verbs" designed to - // format general Go values. For example, this prints - // an instance of our `point` struct. - p := point{1, 2} - fmt.Printf("%v\n", p) + // Go offers several printing "verbs" designed to + // format general Go values. For example, this prints + // an instance of our `point` struct. + p := point{1, 2} + fmt.Printf("%v\n", p) - // If the value is a struct, the `%+v` variant will - // include the struct's field names. - fmt.Printf("%+v\n", p) + // If the value is a struct, the `%+v` variant will + // include the struct's field names. + fmt.Printf("%+v\n", p) - // The `%#v` variant prints a Go syntax representation - // of the value, i.e. the source code snippet that - // would produce that value. - fmt.Printf("%#v\n", p) + // The `%#v` variant prints a Go syntax representation + // of the value, i.e. the source code snippet that + // would produce that value. + fmt.Printf("%#v\n", p) - // To print the type of a value, use `%T`. - fmt.Printf("%T\n", p) + // To print the type of a value, use `%T`. + fmt.Printf("%T\n", p) - // Formatting booleans is straight-forward. - fmt.Printf("%t\n", true) + // Formatting booleans is straight-forward. + fmt.Printf("%t\n", true) - // There are many options for formatting integers. - // Use `%d` for standard, base-10 formatting. - fmt.Printf("%d\n", 123) + // There are many options for formatting integers. + // Use `%d` for standard, base-10 formatting. + fmt.Printf("%d\n", 123) - // This prints a binary representation. - fmt.Printf("%b\n", 14) + // This prints a binary representation. + fmt.Printf("%b\n", 14) - // This prints the character corresponding to the - // given integer. - fmt.Printf("%c\n", 33) + // This prints the character corresponding to the + // given integer. + fmt.Printf("%c\n", 33) - // `%x` provides hex encoding. - fmt.Printf("%x\n", 456) + // `%x` provides hex encoding. + fmt.Printf("%x\n", 456) - // There are also several formatting options for - // floats. For basic decimal formatting use `%f`. - fmt.Printf("%f\n", 78.9) + // There are also several formatting options for + // floats. For basic decimal formatting use `%f`. + fmt.Printf("%f\n", 78.9) - // `%e` and `%E` format the float in (slightly - // different versions of) scientific notation. - fmt.Printf("%e\n", 123400000.0) - fmt.Printf("%E\n", 123400000.0) + // `%e` and `%E` format the float in (slightly + // different versions of) scientific notation. + fmt.Printf("%e\n", 123400000.0) + fmt.Printf("%E\n", 123400000.0) - // For basic string printing use `%s`. - fmt.Printf("%s\n", "\"string\"") + // For basic string printing use `%s`. + fmt.Printf("%s\n", "\"string\"") - // To double-quote strings as in Go source, use `%q`. - fmt.Printf("%q\n", "\"string\"") + // To double-quote strings as in Go source, use `%q`. + fmt.Printf("%q\n", "\"string\"") - // As with integers seen earlier, `%x` renders - // the string in base-16, with two output characters - // per byte of input. - fmt.Printf("%x\n", "hex this") + // As with integers seen earlier, `%x` renders + // the string in base-16, with two output characters + // per byte of input. + fmt.Printf("%x\n", "hex this") - // To print a representation of a pointer, use `%p`. - fmt.Printf("%p\n", &p) + // To print a representation of a pointer, use `%p`. + fmt.Printf("%p\n", &p) - // When formatting numbers you will often want to - // control the width and precision of the resulting - // figure. To specify the width of an integer, use a - // number after the `%` in the verb. By default the - // result will be right-justified and padded with - // spaces. - fmt.Printf("|%6d|%6d|\n", 12, 345) + // When formatting numbers you will often want to + // control the width and precision of the resulting + // figure. To specify the width of an integer, use a + // number after the `%` in the verb. By default the + // result will be right-justified and padded with + // spaces. + fmt.Printf("|%6d|%6d|\n", 12, 345) - // You can also specify the width of printed floats, - // though usually you'll also want to restrict the - // decimal precision at the same time with the - // width.precision syntax. - fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) + // You can also specify the width of printed floats, + // though usually you'll also want to restrict the + // decimal precision at the same time with the + // width.precision syntax. + fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) - // To left-justify, use the `-` flag. - fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) + // To left-justify, use the `-` flag. + fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) - // You may also want to control width when formatting - // strings, especially to ensure that they align in - // table-like output. For basic right-justified width. - fmt.Printf("|%6s|%6s|\n", "foo", "b") + // You may also want to control width when formatting + // strings, especially to ensure that they align in + // table-like output. For basic right-justified width. + fmt.Printf("|%6s|%6s|\n", "foo", "b") - // To left-justify use the `-` flag as with numbers. - fmt.Printf("|%-6s|%-6s|\n", "foo", "b") + // To left-justify use the `-` flag as with numbers. + fmt.Printf("|%-6s|%-6s|\n", "foo", "b") - // So far we've seen `Printf`, which prints the - // formatted string to `os.Stdout`. `Sprintf` formats - // and returns a string without printing it anywhere. - s := fmt.Sprintf("a %s", "string") - fmt.Println(s) + // So far we've seen `Printf`, which prints the + // formatted string to `os.Stdout`. `Sprintf` formats + // and returns a string without printing it anywhere. + s := fmt.Sprintf("a %s", "string") + fmt.Println(s) - // You can format+print to `io.Writers` other than - // `os.Stdout` using `Fprintf`. - fmt.Fprintf(os.Stderr, "an %s\n", "error") + // You can format+print to `io.Writers` other than + // `os.Stdout` using `Fprintf`. + fmt.Fprintf(os.Stderr, "an %s\n", "error") } diff --git a/examples/string-formatting/string-formatting.hash b/examples/string-formatting/string-formatting.hash index c035045..ba1b396 100644 --- a/examples/string-formatting/string-formatting.hash +++ b/examples/string-formatting/string-formatting.hash @@ -1,2 +1,2 @@ 5f39ae6d8f26d59a688a9a9d7d13a5c1d0f7a08b -JJAAFGxHVq +CkBQ3CFpHQ9 diff --git a/examples/string-functions/string-functions.go b/examples/string-functions/string-functions.go index eea809a..c8f2b54 100644 --- a/examples/string-functions/string-functions.go +++ b/examples/string-functions/string-functions.go @@ -13,32 +13,32 @@ var p = fmt.Println func main() { - // Here's a sample of the functions available in - // `strings`. Since these are functions from the - // package, not methods on the string object itself, - // we need pass the string in question as the first - // argument to the function. You can find more - // functions in the [`strings`](http://golang.org/pkg/strings/) - // package docs. - p("Contains: ", s.Contains("test", "es")) - p("Count: ", s.Count("test", "t")) - p("HasPrefix: ", s.HasPrefix("test", "te")) - p("HasSuffix: ", s.HasSuffix("test", "st")) - p("Index: ", s.Index("test", "e")) - p("Join: ", s.Join([]string{"a", "b"}, "-")) - p("Repeat: ", s.Repeat("a", 5)) - p("Replace: ", s.Replace("foo", "o", "0", -1)) - p("Replace: ", s.Replace("foo", "o", "0", 1)) - p("Split: ", s.Split("a-b-c-d-e", "-")) - p("ToLower: ", s.ToLower("TEST")) - p("ToUpper: ", s.ToUpper("test")) - p() + // Here's a sample of the functions available in + // `strings`. Since these are functions from the + // package, not methods on the string object itself, + // we need pass the string in question as the first + // argument to the function. You can find more + // functions in the [`strings`](http://golang.org/pkg/strings/) + // package docs. + p("Contains: ", s.Contains("test", "es")) + p("Count: ", s.Count("test", "t")) + p("HasPrefix: ", s.HasPrefix("test", "te")) + p("HasSuffix: ", s.HasSuffix("test", "st")) + p("Index: ", s.Index("test", "e")) + p("Join: ", s.Join([]string{"a", "b"}, "-")) + p("Repeat: ", s.Repeat("a", 5)) + p("Replace: ", s.Replace("foo", "o", "0", -1)) + p("Replace: ", s.Replace("foo", "o", "0", 1)) + p("Split: ", s.Split("a-b-c-d-e", "-")) + p("ToLower: ", s.ToLower("TEST")) + p("ToUpper: ", s.ToUpper("test")) + p() - // Not part of `strings`, but worth mentioning here, are - // the mechanisms for getting the length of a string in - // bytes and getting a byte by index. - p("Len: ", len("hello")) - p("Char:", "hello"[1]) + // Not part of `strings`, but worth mentioning here, are + // the mechanisms for getting the length of a string in + // bytes and getting a byte by index. + p("Len: ", len("hello")) + p("Char:", "hello"[1]) } // Note that `len` and indexing above work at the byte level. diff --git a/examples/string-functions/string-functions.hash b/examples/string-functions/string-functions.hash index 93ae1ea..068746c 100644 --- a/examples/string-functions/string-functions.hash +++ b/examples/string-functions/string-functions.hash @@ -1,2 +1,2 @@ 17aa523bbd606fa0b624fae44b89812d46330755 -Lf5_Zbg6or +Vn4D3y4_711 diff --git a/examples/structs/structs.go b/examples/structs/structs.go index 9345550..6cf5629 100644 --- a/examples/structs/structs.go +++ b/examples/structs/structs.go @@ -8,34 +8,34 @@ import "fmt" // This `person` struct type has `name` and `age` fields. type person struct { - name string - age int + name string + age int } func main() { - // This syntax creates a new struct. - fmt.Println(person{"Bob", 20}) + // This syntax creates a new struct. + fmt.Println(person{"Bob", 20}) - // You can name the fields when initializing a struct. - fmt.Println(person{name: "Alice", age: 30}) + // You can name the fields when initializing a struct. + fmt.Println(person{name: "Alice", age: 30}) - // Omitted fields will be zero-valued. - fmt.Println(person{name: "Fred"}) + // Omitted fields will be zero-valued. + fmt.Println(person{name: "Fred"}) - // An `&` prefix yields a pointer to the struct. - fmt.Println(&person{name: "Ann", age: 40}) + // An `&` prefix yields a pointer to the struct. + fmt.Println(&person{name: "Ann", age: 40}) - // Access struct fields with a dot. - s := person{name: "Sean", age: 50} - fmt.Println(s.name) + // Access struct fields with a dot. + s := person{name: "Sean", age: 50} + fmt.Println(s.name) - // You can also use dots with struct pointers - the - // pointers are automatically dereferenced. - sp := &s - fmt.Println(sp.age) + // You can also use dots with struct pointers - the + // pointers are automatically dereferenced. + sp := &s + fmt.Println(sp.age) - // Structs are mutable. - sp.age = 51 - fmt.Println(sp.age) + // Structs are mutable. + sp.age = 51 + fmt.Println(sp.age) } diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index 9004363..2c0e37f 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ 49cad39331ee5e9fb8d8dad99d3aff7f18a4e6d0 -OMCP5KFC10 +XMZpGsF4sWM diff --git a/examples/switch/switch.go b/examples/switch/switch.go index 4df7afe..8d72bee 100644 --- a/examples/switch/switch.go +++ b/examples/switch/switch.go @@ -8,54 +8,54 @@ import "time" func main() { - // Here's a basic `switch`. - i := 2 - fmt.Print("Write ", i, " as ") - switch i { - case 1: - fmt.Println("one") - case 2: - fmt.Println("two") - case 3: - fmt.Println("three") - } + // Here's a basic `switch`. + i := 2 + fmt.Print("Write ", i, " as ") + switch i { + case 1: + fmt.Println("one") + case 2: + fmt.Println("two") + case 3: + fmt.Println("three") + } - // You can use commas to separate multiple expressions - // in the same `case` statement. We use the optional - // `default` case in this example as well. - switch time.Now().Weekday() { - case time.Saturday, time.Sunday: - fmt.Println("It's the weekend") - default: - fmt.Println("It's a weekday") - } + // You can use commas to separate multiple expressions + // in the same `case` statement. We use the optional + // `default` case in this example as well. + switch time.Now().Weekday() { + case time.Saturday, time.Sunday: + fmt.Println("It's the weekend") + default: + fmt.Println("It's a weekday") + } - // `switch` without an expression is an alternate way - // to express if/else logic. Here we also show how the - // `case` expressions can be non-constants. - t := time.Now() - switch { - case t.Hour() < 12: - fmt.Println("It's before noon") - default: - fmt.Println("It's after noon") - } + // `switch` without an expression is an alternate way + // to express if/else logic. Here we also show how the + // `case` expressions can be non-constants. + t := time.Now() + switch { + case t.Hour() < 12: + fmt.Println("It's before noon") + default: + fmt.Println("It's after noon") + } - // A type `switch` compares types instead of values. You - // can use this to discover the type of an interface - // value. In this example, the variable `t` will have the - // type corresponding to its clause. - whatAmI := func(i interface{}) { - switch t := i.(type) { - case bool: - fmt.Println("I'm a bool") - case int: - fmt.Println("I'm an int") - default: - fmt.Printf("Don't know type %T\n", t) - } - } - whatAmI(true) - whatAmI(1) - whatAmI("hey") + // A type `switch` compares types instead of values. You + // can use this to discover the type of an interface + // value. In this example, the variable `t` will have the + // type corresponding to its clause. + whatAmI := func(i interface{}) { + switch t := i.(type) { + case bool: + fmt.Println("I'm a bool") + case int: + fmt.Println("I'm an int") + default: + fmt.Printf("Don't know type %T\n", t) + } + } + whatAmI(true) + whatAmI(1) + whatAmI("hey") } diff --git a/examples/tickers/tickers.go b/examples/tickers/tickers.go index ef55c97..110a192 100644 --- a/examples/tickers/tickers.go +++ b/examples/tickers/tickers.go @@ -11,21 +11,21 @@ import "fmt" func main() { - // Tickers use a similar mechanism to timers: a - // channel that is sent values. Here we'll use the - // `range` builtin on the channel to iterate over - // the values as they arrive every 500ms. - ticker := time.NewTicker(500 * time.Millisecond) - go func() { - for t := range ticker.C { - fmt.Println("Tick at", t) - } - }() + // Tickers use a similar mechanism to timers: a + // channel that is sent values. Here we'll use the + // `range` builtin on the channel to iterate over + // the values as they arrive every 500ms. + ticker := time.NewTicker(500 * time.Millisecond) + go func() { + for t := range ticker.C { + fmt.Println("Tick at", t) + } + }() - // Tickers can be stopped like timers. Once a ticker - // is stopped it won't receive any more values on its - // channel. We'll stop ours after 1600ms. - time.Sleep(1600 * time.Millisecond) - ticker.Stop() - fmt.Println("Ticker stopped") + // Tickers can be stopped like timers. Once a ticker + // is stopped it won't receive any more values on its + // channel. We'll stop ours after 1600ms. + time.Sleep(1600 * time.Millisecond) + ticker.Stop() + fmt.Println("Ticker stopped") } diff --git a/examples/time-formatting-parsing/time-formatting-parsing.go b/examples/time-formatting-parsing/time-formatting-parsing.go index 337ccd5..a213baf 100644 --- a/examples/time-formatting-parsing/time-formatting-parsing.go +++ b/examples/time-formatting-parsing/time-formatting-parsing.go @@ -7,44 +7,44 @@ import "fmt" import "time" func main() { - p := fmt.Println + p := fmt.Println - // Here's a basic example of formatting a time - // according to RFC3339, using the corresponding layout - // constant. - t := time.Now() - p(t.Format(time.RFC3339)) + // Here's a basic example of formatting a time + // according to RFC3339, using the corresponding layout + // constant. + t := time.Now() + p(t.Format(time.RFC3339)) - // Time parsing uses the same layout values as `Format`. - t1, e := time.Parse( - time.RFC3339, - "2012-11-01T22:08:41+00:00") - p(t1) + // Time parsing uses the same layout values as `Format`. + t1, e := time.Parse( + time.RFC3339, + "2012-11-01T22:08:41+00:00") + p(t1) - // `Format` and `Parse` use example-based layouts. Usually - // you'll use a constant from `time` for these layouts, but - // you can also supply custom layouts. Layouts must use the - // reference time `Mon Jan 2 15:04:05 MST 2006` to show the - // pattern with which to format/parse a given time/string. - // The example time must be exactly as shown: the year 2006, - // 15 for the hour, Monday for the day of the week, etc. - 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")) - form := "3 04 PM" - t2, e := time.Parse(form, "8 41 PM") - p(t2) + // `Format` and `Parse` use example-based layouts. Usually + // you'll use a constant from `time` for these layouts, but + // you can also supply custom layouts. Layouts must use the + // reference time `Mon Jan 2 15:04:05 MST 2006` to show the + // pattern with which to format/parse a given time/string. + // The example time must be exactly as shown: the year 2006, + // 15 for the hour, Monday for the day of the week, etc. + 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")) + form := "3 04 PM" + t2, e := time.Parse(form, "8 41 PM") + p(t2) - // For purely numeric representations you can also - // use standard string formatting with the extracted - // 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()) + // For purely numeric representations you can also + // use standard string formatting with the extracted + // 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()) - // `Parse` will return an error on malformed input - // explaining the parsing problem. - ansic := "Mon Jan _2 15:04:05 2006" - _, e = time.Parse(ansic, "8:41PM") - p(e) + // `Parse` will return an error on malformed input + // explaining the parsing problem. + ansic := "Mon Jan _2 15:04:05 2006" + _, e = time.Parse(ansic, "8:41PM") + p(e) } diff --git a/examples/time-formatting-parsing/time-formatting-parsing.hash b/examples/time-formatting-parsing/time-formatting-parsing.hash index 25ae213..0d05bde 100644 --- a/examples/time-formatting-parsing/time-formatting-parsing.hash +++ b/examples/time-formatting-parsing/time-formatting-parsing.hash @@ -1,2 +1,2 @@ 1f9962260f5c92efe57db0b96099b3dd06c90333 -BFw556nWcM +nHAisH6amZG diff --git a/examples/time/time.go b/examples/time/time.go index 48af525..1d01432 100644 --- a/examples/time/time.go +++ b/examples/time/time.go @@ -7,55 +7,55 @@ import "fmt" import "time" func main() { - p := fmt.Println + p := fmt.Println - // We'll start by getting the current time. - now := time.Now() - p(now) + // We'll start by getting the current time. + now := time.Now() + p(now) - // You can build a `time` struct by providing the - // year, month, day, etc. Times are always associated - // with a `Location`, i.e. time zone. - then := time.Date( - 2009, 11, 17, 20, 34, 58, 651387237, time.UTC) - p(then) + // You can build a `time` struct by providing the + // year, month, day, etc. Times are always associated + // with a `Location`, i.e. time zone. + then := time.Date( + 2009, 11, 17, 20, 34, 58, 651387237, time.UTC) + p(then) - // You can extract the various components of the time - // value as expected. - p(then.Year()) - p(then.Month()) - p(then.Day()) - p(then.Hour()) - p(then.Minute()) - p(then.Second()) - p(then.Nanosecond()) - p(then.Location()) + // You can extract the various components of the time + // value as expected. + p(then.Year()) + p(then.Month()) + p(then.Day()) + p(then.Hour()) + p(then.Minute()) + p(then.Second()) + p(then.Nanosecond()) + p(then.Location()) - // The Monday-Sunday `Weekday` is also available. - p(then.Weekday()) + // The Monday-Sunday `Weekday` is also available. + p(then.Weekday()) - // These methods compare two times, testing if the - // first occurs before, after, or at the same time - // as the second, respectively. - p(then.Before(now)) - p(then.After(now)) - p(then.Equal(now)) + // These methods compare two times, testing if the + // first occurs before, after, or at the same time + // as the second, respectively. + p(then.Before(now)) + p(then.After(now)) + p(then.Equal(now)) - // The `Sub` methods returns a `Duration` representing - // the interval between two times. - diff := now.Sub(then) - p(diff) + // The `Sub` methods returns a `Duration` representing + // the interval between two times. + diff := now.Sub(then) + p(diff) - // We can compute the length of the duration in - // various units. - p(diff.Hours()) - p(diff.Minutes()) - p(diff.Seconds()) - p(diff.Nanoseconds()) + // We can compute the length of the duration in + // various units. + p(diff.Hours()) + p(diff.Minutes()) + p(diff.Seconds()) + p(diff.Nanoseconds()) - // You can use `Add` to advance a time by a given - // duration, or with a `-` to move backwards by a - // duration. - p(then.Add(diff)) - p(then.Add(-diff)) + // You can use `Add` to advance a time by a given + // duration, or with a `-` to move backwards by a + // duration. + p(then.Add(diff)) + p(then.Add(-diff)) } diff --git a/examples/time/time.hash b/examples/time/time.hash index c588c78..9542207 100644 --- a/examples/time/time.hash +++ b/examples/time/time.hash @@ -1,2 +1,2 @@ b6308f1fea7665e89a28f54aac6cb49b95685eb5 -TTYPzggHg0 +PZMCzzaJURJ diff --git a/examples/timeouts/timeouts.go b/examples/timeouts/timeouts.go index 2f110d1..ccc9ecb 100644 --- a/examples/timeouts/timeouts.go +++ b/examples/timeouts/timeouts.go @@ -10,39 +10,39 @@ import "fmt" func main() { - // For our example, suppose we're executing an external - // call that returns its result on a channel `c1` - // after 2s. - c1 := make(chan string, 1) - go func() { - time.Sleep(2 * time.Second) - c1 <- "result 1" - }() + // For our example, suppose we're executing an external + // call that returns its result on a channel `c1` + // after 2s. + c1 := make(chan string, 1) + go func() { + time.Sleep(2 * time.Second) + c1 <- "result 1" + }() - // Here's the `select` implementing a timeout. - // `res := <-c1` awaits the result and `<-Time.After` - // awaits a value to be sent after the timeout of - // 1s. Since `select` proceeds with the first - // receive that's ready, we'll take the timeout case - // if the operation takes more than the allowed 1s. - select { - case res := <-c1: - fmt.Println(res) - case <-time.After(1 * time.Second): - fmt.Println("timeout 1") - } + // Here's the `select` implementing a timeout. + // `res := <-c1` awaits the result and `<-Time.After` + // awaits a value to be sent after the timeout of + // 1s. Since `select` proceeds with the first + // receive that's ready, we'll take the timeout case + // if the operation takes more than the allowed 1s. + select { + case res := <-c1: + fmt.Println(res) + case <-time.After(1 * time.Second): + fmt.Println("timeout 1") + } - // If we allow a longer timeout of 3s, then the receive - // from `c2` will succeed and we'll print the result. - c2 := make(chan string, 1) - go func() { - time.Sleep(2 * time.Second) - c2 <- "result 2" - }() - select { - case res := <-c2: - fmt.Println(res) - case <-time.After(3 * time.Second): - fmt.Println("timeout 2") - } + // If we allow a longer timeout of 3s, then the receive + // from `c2` will succeed and we'll print the result. + c2 := make(chan string, 1) + go func() { + time.Sleep(2 * time.Second) + c2 <- "result 2" + }() + select { + case res := <-c2: + fmt.Println(res) + case <-time.After(3 * time.Second): + fmt.Println("timeout 2") + } } diff --git a/examples/timers/timers.go b/examples/timers/timers.go index 61cbdde..939cf11 100644 --- a/examples/timers/timers.go +++ b/examples/timers/timers.go @@ -11,29 +11,29 @@ import "fmt" func main() { - // Timers represent a single event in the future. You - // tell the timer how long you want to wait, and it - // provides a channel that will be notified at that - // time. This timer will wait 2 seconds. - timer1 := time.NewTimer(2 * time.Second) + // Timers represent a single event in the future. You + // tell the timer how long you want to wait, and it + // provides a channel that will be notified at that + // time. This timer will wait 2 seconds. + timer1 := time.NewTimer(2 * time.Second) - // The `<-timer1.C` blocks on the timer's channel `C` - // until it sends a value indicating that the timer - // expired. - <-timer1.C - fmt.Println("Timer 1 expired") + // The `<-timer1.C` blocks on the timer's channel `C` + // until it sends a value indicating that the timer + // expired. + <-timer1.C + fmt.Println("Timer 1 expired") - // If you just wanted to wait, you could have used - // `time.Sleep`. One reason a timer may be useful is - // that you can cancel the timer before it expires. - // Here's an example of that. - timer2 := time.NewTimer(time.Second) - go func() { - <-timer2.C - fmt.Println("Timer 2 expired") - }() - stop2 := timer2.Stop() - if stop2 { - fmt.Println("Timer 2 stopped") - } + // If you just wanted to wait, you could have used + // `time.Sleep`. One reason a timer may be useful is + // that you can cancel the timer before it expires. + // Here's an example of that. + timer2 := time.NewTimer(time.Second) + go func() { + <-timer2.C + fmt.Println("Timer 2 expired") + }() + stop2 := timer2.Stop() + if stop2 { + fmt.Println("Timer 2 stopped") + } } diff --git a/examples/url-parsing/url-parsing.go b/examples/url-parsing/url-parsing.go index a70e71f..b4e0050 100644 --- a/examples/url-parsing/url-parsing.go +++ b/examples/url-parsing/url-parsing.go @@ -9,47 +9,47 @@ import "net/url" func main() { - // We'll parse this example URL, which includes a - // scheme, authentication info, host, port, path, - // query params, and query fragment. - s := "postgres://user:pass@host.com:5432/path?k=v#f" + // We'll parse this example URL, which includes a + // scheme, authentication info, host, port, path, + // query params, and query fragment. + s := "postgres://user:pass@host.com:5432/path?k=v#f" - // Parse the URL and ensure there are no errors. - u, err := url.Parse(s) - if err != nil { - panic(err) - } + // Parse the URL and ensure there are no errors. + u, err := url.Parse(s) + if err != nil { + panic(err) + } - // Accessing the scheme is straightforward. - fmt.Println(u.Scheme) + // Accessing the scheme is straightforward. + fmt.Println(u.Scheme) - // `User` contains all authentication info; call - // `Username` and `Password` on this for individual - // values. - fmt.Println(u.User) - fmt.Println(u.User.Username()) - p, _ := u.User.Password() - fmt.Println(p) + // `User` contains all authentication info; call + // `Username` and `Password` on this for individual + // values. + fmt.Println(u.User) + fmt.Println(u.User.Username()) + p, _ := u.User.Password() + fmt.Println(p) - // The `Host` contains both the hostname and the port, - // if present. Use `SplitHostPort` to extract them. - fmt.Println(u.Host) - host, port, _ := net.SplitHostPort(u.Host) - fmt.Println(host) - fmt.Println(port) + // The `Host` contains both the hostname and the port, + // if present. Use `SplitHostPort` to extract them. + fmt.Println(u.Host) + host, port, _ := net.SplitHostPort(u.Host) + fmt.Println(host) + fmt.Println(port) - // Here we extract the `path` and the fragment after - // the `#`. - fmt.Println(u.Path) - fmt.Println(u.Fragment) + // Here we extract the `path` and the fragment after + // the `#`. + fmt.Println(u.Path) + fmt.Println(u.Fragment) - // To get query params in a string of `k=v` format, - // use `RawQuery`. You can also parse query params - // into a map. The parsed query param maps are from - // strings to slices of strings, so index into `[0]` - // if you only want the first value. - fmt.Println(u.RawQuery) - m, _ := url.ParseQuery(u.RawQuery) - fmt.Println(m) - fmt.Println(m["k"][0]) + // To get query params in a string of `k=v` format, + // use `RawQuery`. You can also parse query params + // into a map. The parsed query param maps are from + // strings to slices of strings, so index into `[0]` + // if you only want the first value. + fmt.Println(u.RawQuery) + m, _ := url.ParseQuery(u.RawQuery) + fmt.Println(m) + fmt.Println(m["k"][0]) } diff --git a/examples/values/values.go b/examples/values/values.go index 4618c67..2d34a4b 100644 --- a/examples/values/values.go +++ b/examples/values/values.go @@ -8,15 +8,15 @@ import "fmt" func main() { - // Strings, which can be added together with `+`. - fmt.Println("go" + "lang") + // Strings, which can be added together with `+`. + fmt.Println("go" + "lang") - // Integers and floats. - fmt.Println("1+1 =", 1+1) - fmt.Println("7.0/3.0 =", 7.0/3.0) + // Integers and floats. + fmt.Println("1+1 =", 1+1) + fmt.Println("7.0/3.0 =", 7.0/3.0) - // Booleans, with boolean operators as you'd expect. - fmt.Println(true && false) - fmt.Println(true || false) - fmt.Println(!true) + // Booleans, with boolean operators as you'd expect. + fmt.Println(true && false) + fmt.Println(true || false) + fmt.Println(!true) } diff --git a/examples/values/values.hash b/examples/values/values.hash index 7343a3c..b10176b 100644 --- a/examples/values/values.hash +++ b/examples/values/values.hash @@ -1,2 +1,2 @@ c5a53c75cc57dc15ac4458285c9b139bf85c67bf -fgGVOyuZdu +aGiVohrYqYC diff --git a/examples/variables/variables.go b/examples/variables/variables.go index abff6b9..8e0912f 100644 --- a/examples/variables/variables.go +++ b/examples/variables/variables.go @@ -8,27 +8,27 @@ import "fmt" func main() { - // `var` declares 1 or more variables. - var a = "initial" - fmt.Println(a) + // `var` declares 1 or more variables. + var a = "initial" + fmt.Println(a) - // You can declare multiple variables at once. - var b, c int = 1, 2 - fmt.Println(b, c) + // You can declare multiple variables at once. + var b, c int = 1, 2 + fmt.Println(b, c) - // Go will infer the type of initialized variables. - var d = true - fmt.Println(d) + // Go will infer the type of initialized variables. + var d = true + fmt.Println(d) - // Variables declared without a corresponding - // initialization are _zero-valued_. For example, the - // zero value for an `int` is `0`. - var e int - fmt.Println(e) + // Variables declared without a corresponding + // initialization are _zero-valued_. For example, the + // zero value for an `int` is `0`. + var e int + fmt.Println(e) - // The `:=` syntax is shorthand for declaring and - // initializing a variable, e.g. for - // `var f string = "apple"` in this case. - f := "apple" - fmt.Println(f) + // The `:=` syntax is shorthand for declaring and + // initializing a variable, e.g. for + // `var f string = "apple"` in this case. + f := "apple" + fmt.Println(f) } diff --git a/examples/variadic-functions/variadic-functions.go b/examples/variadic-functions/variadic-functions.go index 5ee4ef2..02c67a5 100644 --- a/examples/variadic-functions/variadic-functions.go +++ b/examples/variadic-functions/variadic-functions.go @@ -10,24 +10,24 @@ import "fmt" // Here's a function that will take an arbitrary number // of `int`s as arguments. func sum(nums ...int) { - fmt.Print(nums, " ") - total := 0 - for _, num := range nums { - total += num - } - fmt.Println(total) + fmt.Print(nums, " ") + total := 0 + for _, num := range nums { + total += num + } + fmt.Println(total) } func main() { - // Variadic functions can be called in the usual way - // with individual arguments. - sum(1, 2) - sum(1, 2, 3) + // Variadic functions can be called in the usual way + // with individual arguments. + sum(1, 2) + sum(1, 2, 3) - // If you already have multiple args in a slice, - // apply them to a variadic function using - // `func(slice...)` like this. - nums := []int{1, 2, 3, 4} - sum(nums...) + // If you already have multiple args in a slice, + // apply them to a variadic function using + // `func(slice...)` like this. + nums := []int{1, 2, 3, 4} + sum(nums...) } diff --git a/examples/waitgroups/waitgroups.go b/examples/waitgroups/waitgroups.go index dc8d0c1..2cf16a3 100644 --- a/examples/waitgroups/waitgroups.go +++ b/examples/waitgroups/waitgroups.go @@ -4,39 +4,39 @@ package main import ( - "fmt" - "sync" - "time" + "fmt" + "sync" + "time" ) // This is the function we'll run in every goroutine. // Note that a WaitGroup must be passed to functions by // pointer. func worker(id int, wg *sync.WaitGroup) { - fmt.Printf("Worker %d starting\n", id) + fmt.Printf("Worker %d starting\n", id) - // Sleep to simulate an expensive task. - time.Sleep(time.Second) - fmt.Printf("Worker %d done\n", id) + // Sleep to simulate an expensive task. + time.Sleep(time.Second) + fmt.Printf("Worker %d done\n", id) - // Notify the WaitGroup that this worker is done. - wg.Done() + // Notify the WaitGroup that this worker is done. + wg.Done() } func main() { - // This WaitGroup is used to wait for all the - // goroutines launched here to finish. - var wg sync.WaitGroup + // This WaitGroup is used to wait for all the + // goroutines launched here to finish. + var wg sync.WaitGroup - // Launch several goroutines and increment the WaitGroup - // counter for each. - for i := 1; i <= 5; i++ { - wg.Add(1) - go worker(i, &wg) - } + // Launch several goroutines and increment the WaitGroup + // counter for each. + for i := 1; i <= 5; i++ { + wg.Add(1) + go worker(i, &wg) + } - // Block until the WaitGroup counter goes back to 0; - // all the workers notified they're done. - wg.Wait() + // Block until the WaitGroup counter goes back to 0; + // all the workers notified they're done. + wg.Wait() } diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index eabda7a..84c8bf1 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -12,40 +12,40 @@ import "time" // results on `results`. We'll sleep a second per job to // simulate an expensive task. func worker(id int, jobs <-chan int, results chan<- int) { - for j := range jobs { - fmt.Println("worker", id, "started job", j) - time.Sleep(time.Second) - fmt.Println("worker", id, "finished job", j) - results <- j * 2 - } + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } } func main() { - // In order to use our pool of workers we need to send - // them work and collect their results. We make 2 - // channels for this. - jobs := make(chan int, 100) - results := make(chan int, 100) + // In order to use our pool of workers we need to send + // them work and collect their results. We make 2 + // channels for this. + jobs := make(chan int, 100) + results := make(chan int, 100) - // This starts up 3 workers, initially blocked - // because there are no jobs yet. - for w := 1; w <= 3; w++ { - go worker(w, jobs, results) - } + // This starts up 3 workers, initially blocked + // because there are no jobs yet. + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } - // Here we send 5 `jobs` and then `close` that - // channel to indicate that's all the work we have. - for j := 1; j <= 5; j++ { - jobs <- j - } - close(jobs) + // Here we send 5 `jobs` and then `close` that + // channel to indicate that's all the work we have. + for j := 1; j <= 5; j++ { + jobs <- j + } + close(jobs) - // Finally we collect all the results of the work. - // This also ensures that the worker goroutines have - // finished. An alternative way to wait for multiple - // goroutines is to use a [WaitGroup](waitgroups). - for a := 1; a <= 5; a++ { - <-results - } + // Finally we collect all the results of the work. + // This also ensures that the worker goroutines have + // finished. An alternative way to wait for multiple + // goroutines is to use a [WaitGroup](waitgroups). + for a := 1; a <= 5; a++ { + <-results + } } diff --git a/examples/writing-files/writing-files.go b/examples/writing-files/writing-files.go index 864182e..82275ce 100644 --- a/examples/writing-files/writing-files.go +++ b/examples/writing-files/writing-files.go @@ -4,55 +4,55 @@ package main import ( - "bufio" - "fmt" - "io/ioutil" - "os" + "bufio" + "fmt" + "io/ioutil" + "os" ) func check(e error) { - if e != nil { - panic(e) - } + if e != nil { + panic(e) + } } func main() { - // To start, here's how to dump a string (or just - // bytes) into a file. - d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("/tmp/dat1", d1, 0644) - check(err) + // To start, here's how to dump a string (or just + // bytes) into a file. + d1 := []byte("hello\ngo\n") + err := ioutil.WriteFile("/tmp/dat1", d1, 0644) + check(err) - // For more granular writes, open a file for writing. - f, err := os.Create("/tmp/dat2") - check(err) + // For more granular writes, open a file for writing. + f, err := os.Create("/tmp/dat2") + check(err) - // It's idiomatic to defer a `Close` immediately - // after opening a file. - defer f.Close() + // It's idiomatic to defer a `Close` immediately + // after opening a file. + defer f.Close() - // You can `Write` byte slices as you'd expect. - d2 := []byte{115, 111, 109, 101, 10} - n2, err := f.Write(d2) - check(err) - fmt.Printf("wrote %d bytes\n", n2) + // You can `Write` byte slices as you'd expect. + d2 := []byte{115, 111, 109, 101, 10} + n2, err := f.Write(d2) + check(err) + fmt.Printf("wrote %d bytes\n", n2) - // A `WriteString` is also available. - n3, err := f.WriteString("writes\n") - fmt.Printf("wrote %d bytes\n", n3) + // A `WriteString` is also available. + n3, err := f.WriteString("writes\n") + fmt.Printf("wrote %d bytes\n", n3) - // Issue a `Sync` to flush writes to stable storage. - f.Sync() + // Issue a `Sync` to flush writes to stable storage. + f.Sync() - // `bufio` provides buffered writers in addition - // to the buffered readers we saw earlier. - w := bufio.NewWriter(f) - n4, err := w.WriteString("buffered\n") - fmt.Printf("wrote %d bytes\n", n4) + // `bufio` provides buffered writers in addition + // to the buffered readers we saw earlier. + w := bufio.NewWriter(f) + n4, err := w.WriteString("buffered\n") + fmt.Printf("wrote %d bytes\n", n4) - // Use `Flush` to ensure all buffered operations have - // been applied to the underlying writer. - w.Flush() + // Use `Flush` to ensure all buffered operations have + // been applied to the underlying writer. + w.Flush() } diff --git a/examples/writing-files/writing-files.hash b/examples/writing-files/writing-files.hash index 16a7fd6..360897a 100644 --- a/examples/writing-files/writing-files.hash +++ b/examples/writing-files/writing-files.hash @@ -1,2 +1,2 @@ 0853ca57176872e9b34b501855ceb8bf5fbdbf46 -5usz1Oc-xY +gyJn9PcndtP diff --git a/public/arrays b/public/arrays index c32e5b9..e4e2d88 100644 --- a/public/arrays +++ b/public/arrays @@ -28,7 +28,7 @@ specific length.

    - +
    package main
     
    diff --git a/public/channel-buffering b/public/channel-buffering index 5cf8cb1..d7e54fd 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -32,7 +32,7 @@ those values.

    - +
    package main
     
    diff --git a/public/channel-directions b/public/channel-directions index d989de8..5b0150f 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -30,7 +30,7 @@ the program.

    - +
    package main
     
    diff --git a/public/channels b/public/channels index a41776a..4616272 100644 --- a/public/channels +++ b/public/channels @@ -30,7 +30,7 @@ goroutine.

    - +
    package main
     
    diff --git a/public/closing-channels b/public/closing-channels index 3ad1396..3bf9b4b 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -29,7 +29,7 @@ completion to the channel’s receivers.

    - +
    package main
     
    diff --git a/public/command-line-arguments b/public/command-line-arguments index 02470c5..5943299 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -30,7 +30,7 @@ For example, go run hello.go uses run and - +
    package main
     
    diff --git a/public/command-line-flags b/public/command-line-flags index b2eb253..3678600 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -30,7 +30,7 @@ command-line flag.

    - +
    package main
     
    diff --git a/public/defer b/public/defer index 6e2ed91..eeff3b8 100644 --- a/public/defer +++ b/public/defer @@ -30,7 +30,7 @@ purposes of cleanup. defer is often used where e.g. - +
    package main
     
    diff --git a/public/environment-variables b/public/environment-variables index 4d8d276..e0b7c26 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -30,7 +30,7 @@ Let’s look at how to set, get, and list environment variables.

    - +
    package main
     
    diff --git a/public/epoch b/public/epoch index aff0719..0ae0cf2 100644 --- a/public/epoch +++ b/public/epoch @@ -30,7 +30,7 @@ Here’s how to do it in Go.

    - +
    package main
     
    diff --git a/public/execing-processes b/public/execing-processes index 00af59f..2fc8e94 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -35,7 +35,7 @@ function.

    - +
    package main
     
    diff --git a/public/exit b/public/exit index bb8c7d8..f92266a 100644 --- a/public/exit +++ b/public/exit @@ -28,7 +28,7 @@ status.

    - +
    package main
     
    diff --git a/public/for b/public/for index 6dc96af..68db267 100644 --- a/public/for +++ b/public/for @@ -28,7 +28,7 @@ three basic types of for loops.

    - +
    package main
     
    diff --git a/public/functions b/public/functions index 7f21857..94acc61 100644 --- a/public/functions +++ b/public/functions @@ -28,7 +28,7 @@ functions with a few different examples.

    - +
    package main
     
    diff --git a/public/hello-world b/public/hello-world index 49a6220..bd9c439 100644 --- a/public/hello-world +++ b/public/hello-world @@ -18,7 +18,7 @@ message. Here’s the full source code.

    - +
    package main
     
    @@ -80,7 +80,7 @@ binaries. We can do this using go build.

    $ go build hello-world.go
     $ ls
    -hello-world	hello-world.go
    +hello-world    hello-world.go
     
    diff --git a/public/if-else b/public/if-else index 00787c4..0ee016d 100644 --- a/public/if-else +++ b/public/if-else @@ -28,7 +28,7 @@ straight-forward.

    - +
    package main
     
    diff --git a/public/interfaces b/public/interfaces index c0f956e..ea4ebda 100644 --- a/public/interfaces +++ b/public/interfaces @@ -28,7 +28,7 @@ signatures.

    - +
    package main
     
    diff --git a/public/line-filters b/public/line-filters index 93b704a..0b7b0a5 100644 --- a/public/line-filters +++ b/public/line-filters @@ -33,7 +33,7 @@ pattern to write your own Go line filters.

    - +
    package main
     
    diff --git a/public/methods b/public/methods index ef53567..2638234 100644 --- a/public/methods +++ b/public/methods @@ -27,7 +27,7 @@ - +
    package main
     
    diff --git a/public/multiple-return-values b/public/multiple-return-values index 3961507..ed3692d 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -29,7 +29,7 @@ to return both result and error values from a function.

    - +
    package main
     
    diff --git a/public/number-parsing b/public/number-parsing index 56c83a2..0e509da 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -28,7 +28,7 @@ in many programs; here’s how to do it in Go.

    - +
    package main
     
    diff --git a/public/panic b/public/panic index 10fc46b..c3e3621 100644 --- a/public/panic +++ b/public/panic @@ -30,7 +30,7 @@ aren’t prepared to handle gracefully.

    - +
    package main
     
    @@ -124,7 +124,7 @@ a non-zero status.

    goroutine 1 [running]:
     main.main()
    -	/.../panic.go:12 +0x47
    +    /.../panic.go:12 +0x47
     ...
     exit status 2
     
    diff --git a/public/pointers b/public/pointers index e24ff9b..5959923 100644 --- a/public/pointers +++ b/public/pointers @@ -29,7 +29,7 @@ within your program.

    - +
    package main
     
    diff --git a/public/random-numbers b/public/random-numbers index 1d7ebd8..393d10c 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -29,7 +29,7 @@ generation.

    - +
    package main
     
    diff --git a/public/range b/public/range index ead2dea..70ac079 100644 --- a/public/range +++ b/public/range @@ -29,7 +29,7 @@ of the data structures we’ve already learned.

    - +
    package main
     
    diff --git a/public/range-over-channels b/public/range-over-channels index b6cb1a6..36222c6 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -30,7 +30,7 @@ values received from a channel.

    - +
    package main
     
    diff --git a/public/reading-files b/public/reading-files index 4aeef67..2e573cd 100644 --- a/public/reading-files +++ b/public/reading-files @@ -29,7 +29,7 @@ reading files.

    - +
    package main
     
    diff --git a/public/recursion b/public/recursion index 2bb2a9d..08d0857 100644 --- a/public/recursion +++ b/public/recursion @@ -29,7 +29,7 @@ Here’s a classic factorial example.

    - +
    package main
     
    diff --git a/public/regular-expressions b/public/regular-expressions index 0fdd469..9ff0a95 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -29,7 +29,7 @@ in Go.

    - +
    package main
     
    diff --git a/public/select b/public/select index 12a5aa2..87f7051 100644 --- a/public/select +++ b/public/select @@ -148,7 +148,7 @@ concurrently.

    -
    real	0m2.245s
    +            
    real    0m2.245s
     
    diff --git a/public/sha1-hashes b/public/sha1-hashes index a0cb8c5..7daa377 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -32,7 +32,7 @@ compute SHA1 hashes in Go.

    - +
    package main
     
    diff --git a/public/signals b/public/signals index f38a239..85849f7 100644 --- a/public/signals +++ b/public/signals @@ -32,7 +32,7 @@ Here’s how to handle signals in Go with channels.

    - +
    package main
     
    diff --git a/public/sorting b/public/sorting index eacc67d..aa4c760 100644 --- a/public/sorting +++ b/public/sorting @@ -29,7 +29,7 @@ builtins first.

    - +
    package main
     
    diff --git a/public/spawning-processes b/public/spawning-processes index eecc288..b175ead 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -32,7 +32,7 @@ of spawning processes from Go.

    - +
    package main
     
    diff --git a/public/string-formatting b/public/string-formatting index 202ca19..3188935 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -29,7 +29,7 @@ common string formatting tasks.

    - +
    package main
     
    diff --git a/public/string-functions b/public/string-functions index bcf2866..1fdf4cf 100644 --- a/public/string-functions +++ b/public/string-functions @@ -29,7 +29,7 @@ to give you a sense of the package.

    - +
    package main
     
    diff --git a/public/structs b/public/structs index f42c329..5d6273d 100644 --- a/public/structs +++ b/public/structs @@ -29,7 +29,7 @@ records.

    - +
    package main
     
    diff --git a/public/time b/public/time index cfd8b5c..e5c1fe4 100644 --- a/public/time +++ b/public/time @@ -28,7 +28,7 @@ here are some examples.

    - +
    package main
     
    diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index 6e79f33..b90c585 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -28,7 +28,7 @@ pattern-based layouts.

    - +
    package main
     
    diff --git a/public/values b/public/values index 057fa53..57317d7 100644 --- a/public/values +++ b/public/values @@ -29,7 +29,7 @@ basic examples.

    - +
    package main
     
    diff --git a/public/worker-pools b/public/worker-pools index 5d14690..e437df8 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -188,7 +188,7 @@ there are 3 workers operating concurrently.

    -
    real	0m2.358s
    +            
    real    0m2.358s
     
    diff --git a/public/writing-files b/public/writing-files index 4280238..b1a3fb9 100644 --- a/public/writing-files +++ b/public/writing-files @@ -28,7 +28,7 @@ ones we saw earlier for reading.

    - +
    package main
     
    diff --git a/tools/format b/tools/format index cdec6a5..457b13f 100755 --- a/tools/format +++ b/tools/format @@ -4,24 +4,6 @@ set -eo pipefail paths=$(ls examples/*/*.go) -gbe_to_4spaces() { - local os=$(tr [A-Z] [a-z] <<< "`uname`") - case $os in - darwin*) - sed -i '' -e 's/ / /g' $1 - ;; - linux*) - sed -i -e 's/ / /g' $1 - ;; - *) - echo "$os is not supported." - echo "Add a proper 'sed' command for your platform to ./tools/format" - return 1 - ;; - esac -} - for path in $paths; do gofmt -w=true $path - gbe_to_4spaces $path done diff --git a/tools/generate.go b/tools/generate.go index c30137f..32f542c 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -3,7 +3,6 @@ package main import ( "crypto/sha1" "fmt" - "github.com/russross/blackfriday" "io/ioutil" "net/http" "os" @@ -12,6 +11,8 @@ import ( "regexp" "strings" "text/template" + + "github.com/russross/blackfriday" ) var cacheDir = "/tmp/gobyexample-cache" @@ -152,7 +153,11 @@ func resetURLHashFile(codehash, code, sourcePath string) string { } func parseSegs(sourcePath string) ([]*Seg, string) { - lines := readLines(sourcePath) + var lines []string + // Convert tabs to spaces for uniform rendering. + for _, line := range readLines(sourcePath) { + lines = append(lines, strings.Replace(line, "\t", " ", -1)) + } filecontent := strings.Join(lines, "\n") segs := []*Seg{} lastSeen := "" diff --git a/tools/measure.go b/tools/measure.go index a4fafb1..eb26378 100644 --- a/tools/measure.go +++ b/tools/measure.go @@ -32,6 +32,9 @@ func main() { foundLongLine := false lines := readLines(sourcePath) for i, line := range lines { + // Convert tabs to spaces before measuring, so we get an accurate measure + // of how long the output will end up being. + line := strings.Replace(line, "\t", " ", -1) if !foundLongLine && !commentPat.MatchString(line) && (utf8.RuneCountInString(line) > 58) { fmt.Printf("measure: %s:%d\n", sourcePath, i+1) foundLongLine = true From c6a401d2a3e4d726148552e1cfafd03ceb671f62 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:32:51 -0700 Subject: [PATCH 084/133] Rebuild subcommands for tabs --- .../command-line-subcommands.go | 76 +++++++++---------- public/command-line-subcommands | 2 +- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/command-line-subcommands/command-line-subcommands.go b/examples/command-line-subcommands/command-line-subcommands.go index af57b21..e2d41ed 100644 --- a/examples/command-line-subcommands/command-line-subcommands.go +++ b/examples/command-line-subcommands/command-line-subcommands.go @@ -8,50 +8,50 @@ package main import ( - "flag" - "fmt" - "os" + "flag" + "fmt" + "os" ) func main() { - // We declare a subcommand using the `NewFlagSet` - // function, and proceed to define new flags specific - // for this subcommand. - fooCmd := flag.NewFlagSet("foo", flag.ExitOnError) - fooEnable := fooCmd.Bool("enable", false, "enable") - fooName := fooCmd.String("name", "", "name") + // We declare a subcommand using the `NewFlagSet` + // function, and proceed to define new flags specific + // for this subcommand. + fooCmd := flag.NewFlagSet("foo", flag.ExitOnError) + fooEnable := fooCmd.Bool("enable", false, "enable") + fooName := fooCmd.String("name", "", "name") - // For a different subcommand we can define different - // supported flags. - barCmd := flag.NewFlagSet("bar", flag.ExitOnError) - barLevel := barCmd.Int("level", 0, "level") + // For a different subcommand we can define different + // supported flags. + barCmd := flag.NewFlagSet("bar", flag.ExitOnError) + barLevel := barCmd.Int("level", 0, "level") - // The subcommand is expected as the first argument - // to the program. - if len(os.Args) < 2 { - fmt.Println("expected 'foo' or 'bar' subcommands") - os.Exit(1) - } + // The subcommand is expected as the first argument + // to the program. + if len(os.Args) < 2 { + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } - // Check which subcommand is invoked. - switch os.Args[1] { + // Check which subcommand is invoked. + switch os.Args[1] { - // For every subcommand, we parse its own flags and - // have access to trailing positional arguments. - case "foo": - fooCmd.Parse(os.Args[2:]) - fmt.Println("subcommand 'foo'") - fmt.Println(" enable:", *fooEnable) - fmt.Println(" name:", *fooName) - fmt.Println(" tail:", fooCmd.Args()) - case "bar": - barCmd.Parse(os.Args[2:]) - fmt.Println("subcommand 'bar'") - fmt.Println(" level:", *barLevel) - fmt.Println(" tail:", barCmd.Args()) - default: - fmt.Println("expected 'foo' or 'bar' subcommands") - os.Exit(1) - } + // For every subcommand, we parse its own flags and + // have access to trailing positional arguments. + case "foo": + fooCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'foo'") + fmt.Println(" enable:", *fooEnable) + fmt.Println(" name:", *fooName) + fmt.Println(" tail:", fooCmd.Args()) + case "bar": + barCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'bar'") + fmt.Println(" level:", *barLevel) + fmt.Println(" tail:", barCmd.Args()) + default: + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } } diff --git a/public/command-line-subcommands b/public/command-line-subcommands index f53c19f..4a0542d 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -218,7 +218,7 @@ have access to trailing positional arguments.

    flag provided but not defined: -enable Usage of bar: -level int - level + level
    From 552611bc1ce2cdb32787f265898ad62e9530273d Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:36:05 -0700 Subject: [PATCH 085/133] Add periods --- .../command-line-subcommands/command-line-subcommands.sh | 6 +++--- public/command-line-subcommands | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/command-line-subcommands/command-line-subcommands.sh b/examples/command-line-subcommands/command-line-subcommands.sh index a7cec9a..c5948e8 100644 --- a/examples/command-line-subcommands/command-line-subcommands.sh +++ b/examples/command-line-subcommands/command-line-subcommands.sh @@ -1,19 +1,19 @@ $ go build command-line-subcommands.go -# First invoke the foo subcommand +# First invoke the foo subcommand. $ ./command-line-subcommands foo -enable -name=joe a1 a2 subcommand 'foo' enable: true name: joe tail: [a1 a2] -# Now try bar +# Now try bar. $ ./command-line-subcommands bar -level 8 a1 subcommand 'bar' level: 8 tail: [a1] -# But bar won't accept foo's flags +# But bar won't accept foo's flags. $ ./command-line-subcommands bar -enable a1 flag provided but not defined: -enable Usage of bar: diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 4a0542d..6fc1e06 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -176,7 +176,7 @@ have access to trailing positional arguments.

    -

    First invoke the foo subcommand

    +

    First invoke the foo subcommand.

    @@ -193,7 +193,7 @@ have access to trailing positional arguments.

    -

    Now try bar

    +

    Now try bar.

    @@ -209,7 +209,7 @@ have access to trailing positional arguments.

    -

    But bar won’t accept foo’s flags

    +

    But bar won’t accept foo’s flags.

    From 973da6773f3bf42c67d7828d5d26e5d8d660962b Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 1 Jun 2019 05:27:03 -0700 Subject: [PATCH 086/133] HTTP servers sample --- examples.txt | 1 + examples/http-servers/http-servers.go | 50 ++++++ examples/http-servers/http-servers.hash | 2 + examples/http-servers/http-servers.sh | 6 + public/http-clients | 2 +- public/http-servers | 198 ++++++++++++++++++++++++ public/index.html | 2 + 7 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 examples/http-servers/http-servers.go create mode 100644 examples/http-servers/http-servers.hash create mode 100644 examples/http-servers/http-servers.sh create mode 100644 public/http-servers diff --git a/examples.txt b/examples.txt index 2c1539b..d4859d3 100644 --- a/examples.txt +++ b/examples.txt @@ -62,6 +62,7 @@ Command-Line Flags Command-Line Subcommands Environment Variables HTTP Clients +HTTP Servers Spawning Processes Exec'ing Processes Signals diff --git a/examples/http-servers/http-servers.go b/examples/http-servers/http-servers.go new file mode 100644 index 0000000..9b97c1d --- /dev/null +++ b/examples/http-servers/http-servers.go @@ -0,0 +1,50 @@ +// Writing a basic HTTP server is very easy using the +// `net/http` package. +package main + +import ( + "fmt" + "net/http" +) + +// A fundamental concept in `net/http` servers is +// *handlers*. A handler is an object implementing the +// `http.Handler` interface. A very common way to write +// a handler is by using the `http.HandlerFunc` adapter +// on functions with the appropriate signature. +func hello(w http.ResponseWriter, req *http.Request) { + + // Functions serving as handlers take a + // `http.ResponseWriter` and a `http.Request` as + // arguments. The response writer is used to fill in the + // HTTP response. Here out simple response is just + // "hello\n". + fmt.Fprintf(w, "hello\n") +} + +func headers(w http.ResponseWriter, req *http.Request) { + + // This handler does something a little more + // sophisticated by reading all the HTTP request + // headers and echoing them into the response body. + for name, headers := range req.Header { + for _, h := range headers { + fmt.Fprintf(w, "%v: %v\n", name, h) + } + } +} + +func main() { + + // We register our handlers on server routes using the + // `http.HandleFunc` convenience function. It sets up + // the *default router* in the `net/http` package and + // takes a function as an argument. + http.HandleFunc("/hello", hello) + http.HandleFunc("/headers", headers) + + // Finally, we call the `ListenAndServe` with the port + // and a handler. `nil` tells it to use the default + // router we've just set up. + http.ListenAndServe(":8090", nil) +} diff --git a/examples/http-servers/http-servers.hash b/examples/http-servers/http-servers.hash new file mode 100644 index 0000000..4728691 --- /dev/null +++ b/examples/http-servers/http-servers.hash @@ -0,0 +1,2 @@ +1bffba1944537a9f9d7166a67d7a2b9f4ce2d70e +hg47WDVcY_W diff --git a/examples/http-servers/http-servers.sh b/examples/http-servers/http-servers.sh new file mode 100644 index 0000000..dcb9a42 --- /dev/null +++ b/examples/http-servers/http-servers.sh @@ -0,0 +1,6 @@ +# Run the server in the background. +$ go run examples/http-servers/http-servers.go & + +# Access the `/hello` route. +$ curl localhost:8090/hello +hello diff --git a/public/http-clients b/public/http-clients index 21779dd..f0fafa8 100644 --- a/public/http-clients +++ b/public/http-clients @@ -146,7 +146,7 @@ settings.

    - Next example: Spawning Processes. + Next example: HTTP Servers.

    +

    Go by Example: HTTP Servers

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Writing a basic HTTP server is very easy using the +net/http package.

    + +
    + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "net/http"
    +)
    +
    + +
    +

    A fundamental concept in net/http servers is +handlers. A handler is an object implementing the +http.Handler interface. A very common way to write +a handler is by using the http.HandlerFunc adapter +on functions with the appropriate signature.

    + +
    + +
    func hello(w http.ResponseWriter, req *http.Request) {
    +
    + +
    +

    Functions serving as handlers take a +http.ResponseWriter and a http.Request as +arguments. The response writer is used to fill in the +HTTP response. Here out simple response is just +“hello\n”.

    + +
    + +
        fmt.Fprintf(w, "hello\n")
    +}
    +
    + +
    + + + +
    func headers(w http.ResponseWriter, req *http.Request) {
    +
    + +
    +

    This handler does something a little more +sophisticated by reading all the HTTP request +headers and echoing them into the response body.

    + +
    + +
        for name, headers := range req.Header {
    +        for _, h := range headers {
    +            fmt.Fprintf(w, "%v: %v\n", name, h)
    +        }
    +    }
    +}
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    We register our handlers on server routes using the +http.HandleFunc convenience function. It sets up +the default router in the net/http package and +takes a function as an argument.

    + +
    + +
        http.HandleFunc("/hello", hello)
    +    http.HandleFunc("/headers", headers)
    +
    + +
    +

    Finally, we call the ListenAndServe with the port +and a handler. nil tells it to use the default +router we’ve just set up.

    + +
    + +
        http.ListenAndServe(":8090", nil)
    +}
    +
    + +
    + + + + + + + + + + + + + +
    +

    Run the server in the background.

    + +
    + +
    $ go run examples/http-servers/http-servers.go &
    +
    + +
    +

    Access the /hello route.

    + +
    + +
    $ curl localhost:8090/hello
    +hello
    +
    + +
    + + +

    + Next example: Spawning Processes. +

    + + +
    + + diff --git a/public/index.html b/public/index.html index ca79490..e3960aa 100644 --- a/public/index.html +++ b/public/index.html @@ -151,6 +151,8 @@
  • HTTP Clients
  • +
  • HTTP Servers
  • +
  • Spawning Processes
  • Exec'ing Processes
  • From fab09ef735485de40de5ded1b93523e6d19aea70 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 1 Jun 2019 05:47:43 -0700 Subject: [PATCH 087/133] Minor rewording --- examples/http-servers/http-servers.go | 2 +- examples/http-servers/http-servers.hash | 4 ++-- public/http-servers | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/http-servers/http-servers.go b/examples/http-servers/http-servers.go index 9b97c1d..5331a75 100644 --- a/examples/http-servers/http-servers.go +++ b/examples/http-servers/http-servers.go @@ -9,7 +9,7 @@ import ( // A fundamental concept in `net/http` servers is // *handlers*. A handler is an object implementing the -// `http.Handler` interface. A very common way to write +// `http.Handler` interface. A common way to write // a handler is by using the `http.HandlerFunc` adapter // on functions with the appropriate signature. func hello(w http.ResponseWriter, req *http.Request) { diff --git a/examples/http-servers/http-servers.hash b/examples/http-servers/http-servers.hash index 4728691..fe3b07d 100644 --- a/examples/http-servers/http-servers.hash +++ b/examples/http-servers/http-servers.hash @@ -1,2 +1,2 @@ -1bffba1944537a9f9d7166a67d7a2b9f4ce2d70e -hg47WDVcY_W +cc9a1fd34b3735d59f0972af21a26aabfff660c8 +FVQG_jryhVF diff --git a/public/http-servers b/public/http-servers index be056a4..d084f5a 100644 --- a/public/http-servers +++ b/public/http-servers @@ -18,7 +18,7 @@ - +
    package main
     
    @@ -44,7 +44,7 @@

    A fundamental concept in net/http servers is handlers. A handler is an object implementing the -http.Handler interface. A very common way to write +http.Handler interface. A common way to write a handler is by using the http.HandlerFunc adapter on functions with the appropriate signature.

    From 573cb47955bb09d8a09d029fa353bf477066d22f Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:44:57 -0700 Subject: [PATCH 088/133] Rebuild for tabs --- examples/http-servers/http-servers.go | 52 +++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/http-servers/http-servers.go b/examples/http-servers/http-servers.go index 5331a75..7556b2d 100644 --- a/examples/http-servers/http-servers.go +++ b/examples/http-servers/http-servers.go @@ -3,8 +3,8 @@ package main import ( - "fmt" - "net/http" + "fmt" + "net/http" ) // A fundamental concept in `net/http` servers is @@ -14,37 +14,37 @@ import ( // on functions with the appropriate signature. func hello(w http.ResponseWriter, req *http.Request) { - // Functions serving as handlers take a - // `http.ResponseWriter` and a `http.Request` as - // arguments. The response writer is used to fill in the - // HTTP response. Here out simple response is just - // "hello\n". - fmt.Fprintf(w, "hello\n") + // Functions serving as handlers take a + // `http.ResponseWriter` and a `http.Request` as + // arguments. The response writer is used to fill in the + // HTTP response. Here out simple response is just + // "hello\n". + fmt.Fprintf(w, "hello\n") } func headers(w http.ResponseWriter, req *http.Request) { - // This handler does something a little more - // sophisticated by reading all the HTTP request - // headers and echoing them into the response body. - for name, headers := range req.Header { - for _, h := range headers { - fmt.Fprintf(w, "%v: %v\n", name, h) - } - } + // This handler does something a little more + // sophisticated by reading all the HTTP request + // headers and echoing them into the response body. + for name, headers := range req.Header { + for _, h := range headers { + fmt.Fprintf(w, "%v: %v\n", name, h) + } + } } func main() { - // We register our handlers on server routes using the - // `http.HandleFunc` convenience function. It sets up - // the *default router* in the `net/http` package and - // takes a function as an argument. - http.HandleFunc("/hello", hello) - http.HandleFunc("/headers", headers) + // We register our handlers on server routes using the + // `http.HandleFunc` convenience function. It sets up + // the *default router* in the `net/http` package and + // takes a function as an argument. + http.HandleFunc("/hello", hello) + http.HandleFunc("/headers", headers) - // Finally, we call the `ListenAndServe` with the port - // and a handler. `nil` tells it to use the default - // router we've just set up. - http.ListenAndServe(":8090", nil) + // Finally, we call the `ListenAndServe` with the port + // and a handler. `nil` tells it to use the default + // router we've just set up. + http.ListenAndServe(":8090", nil) } From d1886245ba9b17ee0f71af7a9a2ad7e8a7e0ed96 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:50:21 -0700 Subject: [PATCH 089/133] Presentation tweaks --- examples/http-servers/http-servers.go | 2 +- examples/http-servers/http-servers.hash | 4 ++-- examples/http-servers/http-servers.sh | 2 +- public/http-servers | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/http-servers/http-servers.go b/examples/http-servers/http-servers.go index 7556b2d..72726b4 100644 --- a/examples/http-servers/http-servers.go +++ b/examples/http-servers/http-servers.go @@ -1,4 +1,4 @@ -// Writing a basic HTTP server is very easy using the +// Writing a basic HTTP server is easy using the // `net/http` package. package main diff --git a/examples/http-servers/http-servers.hash b/examples/http-servers/http-servers.hash index fe3b07d..6a0a323 100644 --- a/examples/http-servers/http-servers.hash +++ b/examples/http-servers/http-servers.hash @@ -1,2 +1,2 @@ -cc9a1fd34b3735d59f0972af21a26aabfff660c8 -FVQG_jryhVF +ac2909e69be30862bd9f18db954d9ee10f57ec6a +8GBAW6yNcbn diff --git a/examples/http-servers/http-servers.sh b/examples/http-servers/http-servers.sh index dcb9a42..2db5f45 100644 --- a/examples/http-servers/http-servers.sh +++ b/examples/http-servers/http-servers.sh @@ -1,5 +1,5 @@ # Run the server in the background. -$ go run examples/http-servers/http-servers.go & +$ go run http-servers.go & # Access the `/hello` route. $ curl localhost:8090/hello diff --git a/public/http-servers b/public/http-servers index d084f5a..958ddc3 100644 --- a/public/http-servers +++ b/public/http-servers @@ -13,12 +13,12 @@ -

    Writing a basic HTTP server is very easy using the +

    Writing a basic HTTP server is easy using the net/http package.

    - +
    package main
     
    @@ -163,7 +163,7 @@ router we’ve just set up.

    -
    $ go run examples/http-servers/http-servers.go &
    +            
    $ go run http-servers.go &
     
    From 6d8aa9b50a20c4caa93b7e41f86aeb6961351c59 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 4 Jun 2019 15:56:59 -0700 Subject: [PATCH 090/133] Remove pointers from the stateful-goroutines example. The pointers are unnecessary and make the sample slightly more complicated. Fixes #221 --- .../stateful-goroutines.go | 9 ++++---- .../stateful-goroutines.hash | 4 ++-- public/stateful-goroutines | 23 ++++++++++++++----- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/examples/stateful-goroutines/stateful-goroutines.go b/examples/stateful-goroutines/stateful-goroutines.go index 598c4a9..59655bb 100644 --- a/examples/stateful-goroutines/stateful-goroutines.go +++ b/examples/stateful-goroutines/stateful-goroutines.go @@ -28,6 +28,7 @@ type readOp struct { key int resp chan int } + type writeOp struct { key int val int @@ -43,8 +44,8 @@ func main() { // The `reads` and `writes` channels will be used by // other goroutines to issue read and write requests, // respectively. - reads := make(chan *readOp) - writes := make(chan *writeOp) + reads := make(chan readOp) + writes := make(chan writeOp) // Here is the goroutine that owns the `state`, which // is a map as in the previous example but now private @@ -76,7 +77,7 @@ func main() { for r := 0; r < 100; r++ { go func() { for { - read := &readOp{ + read := readOp{ key: rand.Intn(5), resp: make(chan int)} reads <- read @@ -92,7 +93,7 @@ func main() { for w := 0; w < 10; w++ { go func() { for { - write := &writeOp{ + write := writeOp{ key: rand.Intn(5), val: rand.Intn(100), resp: make(chan bool)} diff --git a/examples/stateful-goroutines/stateful-goroutines.hash b/examples/stateful-goroutines/stateful-goroutines.hash index f88cfa8..4956f93 100644 --- a/examples/stateful-goroutines/stateful-goroutines.hash +++ b/examples/stateful-goroutines/stateful-goroutines.hash @@ -1,2 +1,2 @@ -ff8b7e93a43c284ada17f4387cc5dfeafa3ee316 -dlfBGF-qff6 +330fde708b006d5571f9b94e7a63b4fead62bd36 +DxITfgl__z9 diff --git a/public/stateful-goroutines b/public/stateful-goroutines index 17add47..144f1e9 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -34,7 +34,7 @@ by exactly 1 goroutine.

    - +
    package main
     
    @@ -76,7 +76,18 @@ goroutine to respond.

    key int resp chan int } -type writeOp struct { +
    + + + + + + + + + + +
    type writeOp struct {
         key  int
         val  int
         resp chan bool
    @@ -121,8 +132,8 @@ respectively.

    -
        reads := make(chan *readOp)
    -    writes := make(chan *writeOp)
    +            
        reads := make(chan readOp)
    +    writes := make(chan writeOp)
     
    @@ -174,7 +185,7 @@ result over the provided resp channel.

        for r := 0; r < 100; r++ {
             go func() {
                 for {
    -                read := &readOp{
    +                read := readOp{
                         key:  rand.Intn(5),
                         resp: make(chan int)}
                     reads <- read
    @@ -200,7 +211,7 @@ approach.

        for w := 0; w < 10; w++ {
             go func() {
                 for {
    -                write := &writeOp{
    +                write := writeOp{
                         key:  rand.Intn(5),
                         val:  rand.Intn(100),
                         resp: make(chan bool)}
    
    From f4729c8ed2ca4de899cce8aeacaa817f70c9e959 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Tue, 4 Jun 2019 16:08:22 -0700
    Subject: [PATCH 091/133] Fix reading-files example to not show out-of-bounds
     bytes
    
    Fixes #165
    ---
     examples/reading-files/reading-files.go   |  6 +++---
     examples/reading-files/reading-files.hash |  4 ++--
     examples/reading-files/reading-files.sh   |  2 +-
     public/reading-files                      | 24 +++++++----------------
     4 files changed, 13 insertions(+), 23 deletions(-)
    
    diff --git a/examples/reading-files/reading-files.go b/examples/reading-files/reading-files.go
    index bcff7fe..49387a6 100644
    --- a/examples/reading-files/reading-files.go
    +++ b/examples/reading-files/reading-files.go
    @@ -40,7 +40,7 @@ func main() {
     	b1 := make([]byte, 5)
     	n1, err := f.Read(b1)
     	check(err)
    -	fmt.Printf("%d bytes: %s\n", n1, string(b1))
    +	fmt.Printf("%d bytes: %s\n", n1, string(b1[:n1]))
     
     	// You can also `Seek` to a known location in the file
     	// and `Read` from there.
    @@ -49,7 +49,8 @@ func main() {
     	b2 := make([]byte, 2)
     	n2, err := f.Read(b2)
     	check(err)
    -	fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2))
    +	fmt.Printf("%d bytes @ %d: ", n2, o2)
    +	fmt.Printf("%v\n", string(b2[:n2]))
     
     	// The `io` package provides some functions that may
     	// be helpful for file reading. For example, reads
    @@ -80,5 +81,4 @@ func main() {
     	// be scheduled immediately after `Open`ing with
     	// `defer`).
     	f.Close()
    -
     }
    diff --git a/examples/reading-files/reading-files.hash b/examples/reading-files/reading-files.hash
    index f687f38..8cf5bf6 100644
    --- a/examples/reading-files/reading-files.hash
    +++ b/examples/reading-files/reading-files.hash
    @@ -1,2 +1,2 @@
    -2aa7a2e248065cebfa6f8eece3234b5ffa710273
    -GQgp-I3dLb2
    +463a6f2999a023887af6b23c8f79f24978eb8115
    +cocJ6kBH_iZ
    diff --git a/examples/reading-files/reading-files.sh b/examples/reading-files/reading-files.sh
    index b3ab74f..a1deb72 100644
    --- a/examples/reading-files/reading-files.sh
    +++ b/examples/reading-files/reading-files.sh
    @@ -1,6 +1,6 @@
     $ echo "hello" > /tmp/dat
     $ echo "go" >>   /tmp/dat
    -$ go run reading-files.go 
    +$ go run reading-files.go
     hello
     go
     5 bytes: hello
    diff --git a/public/reading-files b/public/reading-files
    index 2e573cd..1b08728 100644
    --- a/public/reading-files
    +++ b/public/reading-files
    @@ -29,7 +29,7 @@ reading files.

    - +
    package main
     
    @@ -128,7 +128,7 @@ actually were read.

        b1 := make([]byte, 5)
         n1, err := f.Read(b1)
         check(err)
    -    fmt.Printf("%d bytes: %s\n", n1, string(b1))
    +    fmt.Printf("%d bytes: %s\n", n1, string(b1[:n1]))
     
    @@ -147,7 +147,8 @@ and Read from there.

    b2 := make([]byte, 2) n2, err := f.Read(b2) check(err) - fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) + fmt.Printf("%d bytes @ %d: ", n2, o2) + fmt.Printf("%v\n", string(b2[:n2]))
    @@ -214,22 +215,11 @@ reading methods it provides.

    be scheduled immediately after Opening with defer).

    - - - -
        f.Close()
    -
    - - - - - - - -
    }
    +            
        f.Close()
    +}
     
    @@ -247,7 +237,7 @@ be scheduled immediately after Opening with
    $ echo "hello" > /tmp/dat
     $ echo "go" >>   /tmp/dat
    -$ go run reading-files.go 
    +$ go run reading-files.go
     hello
     go
     5 bytes: hello
    
    From f99adfc228194d44bab6f736a1a118839cff7c10 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Tue, 4 Jun 2019 16:27:55 -0700
    Subject: [PATCH 092/133] Keep the two structs together for presentation
    
    ---
     .../stateful-goroutines/stateful-goroutines.go    |  1 -
     .../stateful-goroutines/stateful-goroutines.hash  |  4 ++--
     public/stateful-goroutines                        | 15 ++-------------
     3 files changed, 4 insertions(+), 16 deletions(-)
    
    diff --git a/examples/stateful-goroutines/stateful-goroutines.go b/examples/stateful-goroutines/stateful-goroutines.go
    index 59655bb..cb8b347 100644
    --- a/examples/stateful-goroutines/stateful-goroutines.go
    +++ b/examples/stateful-goroutines/stateful-goroutines.go
    @@ -28,7 +28,6 @@ type readOp struct {
     	key  int
     	resp chan int
     }
    -
     type writeOp struct {
     	key  int
     	val  int
    diff --git a/examples/stateful-goroutines/stateful-goroutines.hash b/examples/stateful-goroutines/stateful-goroutines.hash
    index 4956f93..1f3eb48 100644
    --- a/examples/stateful-goroutines/stateful-goroutines.hash
    +++ b/examples/stateful-goroutines/stateful-goroutines.hash
    @@ -1,2 +1,2 @@
    -330fde708b006d5571f9b94e7a63b4fead62bd36
    -DxITfgl__z9
    +956afe7524b492b2e85f8320c70f180c448a764a
    +saQTLpdIgp2
    diff --git a/public/stateful-goroutines b/public/stateful-goroutines
    index 144f1e9..f684680 100644
    --- a/public/stateful-goroutines
    +++ b/public/stateful-goroutines
    @@ -34,7 +34,7 @@ by exactly 1 goroutine.

    - +
    package main
     
    @@ -76,18 +76,7 @@ goroutine to respond.

    key int resp chan int } -
    - - - - - - - - - - -
    type writeOp struct {
    +type writeOp struct {
         key  int
         val  int
         resp chan bool
    
    From baf22e84e7e5b331572d761bdde78f210e7f7380 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Tue, 4 Jun 2019 19:03:37 -0700
    Subject: [PATCH 093/133] Move  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.

    - + @@ -28,7 +28,9 @@ specific length.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ specific length.

    - +
    import "fmt"
     
    @@ -52,7 +54,7 @@ specific length.

    - +
    func main() {
     
    @@ -68,7 +70,7 @@ zero-valued, which for ints means 0s.

    - +
        var a [5]int
         fmt.Println("emp:", a)
     
    @@ -84,7 +86,7 @@ zero-valued, which for ints means 0s.

    - +
        a[4] = 100
         fmt.Println("set:", a)
         fmt.Println("get:", a[4])
    @@ -99,7 +101,7 @@ zero-valued, which for ints means 0s.

    - +
        fmt.Println("len:", len(a))
     
    @@ -113,7 +115,7 @@ in one line.

    - +
        b := [5]int{1, 2, 3, 4, 5}
         fmt.Println("dcl:", b)
     
    @@ -129,7 +131,7 @@ structures.

    - +
        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.

    - + diff --git a/public/atomic-counters b/public/atomic-counters index a9ec770..9ba1895 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -22,7 +22,7 @@ counters accessed by multiple goroutines.

    - + @@ -32,7 +32,9 @@ counters accessed by multiple goroutines.

    - + + +
    package main
     
    @@ -44,7 +46,7 @@ counters accessed by multiple goroutines.

    - +
    import "fmt"
     import "time"
     import "sync/atomic"
    @@ -58,7 +60,7 @@ counters accessed by multiple goroutines.

    - +
    func main() {
     
    @@ -72,7 +74,7 @@ counters accessed by multiple goroutines.

    - +
        var ops uint64
     
    @@ -87,7 +89,7 @@ once a millisecond.

    - +
        for i := 0; i < 50; i++ {
             go func() {
                 for {
    @@ -105,7 +107,7 @@ address of our ops counter with the
     
               
               
    -	        
    +            
                 
                    atomic.AddUint64(&ops, 1)
     
    @@ -118,7 +120,7 @@ address of our ops counter with the - +
                    time.Sleep(time.Millisecond)
                 }
             }()
    @@ -134,7 +136,7 @@ address of our ops counter with the
     
               
               
    -	        
    +            
                 
        time.Sleep(time.Second)
     
    @@ -152,7 +154,7 @@ fetch the value.

    - +
        opsFinal := atomic.LoadUint64(&ops)
         fmt.Println("ops:", opsFinal)
     }
    @@ -172,7 +174,7 @@ fetch the value.

    - +
    $ go run atomic-counters.go
     ops: 41419
     
    @@ -187,7 +189,7 @@ state.

    - + diff --git a/public/base64-encoding b/public/base64-encoding index f067bee..2c1da0d 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -18,7 +18,7 @@ encoding/decoding.

    - + @@ -28,7 +28,9 @@ encoding/decoding.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ save us some space below.

    - +
    import b64 "encoding/base64"
     import "fmt"
     
    @@ -56,7 +58,7 @@ save us some space below.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ save us some space below.

    - +
        data := "abc123!?$*&()'-=@~"
     
    @@ -85,7 +87,7 @@ convert our string to that type.

    - +
        sEnc := b64.StdEncoding.EncodeToString([]byte(data))
         fmt.Println(sEnc)
     
    @@ -101,7 +103,7 @@ well-formed.

    - +
        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!?$*&()'-=@~
     
    diff --git a/public/channel-buffering b/public/channel-buffering index d7e54fd..2734939 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -22,7 +22,7 @@ those values.

    - + @@ -32,7 +32,9 @@ those values.

    - + + +
    package main
     
    @@ -44,7 +46,7 @@ those values.

    - +
    import "fmt"
     
    @@ -56,7 +58,7 @@ those values.

    - +
    func main() {
     
    @@ -70,7 +72,7 @@ those values.

    - +
        messages := make(chan string, 2)
     
    @@ -85,7 +87,7 @@ concurrent receive.

    - +
        messages <- "buffered"
         messages <- "channel"
     
    @@ -99,7 +101,7 @@ concurrent receive.

    - +
        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.

    - + @@ -30,7 +30,9 @@ the program.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ the program.

    - +
    import "fmt"
     
    @@ -57,7 +59,7 @@ receive on this channel.

    - +
    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
     
    diff --git a/public/channel-synchronization b/public/channel-synchronization index f860261..00076f9 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -21,7 +21,7 @@ you may prefer to use a WaitGroup.

    - + @@ -31,7 +31,9 @@ you may prefer to use a WaitGroup.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ you may prefer to use a WaitGroup.

    - +
    import "fmt"
     import "time"
     
    @@ -59,7 +61,7 @@ goroutine that this function’s work is done.

    - +
    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
     }
     
    @@ -88,7 +90,7 @@ goroutine that this function’s work is done.

    - +
    func main() {
     
    @@ -102,7 +104,7 @@ notify on.

    - +
        done := make(chan bool, 1)
         go worker(done)
     
    @@ -117,7 +119,7 @@ worker on the channel.

    - +
        <-done
     }
     
    @@ -134,7 +136,7 @@ worker on the channel.

    - +
    $ go run channel-synchronization.go      
     working...done                  
     
    @@ -150,7 +152,7 @@ started.

    - + diff --git a/public/channels b/public/channels index 4616272..94b14d7 100644 --- a/public/channels +++ b/public/channels @@ -20,7 +20,7 @@ goroutine.

    - + @@ -30,7 +30,9 @@ goroutine.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ goroutine.

    - +
    import "fmt"
     
    @@ -54,7 +56,7 @@ goroutine.

    - +
    func main() {
     
    @@ -68,7 +70,7 @@ Channels are typed by the values they convey.

    - +
        messages := make(chan string)
     
    @@ -83,7 +85,7 @@ channel we made above, from a new goroutine.

    - +
        go func() { messages <- "ping" }()
     
    @@ -98,7 +100,7 @@ we sent above and print it out.

    - +
        msg := <-messages
         fmt.Println(msg)
     }
    @@ -119,7 +121,7 @@ our channel.

    - +
    $ go run channels.go 
     ping
     
    @@ -136,7 +138,7 @@ message without having to use any other synchronization.

    - + diff --git a/public/closing-channels b/public/closing-channels index 3bf9b4b..d873cd8 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -19,7 +19,7 @@ completion to the channel’s receivers.

    - + @@ -29,7 +29,9 @@ completion to the channel’s receivers.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ completion to the channel’s receivers.

    - +
    import "fmt"
     
    @@ -57,7 +59,7 @@ the worker we’ll 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
     }
     
    @@ -140,7 +142,7 @@ we saw earlier.

    - +
    $ go run closing-channels.go 
     sent job 1
     received job 1
    @@ -162,7 +164,7 @@ example: range over channels.

    - + diff --git a/public/closures b/public/closures index 5cab1c8..d85af28 100644 --- a/public/closures +++ b/public/closures @@ -20,7 +20,7 @@ a function inline without having to name it.

    - + @@ -30,7 +30,9 @@ a function inline without having to name it.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ a function inline without having to name it.

    - +
    import "fmt"
     
    @@ -58,7 +60,7 @@ form a closure.

    - +
    func intSeq() func() int {
         i := 0
         return func() int {
    @@ -76,7 +78,7 @@ form a closure.

    - +
    func main() {
     
    @@ -92,7 +94,7 @@ we call nextInt.

    - +
        nextInt := intSeq()
     
    @@ -106,7 +108,7 @@ a few times.

    - +
        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.

    - + diff --git a/public/collection-functions b/public/collection-functions index 6aae10a..07e970b 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -20,7 +20,7 @@ collection with a custom function.

    - + @@ -35,7 +35,7 @@ your program and data types.

    - + @@ -51,7 +51,7 @@ helper function.

    - + @@ -61,7 +61,9 @@ helper function.

    - + + +
    package main
     
    @@ -73,7 +75,7 @@ helper function.

    - +
    import "strings"
     import "fmt"
     
    @@ -88,7 +90,7 @@ helper function.

    - +
    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() {
     
    @@ -220,7 +222,7 @@ the function f to each string in the original slice.

    - +
        var strs = []string{"peach", "apple", "pear", "plum"}
     
    @@ -232,7 +234,7 @@ the function f to each string in the original slice.

    - +
        fmt.Println(Index(strs, "pear"))
     
    @@ -244,7 +246,7 @@ the function f to each string in the original slice.

    - +
        fmt.Println(Include(strs, "grape"))
     
    @@ -256,7 +258,7 @@ the function 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))
     
    @@ -313,7 +315,7 @@ type.

    - +
    }
     
    @@ -329,7 +331,7 @@ type.

    - +
    $ 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
     
               
               
    -	        
    +            
                 
               
             
    @@ -30,7 +30,9 @@ For example, go run hello.go uses run and
                 
               
               
    -	        
    +            
    +              
    +            
                 
    package main
     
    @@ -42,7 +44,7 @@ For example, go run hello.go uses run and - +
    import "os"
     import "fmt"
     
    @@ -55,7 +57,7 @@ For example, go run hello.go uses run and - +
    func main() {
     
    @@ -71,7 +73,7 @@ holds the arguments to the program.

    - +
        argsWithProg := os.Args
         argsWithoutProg := os.Args[1:]
     
    @@ -85,7 +87,7 @@ holds the arguments to the program.

    - +
        arg := os.Args[3]
     
    @@ -97,7 +99,7 @@ holds the arguments to the program.

    - +
        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.

    - + diff --git a/public/command-line-flags b/public/command-line-flags index 3678600..42dad0b 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -20,7 +20,7 @@ command-line flag.

    - + @@ -30,7 +30,9 @@ command-line flag.

    - + + +
    package main
     
    @@ -45,7 +47,7 @@ implement our example command-line program.

    - +
    import "flag"
     import "fmt"
     
    @@ -58,7 +60,7 @@ implement our example command-line program.

    - +
    func main() {
     
    @@ -76,7 +78,7 @@ we’ll see how to use this pointer below.

    - +
        wordPtr := flag.String("word", "foo", "a string")
     
    @@ -90,7 +92,7 @@ similar approach to the word flag.

    - +
        numbPtr := flag.Int("numb", 42, "an int")
         boolPtr := flag.Bool("fork", false, "a bool")
     
    @@ -107,7 +109,7 @@ declaration function.

    - +
        var svar string
         flag.StringVar(&svar, "svar", "bar", "a string var")
     
    @@ -122,7 +124,7 @@ to execute the command-line parsing.

    - +
        flag.Parse()
     
    @@ -138,7 +140,7 @@ to get the actual option values.

    - +
        fmt.Println("word:", *wordPtr)
         fmt.Println("numb:", *numbPtr)
         fmt.Println("fork:", *boolPtr)
    @@ -162,7 +164,7 @@ binary directly.

    - +
    $ go build command-line-flags.go
     
    @@ -176,7 +178,7 @@ all flags.

    - +
    $ ./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.

    - + diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 6fc1e06..945f646 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -22,7 +22,7 @@ subcommands that have their own flags.

    - + @@ -32,7 +32,9 @@ subcommands that have their own flags.

    - + + +
    package main
     
    @@ -44,7 +46,7 @@ subcommands that have their own flags.

    - +
    import (
         "flag"
         "fmt"
    @@ -60,7 +62,7 @@ subcommands that have their own flags.

    - +
    func main() {
     
    @@ -75,7 +77,7 @@ for this subcommand.

    - +
        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")
     
    @@ -106,7 +108,7 @@ to the program.

    - +
        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] {
     
    @@ -136,7 +138,7 @@ have access to trailing positional arguments.

    - +
        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 
     
    @@ -180,7 +182,7 @@ have access to trailing positional arguments.

    - +
    $ ./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.

    - + @@ -28,7 +28,9 @@ and numeric values.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ and numeric values.

    - +
    import "fmt"
     import "math"
     
    @@ -54,7 +56,7 @@ and numeric values.

    - +
    const s string = "constant"
     
    @@ -66,7 +68,7 @@ and numeric values.

    - +
    func main() {
         fmt.Println(s)
     
    @@ -81,7 +83,7 @@ statement can.

    - +
        const n = 500000000
     
    @@ -95,7 +97,7 @@ arbitrary precision.

    - +
        const d = 3e20 / n
         fmt.Println(d)
     
    @@ -110,7 +112,7 @@ one, such as by an explicit conversion.

    - +
        fmt.Println(int64(d))
     
    @@ -126,7 +128,7 @@ assignment or function call. For example, here - +
        fmt.Println(math.Sin(n))
     }
     
    @@ -143,7 +145,7 @@ assignment or function call. For example, here - +
    $ 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.
     
               
               
    -	        
    +            
                 
               
             
    @@ -30,7 +30,9 @@ purposes of cleanup. defer is often used where e.g.
                 
               
               
    -	        
    +            
    +              
    +            
                 
    package main
     
    @@ -42,7 +44,7 @@ purposes of cleanup. defer is often used where e.g. - +
    import "fmt"
     import "os"
     
    @@ -58,7 +60,7 @@ do that with defer.

    - +
    func main() {
     
    @@ -75,7 +77,7 @@ of the enclosing function (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
                 
               
               
    -	        
    +            
                 
    }
     
    @@ -135,7 +137,7 @@ of the enclosing function (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.

    - + @@ -30,7 +30,9 @@ Let’s look at how to set, get, and list environment variables.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ Let’s look at how to set, get, and list environment variables.

    - +
    import "os"
     import "strings"
     import "fmt"
    @@ -56,7 +58,7 @@ Let’s look at how to set, get, and list environment variables.

    - +
    func main() {
     
    @@ -72,7 +74,7 @@ environment.

    - +
        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.

    - + @@ -30,7 +30,9 @@ Here’s how to do it in Go.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ Here’s how to do it in Go.

    - +
    import "fmt"
     import "time"
     
    @@ -55,7 +57,7 @@ Here’s how to do it in Go.

    - +
    func main() {
     
    @@ -70,7 +72,7 @@ nanoseconds, respectively.

    - +
        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.

    - + diff --git a/public/errors b/public/errors index 59cfb7e..489f119 100644 --- a/public/errors +++ b/public/errors @@ -24,7 +24,7 @@ non-error tasks.

    - + @@ -34,7 +34,9 @@ non-error tasks.

    - + + +
    package main
     
    @@ -46,7 +48,7 @@ non-error tasks.

    - +
    import "errors"
     import "fmt"
     
    @@ -61,7 +63,7 @@ have type error, a built-in interface.

    - +
    func f1(arg int) (int, error) {
         if arg == 42 {
     
    @@ -76,7 +78,7 @@ with the given error message.

    - +
            return -1, errors.New("can't work with 42")
     
    @@ -88,7 +90,7 @@ with the given error message.

    - +
        }
     
    @@ -102,7 +104,7 @@ there was no error.

    - +
        return arg + 3, nil
     }
     
    @@ -119,7 +121,7 @@ to explicitly represent an argument error.

    - +
    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 {
     
    @@ -164,7 +166,7 @@ fields 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() {
     
    @@ -195,7 +197,7 @@ idiom in Go code.

    - +
        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.

    - + diff --git a/public/execing-processes b/public/execing-processes index 2fc8e94..85b155d 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -25,7 +25,7 @@ function.

    - + @@ -35,7 +35,9 @@ function.

    - + + +
    package main
     
    @@ -47,7 +49,7 @@ function.

    - +
    import "syscall"
     import "os"
     import "os/exec"
    @@ -61,7 +63,7 @@ function.

    - +
    func main() {
     
    @@ -77,7 +79,7 @@ we’ll use 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"}
     
    @@ -111,7 +113,7 @@ environment.

    - +
        env := os.Environ()
     
    @@ -128,7 +130,7 @@ value.

    - +
        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.

    - + diff --git a/public/exit b/public/exit index f92266a..4c6975d 100644 --- a/public/exit +++ b/public/exit @@ -18,7 +18,7 @@ status.

    - + @@ -28,7 +28,9 @@ status.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ status.

    - +
    import "fmt"
     import "os"
     
    @@ -53,7 +55,7 @@ status.

    - +
    func main() {
     
    @@ -67,7 +69,7 @@ this fmt.Println will never be called.

    - +
        defer fmt.Println("!")
     
    @@ -80,7 +82,7 @@ this fmt.Println will never be called.

    - +
        os.Exit(3)
     }
     
    @@ -97,7 +99,7 @@ use os.Exit.

    - + @@ -113,7 +115,7 @@ will be picked up by go and printed.

    - +
    $ go run exit.go
     exit status 3
     
    @@ -128,7 +130,7 @@ the status in the terminal.

    - +
    $ go build exit.go
     $ ./exit
     $ echo $?
    @@ -144,7 +146,7 @@ the status in the terminal.

    - + diff --git a/public/for b/public/for index 68db267..314f139 100644 --- a/public/for +++ b/public/for @@ -18,7 +18,7 @@ three basic types of for loops.

    - + @@ -28,7 +28,9 @@ three basic types of for loops.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ three basic types of for loops.

    - +
    import "fmt"
     
    @@ -52,7 +54,7 @@ three basic types of for loops.

    - +
    func main() {
     
    @@ -65,7 +67,7 @@ three basic types of 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.

    - + diff --git a/public/functions b/public/functions index 94acc61..7c89d83 100644 --- a/public/functions +++ b/public/functions @@ -18,7 +18,7 @@ functions with a few different examples.

    - + @@ -28,7 +28,9 @@ functions with a few different examples.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ functions with a few different examples.

    - +
    import "fmt"
     
    @@ -54,7 +56,7 @@ their sum as an int.

    - +
    func plus(a int, b int) int {
     
    @@ -69,7 +71,7 @@ expression.

    - +
        return a + b
     }
     
    @@ -86,7 +88,7 @@ declares the type.

    - +
    func plusPlus(a, b, c int) int {
         return a + b + c
     }
    @@ -100,7 +102,7 @@ declares the type.

    - +
    func main() {
     
    @@ -114,7 +116,7 @@ declares the type.

    - +
        res := plus(1, 2)
         fmt.Println("1+2 =", res)
     
    @@ -127,7 +129,7 @@ declares the type.

    - +
        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.

    - + diff --git a/public/goroutines b/public/goroutines index df884f2..40ba434 100644 --- a/public/goroutines +++ b/public/goroutines @@ -17,7 +17,7 @@ - + @@ -27,7 +27,9 @@ - + + +
    package main
     
    @@ -39,7 +41,7 @@ - +
    import "fmt"
     
    @@ -51,7 +53,7 @@ - +
    func f(from string) {
         for i := 0; i < 3; i++ {
             fmt.Println(from, ":", i)
    @@ -67,7 +69,7 @@
                 
               
               
    -	        
    +            
                 
    func main() {
     
    @@ -82,7 +84,7 @@ synchronously.

    - +
        f("direct")
     
    @@ -97,7 +99,7 @@ concurrently with the calling one.

    - +
        go f("goroutine")
     
    @@ -111,7 +113,7 @@ function call.

    - +
        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.

    - + diff --git a/public/hello-world b/public/hello-world index bd9c439..d8b1872 100644 --- a/public/hello-world +++ b/public/hello-world @@ -18,7 +18,9 @@ message. Here’s the full source code.

    - + + +
    package main
     
    @@ -30,7 +32,7 @@ message. Here’s the full source code.

    - +
    import "fmt"
     
    @@ -42,7 +44,7 @@ message. Here’s the full source code.

    - +
    func main() {
         fmt.Println("hello world")
     }
    @@ -62,7 +64,7 @@ use go run.

    - +
    $ go run hello-world.go
     hello world
     
    @@ -77,7 +79,7 @@ binaries. We can do this using 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
     
    @@ -107,7 +109,7 @@ learn more about the language.

    - + diff --git a/public/http-clients b/public/http-clients index f0fafa8..5d5bf04 100644 --- a/public/http-clients +++ b/public/http-clients @@ -20,7 +20,9 @@ HTTP requests.

    - + + +
    package main
     
    @@ -32,7 +34,7 @@ HTTP requests.

    - +
    import (
         "bufio"
         "fmt"
    @@ -48,7 +50,7 @@ HTTP requests.

    - +
    func main() {
     
    @@ -65,7 +67,7 @@ settings.

    - +
        resp, err := http.Get("http://gobyexample.com")
         if err != nil {
             panic(err)
    @@ -82,7 +84,7 @@ settings.

    - +
        fmt.Println("Response status:", resp.Status)
     
    @@ -95,7 +97,7 @@ settings.

    - +
        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
     
    @@ -30,7 +32,7 @@ - +
    import (
         "fmt"
         "net/http"
    @@ -50,7 +52,7 @@ on functions with the appropriate signature.

    - +
    func hello(w http.ResponseWriter, req *http.Request) {
     
    @@ -67,7 +69,7 @@ HTTP response. Here out simple response is just - +
        fmt.Fprintf(w, "hello\n")
     }
     
    @@ -80,7 +82,7 @@ HTTP response. Here out simple response is just - +
    func headers(w http.ResponseWriter, req *http.Request) {
     
    @@ -95,7 +97,7 @@ headers and echoing them into the response body.

    - +
        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() {
     
    @@ -128,7 +130,7 @@ takes a function as an argument.

    - +
        http.HandleFunc("/hello", hello)
         http.HandleFunc("/headers", headers)
     
    @@ -144,7 +146,7 @@ router we’ve just set up.

    - +
        http.ListenAndServe(":8090", nil)
     }
     
    @@ -162,7 +164,7 @@ router we’ve just set up.

    - +
    $ go run http-servers.go &
     
    @@ -175,7 +177,7 @@ router we’ve just set up.

    - +
    $ curl localhost:8090/hello
     hello
     
    diff --git a/public/if-else b/public/if-else index 0ee016d..2ed0680 100644 --- a/public/if-else +++ b/public/if-else @@ -18,7 +18,7 @@ straight-forward.

    - + @@ -28,7 +28,9 @@ straight-forward.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ straight-forward.

    - +
    import "fmt"
     
    @@ -52,7 +54,7 @@ straight-forward.

    - +
    func main() {
     
    @@ -65,7 +67,7 @@ straight-forward.

    - +
        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.

    - + @@ -134,7 +136,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.

    - + diff --git a/public/interfaces b/public/interfaces index ea4ebda..277c8f8 100644 --- a/public/interfaces +++ b/public/interfaces @@ -18,7 +18,7 @@ signatures.

    - + @@ -28,7 +28,9 @@ signatures.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ signatures.

    - +
    import "fmt"
     import "math"
     
    @@ -54,7 +56,7 @@ signatures.

    - +
    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 rects.

    - +
    func (r rect) area() float64 {
         return r.width * r.height
     }
    @@ -109,7 +111,7 @@ implement geometry on rects.

    - +
    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.

    - + diff --git a/public/json b/public/json index 61fe8bc..54979d2 100644 --- a/public/json +++ b/public/json @@ -19,7 +19,7 @@ data types.

    - + @@ -29,7 +29,9 @@ data types.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ data types.

    - +
    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() {
     
    @@ -91,7 +93,7 @@ values.

    - +
        bolB, _ := json.Marshal(true)
         fmt.Println(string(bolB))
     
    @@ -104,7 +106,7 @@ values.

    - +
        intB, _ := json.Marshal(1)
         fmt.Println(string(intB))
     
    @@ -117,7 +119,7 @@ values.

    - +
        fltB, _ := json.Marshal(2.34)
         fmt.Println(string(fltB))
     
    @@ -130,7 +132,7 @@ values.

    - +
        strB, _ := json.Marshal("gopher")
         fmt.Println(string(strB))
     
    @@ -145,7 +147,7 @@ to JSON arrays and objects as you’d expect.

    - +
        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"]}`)
     
    @@ -232,7 +234,7 @@ to arbitrary data types.

    - +
        var dat map[string]interface{}
     
    @@ -246,7 +248,7 @@ associated errors.

    - +
        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)
     
    @@ -280,7 +282,7 @@ conversions.

    - +
        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.Writers 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.Writers like
                 
               
               
    -	        
    +            
                 
    $ go run json.go
     true
     1
    @@ -369,7 +371,7 @@ for more.

    - + diff --git a/public/line-filters b/public/line-filters index 0b7b0a5..d1dd866 100644 --- a/public/line-filters +++ b/public/line-filters @@ -20,7 +20,7 @@ line filters.

    - + @@ -33,7 +33,9 @@ pattern to write your own Go line filters.

    - + + +
    package main
     
    @@ -45,7 +47,7 @@ pattern to write your own Go line filters.

    - +
    import (
         "bufio"
         "fmt"
    @@ -62,7 +64,7 @@ pattern to write your own Go line filters.

    - +
    func main() {
     
    @@ -78,7 +80,7 @@ the next line in the default scanner.

    - +
        scanner := bufio.NewScanner(os.Stdin)
     
    @@ -92,7 +94,7 @@ from the input.

    - +
        for scanner.Scan() {
     
    @@ -104,7 +106,7 @@ from the input.

    - +
            ucl := strings.ToUpper(scanner.Text())
     
    @@ -117,7 +119,7 @@ from the input.

    - +
            fmt.Println(ucl)
         }
     
    @@ -132,7 +134,7 @@ expected and not reported by 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
     
    @@ -168,7 +170,7 @@ lowercase 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 @@
     
               
               
    -	        
    +            
                 
               
             
    @@ -28,7 +28,9 @@
                 
               
               
    -	        
    +            
    +              
    +            
                 
    package main
     
    @@ -40,7 +42,7 @@ - +
    import "fmt"
     
    @@ -52,7 +54,7 @@ - +
    func main() {
     
    @@ -66,7 +68,7 @@ - +
        m := make(map[string]int)
     
    @@ -80,7 +82,7 @@ syntax.

    - +
        m["k1"] = 7
         m["k2"] = 13
     
    @@ -95,7 +97,7 @@ its key/value pairs.

    - +
        fmt.Println("map:", m)
     
    @@ -108,7 +110,7 @@ its key/value pairs.

    - +
        v1 := m["k1"]
         fmt.Println("v1: ", v1)
     
    @@ -123,7 +125,7 @@ pairs when called on a map.

    - +
        fmt.Println("len:", len(m))
     
    @@ -137,7 +139,7 @@ a map.

    - +
        delete(m, "k2")
         fmt.Println("map:", m)
     
    @@ -157,7 +159,7 @@ itself, so we ignored it with the blank identifier - +
        _, prs := m["k2"]
         fmt.Println("prs:", prs)
     
    @@ -172,7 +174,7 @@ the same line with this syntax.

    - +
        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 @@
     
               
               
    -	        
    +            
                 
               
             
    @@ -27,7 +27,9 @@
                 
               
               
    -	        
    +            
    +              
    +            
                 
    package main
     
    @@ -39,7 +41,7 @@ - +
    import "fmt"
     
    @@ -51,7 +53,7 @@ - +
    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}
     
    @@ -110,7 +112,7 @@ receiver types. Here’s an example of a value receiver.

    - +
        fmt.Println("area: ", r.area())
         fmt.Println("perim:", r.perim())
     
    @@ -128,7 +130,7 @@ receiving struct.

    - +
        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.

    - + diff --git a/public/multiple-return-values b/public/multiple-return-values index ed3692d..5392875 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -19,7 +19,7 @@ to return both result and error values from a function.

    - + @@ -29,7 +29,9 @@ to return both result and error values from a function.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ to return both result and error values from a function.

    - +
    import "fmt"
     
    @@ -55,7 +57,7 @@ the function returns 2 ints.

    - +
    func vals() (int, int) {
         return 3, 7
     }
    @@ -69,7 +71,7 @@ the function returns 2 ints.

    - +
    func main() {
     
    @@ -83,7 +85,7 @@ call with multiple assignment.

    - +
        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.

    - + diff --git a/public/mutexes b/public/mutexes index 6bc013e..efc2253 100644 --- a/public/mutexes +++ b/public/mutexes @@ -20,7 +20,7 @@ to safely access data across multiple goroutines.

    - + @@ -30,7 +30,9 @@ to safely access data across multiple goroutines.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ to safely access data across multiple goroutines.

    - +
    import (
         "fmt"
         "math/rand"
    @@ -60,7 +62,7 @@ to safely access data across multiple goroutines.

    - +
    func main() {
     
    @@ -73,7 +75,7 @@ to safely access data across multiple goroutines.

    - +
        var state = make(map[int]int)
     
    @@ -86,7 +88,7 @@ to safely access data across multiple goroutines.

    - +
        var mutex = &sync.Mutex{}
     
    @@ -100,7 +102,7 @@ operations we do.

    - +
        var readOps uint64
         var writeOps uint64
     
    @@ -116,7 +118,7 @@ each goroutine.

    - +
        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)
     
    @@ -210,7 +212,7 @@ using the same pattern we did for reads.

    - +
        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.

    - + diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index 30c1560..ada60a3 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -20,7 +20,7 @@ non-blocking multi-way selects.

    - + @@ -30,7 +30,9 @@ non-blocking multi-way selects.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ non-blocking multi-way selects.

    - +
    import "fmt"
     
    @@ -54,7 +56,7 @@ non-blocking multi-way selects.

    - +
    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.

    - + @@ -28,7 +28,9 @@ in many programs; here’s how to do it in Go.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ parsing.

    - +
    import "strconv"
     import "fmt"
     
    @@ -55,7 +57,7 @@ parsing.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ precision to parse.

    - +
        f, _ := strconv.ParseFloat("1.234", 64)
         fmt.Println(f)
     
    @@ -85,7 +87,7 @@ bits.

    - +
        i, _ := strconv.ParseInt("123", 0, 64)
         fmt.Println(i)
     
    @@ -99,7 +101,7 @@ bits.

    - +
        d, _ := strconv.ParseInt("0x1c8", 0, 64)
         fmt.Println(d)
     
    @@ -113,7 +115,7 @@ bits.

    - +
        u, _ := strconv.ParseUint("789", 0, 64)
         fmt.Println(u)
     
    @@ -128,7 +130,7 @@ bits.

    - +
        k, _ := strconv.Atoi("135")
         fmt.Println(k)
     
    @@ -142,7 +144,7 @@ bits.

    - +
        _, 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.

    - + diff --git a/public/panic b/public/panic index c3e3621..59198af 100644 --- a/public/panic +++ b/public/panic @@ -20,7 +20,7 @@ aren’t prepared to handle gracefully.

    - + @@ -30,7 +30,9 @@ aren’t prepared to handle gracefully.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ aren’t prepared to handle gracefully.

    - +
    import "os"
     
    @@ -54,7 +56,7 @@ aren’t prepared to handle gracefully.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ site designed to panic.

    - +
        panic("a problem")
     
    @@ -85,7 +87,7 @@ returns an error value that we don’t know how to - +
        _, 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
     
    @@ -121,7 +123,7 @@ a non-zero status.

    - +
    goroutine 1 [running]:
     main.main()
         /.../panic.go:12 +0x47
    @@ -140,7 +142,7 @@ to use error-indicating return values wherever possible.

    - + diff --git a/public/pointers b/public/pointers index 5959923..16687f5 100644 --- a/public/pointers +++ b/public/pointers @@ -19,7 +19,7 @@ within your program.

    - + @@ -29,7 +29,9 @@ within your program.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ within your program.

    - +
    import "fmt"
     
    @@ -58,7 +60,7 @@ from the one in the calling function.

    - +
    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)
     
    @@ -121,7 +123,7 @@ i.e. a pointer to i.

    - +
        zeroptr(&i)
         fmt.Println("zeroptr:", i)
     
    @@ -135,7 +137,7 @@ i.e. a pointer to i.

    - +
        fmt.Println("pointer:", &i)
     }
     
    @@ -155,7 +157,7 @@ the memory address for that variable.

    - +
    $ 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.

    - + @@ -29,7 +29,9 @@ generation.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ generation.

    - +
    import "time"
     import "fmt"
     import "math/rand"
    @@ -55,7 +57,7 @@ generation.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ generation.

    - +
        fmt.Print(rand.Intn(100), ",")
         fmt.Print(rand.Intn(100))
         fmt.Println()
    @@ -85,7 +87,7 @@ generation.

    - +
        fmt.Println(rand.Float64())
     
    @@ -99,7 +101,7 @@ other ranges, for example 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)
     
    @@ -133,7 +135,7 @@ functions on the 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.

    - + diff --git a/public/range b/public/range index 70ac079..e9aa99e 100644 --- a/public/range +++ b/public/range @@ -19,7 +19,7 @@ of the data structures we’ve already learned.

    - + @@ -29,7 +29,9 @@ of the data structures we’ve already learned.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ of the data structures we’ve already learned.

    - +
    import "fmt"
     
    @@ -53,7 +55,7 @@ of the data structures we’ve already learned.

    - +
    func main() {
     
    @@ -67,7 +69,7 @@ Arrays work like this too.

    - +
        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.

    - + @@ -30,7 +30,9 @@ values received from a channel.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ values received from a channel.

    - +
    import "fmt"
     
    @@ -54,7 +56,7 @@ values received from a channel.

    - +
    func main() {
     
    @@ -67,7 +69,7 @@ values received from a channel.

    - +
        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.

    - + diff --git a/public/rate-limiting b/public/rate-limiting index b41c17f..07dc185 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -21,7 +21,7 @@ channels, and tickers.

    - + @@ -31,7 +31,9 @@ channels, and tickers.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ channels, and tickers.

    - +
    import "time"
     import "fmt"
     
    @@ -56,7 +58,7 @@ channels, and tickers.

    - +
    func main() {
     
    @@ -72,7 +74,7 @@ same name.

    - +
        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)
     
    @@ -106,7 +108,7 @@ before serving each request, we limit ourselves to - +
        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)
     
    @@ -139,7 +141,7 @@ channel will allow bursts of up to 3 events.

    - +
        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.

    - + @@ -29,7 +29,9 @@ reading files.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ reading files.

    - +
    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() {
     
    @@ -91,7 +93,7 @@ slurping a file’s entire contents into memory.

    - +
        dat, err := ioutil.ReadFile("/tmp/dat")
         check(err)
         fmt.Print(string(dat))
    @@ -108,7 +110,7 @@ by Opening a file to obtain an os.File value.

    - +
        f, err := os.Open("/tmp/dat")
         check(err)
     
    @@ -124,7 +126,7 @@ actually were read.

    - +
        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)
     
    @@ -199,7 +201,7 @@ reading methods it provides.

    - +
        r4 := bufio.NewReader(f)
         b4, err := r4.Peek(5)
         check(err)
    @@ -217,7 +219,7 @@ be scheduled immediately after Opening with
     
               
               
    -	        
    +            
                 
        f.Close()
     }
     
    @@ -234,7 +236,7 @@ be scheduled immediately after Opening with - +
    $ echo "hello" > /tmp/dat
     $ echo "go" >>   /tmp/dat
     $ go run reading-files.go
    @@ -255,7 +257,7 @@ be scheduled immediately after Opening with
     
               
               
    -	        
    +            
                 
               
             
    diff --git a/public/recursion b/public/recursion
    index 08d0857..bedbf2f 100644
    --- a/public/recursion
    +++ b/public/recursion
    @@ -19,7 +19,7 @@ Here’s a classic factorial example.

    - + @@ -29,7 +29,9 @@ Here’s a classic factorial example.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ Here’s a classic factorial example.

    - +
    import "fmt"
     
    @@ -55,7 +57,7 @@ base case of 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
     
    diff --git a/public/regular-expressions b/public/regular-expressions index 9ff0a95..8db2fbd 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -19,7 +19,7 @@ in Go.

    - + @@ -29,7 +29,9 @@ in Go.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ in Go.

    - +
    import "bytes"
     import "fmt"
     import "regexp"
    @@ -55,7 +57,7 @@ in Go.

    - +
    func main() {
     
    @@ -68,7 +70,7 @@ in Go.

    - +
        match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
         fmt.Println(match)
     
    @@ -84,7 +86,7 @@ optimized Regexp struct.

    - +
        r, _ := regexp.Compile("p([a-z]+)ch")
     
    @@ -98,7 +100,7 @@ a match test like we saw earlier.

    - +
        fmt.Println(r.MatchString("peach"))
     
    @@ -111,7 +113,7 @@ a match test like we saw earlier.

    - +
        fmt.Println(r.FindString("peach punch"))
     
    @@ -126,7 +128,7 @@ matching text.

    - +
        fmt.Println(r.FindStringIndex("peach punch"))
     
    @@ -142,7 +144,7 @@ information for both p([a-z]+)ch and ([a-z]+).

    - +
        fmt.Println(r.FindStringSubmatch("peach punch"))
     
    @@ -156,7 +158,7 @@ indexes of matches and submatches.

    - +
        fmt.Println(r.FindStringSubmatchIndex("peach punch"))
     
    @@ -171,7 +173,7 @@ example to find all matches for a regexp.

    - +
        fmt.Println(r.FindAllString("peach punch pinch", -1))
     
    @@ -185,7 +187,7 @@ functions we saw above as well.

    - +
        fmt.Println(r.FindAllStringSubmatchIndex(
             "peach punch pinch", -1))
     
    @@ -201,7 +203,7 @@ of matches.

    - +
        fmt.Println(r.FindAllString("peach punch pinch", 2))
     
    @@ -217,7 +219,7 @@ function name.

    - +
        fmt.Println(r.Match([]byte("peach")))
     
    @@ -233,7 +235,7 @@ constants because it has 2 return values.

    - +
        r = regexp.MustCompile("p([a-z]+)ch")
         fmt.Println(r)
     
    @@ -248,7 +250,7 @@ subsets of strings with other values.

    - +
        fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
     
    @@ -262,7 +264,7 @@ text with a given function.

    - +
        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
     
               
               
    -	        
    +            
                 
               
             
    diff --git a/public/select b/public/select
    index 87f7051..d6733a1 100644
    --- a/public/select
    +++ b/public/select
    @@ -19,7 +19,7 @@ select is a powerful feature of Go.

    - + @@ -29,7 +29,9 @@ select is a powerful feature of Go.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ select is a powerful feature of Go.

    - +
    import "time"
     import "fmt"
     
    @@ -54,7 +56,7 @@ select is a powerful feature of Go.

    - +
    func main() {
     
    @@ -67,7 +69,7 @@ select is a powerful feature of Go.

    - +
        c1 := make(chan string)
         c2 := make(chan string)
     
    @@ -83,7 +85,7 @@ executing in concurrent goroutines.

    - +
        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
     
    diff --git a/public/sha1-hashes b/public/sha1-hashes index 7daa377..c28cf1d 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -22,7 +22,7 @@ compute SHA1 hashes in Go.

    - + @@ -32,7 +32,9 @@ compute SHA1 hashes in Go.

    - + + +
    package main
     
    @@ -46,7 +48,7 @@ compute SHA1 hashes in Go.

    - +
    import "crypto/sha1"
     import "fmt"
     
    @@ -59,7 +61,7 @@ compute SHA1 hashes in Go.

    - +
    func main() {
         s := "sha1 this string"
     
    @@ -75,7 +77,7 @@ Here we start with a new hash.

    - +
        h := sha1.New()
     
    @@ -89,7 +91,7 @@ use []byte(s) to coerce it to bytes.

    - +
        h.Write([]byte(s))
     
    @@ -104,7 +106,7 @@ to an existing byte slice: it usually isn’t needed.

    - +
        bs := h.Sum(nil)
     
    @@ -119,7 +121,7 @@ a hash results to a hex string.

    - +
        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().

    - + @@ -169,7 +171,7 @@ you should carefully research - + diff --git a/public/signals b/public/signals index 85849f7..50f0ec1 100644 --- a/public/signals +++ b/public/signals @@ -22,7 +22,7 @@ Here’s how to handle signals in Go with channels.

    - + @@ -32,7 +32,9 @@ Here’s how to handle signals in Go with channels.

    - + + +
    package main
     
    @@ -44,7 +46,7 @@ Here’s how to handle signals in Go with channels.

    - +
    import "fmt"
     import "os"
     import "os/signal"
    @@ -59,7 +61,7 @@ Here’s how to handle signals in Go with channels.

    - +
    func main() {
     
    @@ -75,7 +77,7 @@ notify us when the program can exit).

    - +
        sigs := make(chan os.Signal, 1)
         done := make(chan bool, 1)
     
    @@ -90,7 +92,7 @@ receive notifications of the specified signals.

    - +
        signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
     
    @@ -105,7 +107,7 @@ and then notify the program that it can finish.

    - +
        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.

    - + @@ -28,7 +28,9 @@ powerful interface to sequences than arrays.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ powerful interface to sequences than arrays.

    - +
    import "fmt"
     
    @@ -52,7 +54,7 @@ powerful interface to sequences than arrays.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ the builtin make. Here we make a slice of - +
        s := make([]string, 3)
         fmt.Println("emp:", s)
     
    @@ -83,7 +85,7 @@ the builtin 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))
     
    @@ -118,7 +120,7 @@ Note that we need to accept a return value from - +
        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)
     
    @@ -166,7 +168,7 @@ of the elements s[2], s[3], and s[4].

    - +
        l = s[:5]
         fmt.Println("sl2:", l)
     
    @@ -180,7 +182,7 @@ of the elements s[2], s[3], and s[4].

    - +
        l = s[2:]
         fmt.Println("sl3:", l)
     
    @@ -195,7 +197,7 @@ in a single line as well.

    - +
        t := []string{"g", "h", "i"}
         fmt.Println("dcl:", t)
     
    @@ -211,7 +213,7 @@ vary, unlike with multi-dimensional arrays.

    - +
        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.

    - + @@ -276,7 +278,7 @@ Go’s other key builtin data structure: maps.

    - + diff --git a/public/sorting b/public/sorting index aa4c760..73f22b1 100644 --- a/public/sorting +++ b/public/sorting @@ -19,7 +19,7 @@ builtins first.

    - + @@ -29,7 +29,9 @@ builtins first.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ builtins first.

    - +
    import "fmt"
     import "sort"
     
    @@ -54,7 +56,7 @@ builtins first.

    - +
    func main() {
     
    @@ -70,7 +72,7 @@ return a new one.

    - +
        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.

    - + @@ -31,7 +31,9 @@ in Go.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ in Go.

    - +
    import "sort"
     import "fmt"
     
    @@ -60,7 +62,7 @@ type.

    - +
    type byLength []string
     
    @@ -79,7 +81,7 @@ we use 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]
     
    @@ -143,7 +145,7 @@ functions.

    - + diff --git a/public/spawning-processes b/public/spawning-processes index b175ead..c6ba21e 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -22,7 +22,7 @@ of spawning processes from Go.

    - + @@ -32,7 +32,9 @@ of spawning processes from Go.

    - + + +
    package main
     
    @@ -44,7 +46,7 @@ of spawning processes from Go.

    - +
    import "fmt"
     import "io/ioutil"
     import "os/exec"
    @@ -58,7 +60,7 @@ of spawning processes from Go.

    - +
    func main() {
     
    @@ -74,7 +76,7 @@ to represent this external process.

    - +
        dateCmd := exec.Command("date")
     
    @@ -90,7 +92,7 @@ and collecting its output. If there were no errors, - +
        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")
     
    @@ -126,7 +128,7 @@ to exit.

    - +
        grepIn, _ := grepCmd.StdinPipe()
         grepOut, _ := grepCmd.StdoutPipe()
         grepCmd.Start()
    @@ -149,7 +151,7 @@ exactly the same way.

    - +
        fmt.Println("> grep hello")
         fmt.Println(string(grepBytes))
     
    @@ -168,7 +170,7 @@ option:

    - +
        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
     
    @@ -220,7 +222,7 @@ as if we had run them directly from the command-line.

    - +
    > 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.

    - + @@ -34,7 +34,9 @@ by exactly 1 goroutine.

    - + + +
    package main
     
    @@ -46,7 +48,7 @@ by exactly 1 goroutine.

    - +
    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() {
     
    @@ -104,7 +106,7 @@ goroutine to respond.

    - +
        var readOps uint64
         var writeOps uint64
     
    @@ -120,7 +122,7 @@ respectively.

    - +
        reads := make(chan readOp)
         writes := make(chan writeOp)
     
    @@ -142,7 +144,7 @@ value in the case of 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)
     
    @@ -235,7 +237,7 @@ approach.

    - +
        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.

    - + diff --git a/public/string-formatting b/public/string-formatting index 3188935..c3118b0 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -19,7 +19,7 @@ common string formatting tasks.

    - + @@ -29,7 +29,9 @@ common string formatting tasks.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ common string formatting tasks.

    - +
    import "fmt"
     import "os"
     
    @@ -54,7 +56,7 @@ common string formatting tasks.

    - +
    type point struct {
         x, y int
     }
    @@ -68,7 +70,7 @@ common string formatting tasks.

    - +
    func main() {
     
    @@ -83,7 +85,7 @@ an instance of our point struct.

    - +
        p := point{1, 2}
         fmt.Printf("%v\n", p)
     
    @@ -98,7 +100,7 @@ include the struct’s field names.

    - +
        fmt.Printf("%+v\n", p)
     
    @@ -113,7 +115,7 @@ would produce that value.

    - +
        fmt.Printf("%#v\n", p)
     
    @@ -126,7 +128,7 @@ would produce that value.

    - +
        fmt.Printf("%T\n", p)
     
    @@ -139,7 +141,7 @@ would produce that value.

    - +
        fmt.Printf("%t\n", true)
     
    @@ -153,7 +155,7 @@ Use %d for standard, base-10 formatting.

    - +
        fmt.Printf("%d\n", 123)
     
    @@ -166,7 +168,7 @@ Use %d for standard, base-10 formatting.

    - +
        fmt.Printf("%b\n", 14)
     
    @@ -180,7 +182,7 @@ given integer.

    - +
        fmt.Printf("%c\n", 33)
     
    @@ -193,7 +195,7 @@ given integer.

    - +
        fmt.Printf("%x\n", 456)
     
    @@ -207,7 +209,7 @@ floats. For basic decimal formatting use %f.

    - +
        fmt.Printf("%f\n", 78.9)
     
    @@ -221,7 +223,7 @@ different versions of) scientific notation.

    - +
        fmt.Printf("%e\n", 123400000.0)
         fmt.Printf("%E\n", 123400000.0)
     
    @@ -235,7 +237,7 @@ different versions of) scientific notation.

    - +
        fmt.Printf("%s\n", "\"string\"")
     
    @@ -248,7 +250,7 @@ different versions of) scientific notation.

    - +
        fmt.Printf("%q\n", "\"string\"")
     
    @@ -263,7 +265,7 @@ per byte of input.

    - +
        fmt.Printf("%x\n", "hex this")
     
    @@ -276,7 +278,7 @@ per byte of input.

    - +
        fmt.Printf("%p\n", &p)
     
    @@ -294,7 +296,7 @@ spaces.

    - +
        fmt.Printf("|%6d|%6d|\n", 12, 345)
     
    @@ -310,7 +312,7 @@ width.precision syntax.

    - +
        fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
     
    @@ -323,7 +325,7 @@ width.precision syntax.

    - +
        fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
     
    @@ -338,7 +340,7 @@ table-like output. For basic right-justified width.

    - +
        fmt.Printf("|%6s|%6s|\n", "foo", "b")
     
    @@ -351,7 +353,7 @@ table-like output. For basic right-justified width.

    - +
        fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
     
    @@ -366,7 +368,7 @@ and returns a string without printing it anywhere.

    - +
        s := fmt.Sprintf("a %s", "string")
         fmt.Println(s)
     
    @@ -381,7 +383,7 @@ and returns a string without printing it anywhere.

    - +
        fmt.Fprintf(os.Stderr, "an %s\n", "error")
     }
     
    @@ -398,7 +400,7 @@ and returns a string without printing it anywhere.

    - +
    $ 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.

    - + @@ -29,7 +29,9 @@ to give you a sense of the package.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ to give you a sense of the package.

    - +
    import s "strings"
     import "fmt"
     
    @@ -56,7 +58,7 @@ it a lot below.

    - +
    var p = fmt.Println
     
    @@ -68,7 +70,7 @@ it a lot below.

    - +
    func main() {
     
    @@ -87,7 +89,7 @@ package docs.

    - +
        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.

    - + @@ -148,7 +150,7 @@ for more information.

    - +
    $ go run string-functions.go
     Contains:   true
     Count:      2
    @@ -172,7 +174,7 @@ for more information.

    - +
    Len:  5
     Char: 101
     
    diff --git a/public/structs b/public/structs index 5d6273d..31c03d0 100644 --- a/public/structs +++ b/public/structs @@ -19,7 +19,7 @@ records.

    - + @@ -29,7 +29,9 @@ records.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ records.

    - +
    import "fmt"
     
    @@ -54,7 +56,7 @@ records.

    - +
    type person struct {
         name string
         age  int
    @@ -69,7 +71,7 @@ records.

    - +
    func main() {
     
    @@ -82,7 +84,7 @@ records.

    - +
        fmt.Println(person{"Bob", 20})
     
    @@ -95,7 +97,7 @@ records.

    - +
        fmt.Println(person{name: "Alice", age: 30})
     
    @@ -108,7 +110,7 @@ records.

    - +
        fmt.Println(person{name: "Fred"})
     
    @@ -121,7 +123,7 @@ records.

    - +
        fmt.Println(&person{name: "Ann", age: 40})
     
    @@ -134,7 +136,7 @@ records.

    - +
        s := person{name: "Sean", age: 50}
         fmt.Println(s.name)
     
    @@ -149,7 +151,7 @@ pointers are automatically dereferenced.

    - +
        sp := &s
         fmt.Println(sp.age)
     
    @@ -163,7 +165,7 @@ pointers are automatically dereferenced.

    - +
        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.

    - + @@ -28,7 +28,9 @@ branches.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ branches.

    - +
    import "fmt"
     import "time"
     
    @@ -53,7 +55,7 @@ branches.

    - +
    func main() {
     
    @@ -66,7 +68,7 @@ branches.

    - +
        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.

    - + @@ -31,7 +31,9 @@ periodically until we stop it.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ periodically until we stop it.

    - +
    import "time"
     import "fmt"
     
    @@ -56,7 +58,7 @@ periodically until we stop it.

    - +
    func main() {
     
    @@ -72,7 +74,7 @@ the values as they arrive every 500ms.

    - +
        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.

    - + @@ -28,7 +28,9 @@ here are some examples.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ here are some examples.

    - +
    import "fmt"
     import "time"
     
    @@ -53,7 +55,7 @@ here are some examples.

    - +
    func main() {
         p := fmt.Println
     
    @@ -67,7 +69,7 @@ here are some examples.

    - +
        now := time.Now()
         p(now)
     
    @@ -83,7 +85,7 @@ with a 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())
     
    @@ -134,7 +136,7 @@ as the second, respectively.

    - +
        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)
     
    @@ -165,7 +167,7 @@ various units.

    - +
        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.

    - + diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index b90c585..f16fbc9 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -18,7 +18,7 @@ pattern-based layouts.

    - + @@ -28,7 +28,9 @@ pattern-based layouts.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ pattern-based layouts.

    - +
    import "fmt"
     import "time"
     
    @@ -53,7 +55,7 @@ pattern-based layouts.

    - +
    func main() {
         p := fmt.Println
     
    @@ -69,7 +71,7 @@ constant.

    - +
        t := time.Now()
         p(t.Format(time.RFC3339))
     
    @@ -83,7 +85,7 @@ constant.

    - +
        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.

    - + @@ -30,7 +30,9 @@ elegant thanks to channels and select.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ elegant thanks to channels and select.

    - +
    import "time"
     import "fmt"
     
    @@ -55,7 +57,7 @@ elegant thanks to channels and select.

    - +
    func main() {
     
    @@ -70,7 +72,7 @@ after 2s.

    - +
        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.

    - + diff --git a/public/timers b/public/timers index 7a11306..7004b5f 100644 --- a/public/timers +++ b/public/timers @@ -21,7 +21,7 @@ at tickers.

    - + @@ -31,7 +31,9 @@ at tickers.

    - + + +
    package main
     
    @@ -43,7 +45,7 @@ at tickers.

    - +
    import "time"
     import "fmt"
     
    @@ -56,7 +58,7 @@ at tickers.

    - +
    func main() {
     
    @@ -72,7 +74,7 @@ time. This timer will wait 2 seconds.

    - +
        timer1 := time.NewTimer(2 * time.Second)
     
    @@ -87,7 +89,7 @@ expired.

    - +
        <-timer1.C
         fmt.Println("Timer 1 expired")
     
    @@ -104,7 +106,7 @@ Here’s an example of that.

    - +
        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.

    - + @@ -28,7 +28,9 @@ Here’s how to parse URLs in Go.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ Here’s how to parse URLs in Go.

    - +
    import "fmt"
     import "net"
     import "net/url"
    @@ -54,7 +56,7 @@ Here’s how to parse URLs in Go.

    - +
    func main() {
     
    @@ -69,7 +71,7 @@ query params, and query fragment.

    - +
        s := "postgres://user:pass@host.com:5432/path?k=v#f"
     
    @@ -82,7 +84,7 @@ query params, and query fragment.

    - +
        u, err := url.Parse(s)
         if err != nil {
             panic(err)
    @@ -98,7 +100,7 @@ query params, and query fragment.

    - +
        fmt.Println(u.Scheme)
     
    @@ -113,7 +115,7 @@ values.

    - +
        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)
     
    @@ -165,7 +167,7 @@ if you only want the first value.

    - +
        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.

    - + @@ -29,7 +29,9 @@ basic examples.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ basic examples.

    - +
    import "fmt"
     
    @@ -53,7 +55,7 @@ basic examples.

    - +
    func main() {
     
    @@ -66,7 +68,7 @@ basic examples.

    - +
        fmt.Println("go" + "lang")
     
    @@ -79,7 +81,7 @@ basic examples.

    - +
        fmt.Println("1+1 =", 1+1)
         fmt.Println("7.0/3.0 =", 7.0/3.0)
     
    @@ -93,7 +95,7 @@ basic examples.

    - +
        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.

    - + @@ -29,7 +29,9 @@ calls.

    - + + +
    package main
     
    @@ -41,7 +43,7 @@ calls.

    - +
    import "fmt"
     
    @@ -53,7 +55,7 @@ calls.

    - +
    func main() {
     
    @@ -66,7 +68,7 @@ calls.

    - +
        var a = "initial"
         fmt.Println(a)
     
    @@ -80,7 +82,7 @@ calls.

    - +
        var b, c int = 1, 2
         fmt.Println(b, c)
     
    @@ -94,7 +96,7 @@ calls.

    - +
        var d = true
         fmt.Println(d)
     
    @@ -110,7 +112,7 @@ zero value for an int is 0.

    - +
        var e int
         fmt.Println(e)
     
    @@ -126,7 +128,7 @@ initializing a variable, e.g. for - +
        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.

    - + @@ -30,7 +30,9 @@ function.

    - + + +
    package main
     
    @@ -42,7 +44,7 @@ function.

    - +
    import "fmt"
     
    @@ -56,7 +58,7 @@ of ints as arguments.

    - +
    func sum(nums ...int) {
         fmt.Print(nums, " ")
         total := 0
    @@ -75,7 +77,7 @@ of ints as arguments.

    - +
    func main() {
     
    @@ -89,7 +91,7 @@ with individual arguments.

    - +
        sum(1, 2)
         sum(1, 2, 3)
     
    @@ -105,7 +107,7 @@ apply them to a variadic function using - +
        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.

    - + diff --git a/public/waitgroups b/public/waitgroups index d2d6b2e..45792a8 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -18,7 +18,7 @@ use a wait group.

    - + @@ -28,7 +28,9 @@ use a wait group.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ use a wait group.

    - +
    import (
         "fmt"
         "sync"
    @@ -59,7 +61,7 @@ pointer.

    - +
    func worker(id int, wg *sync.WaitGroup) {
         fmt.Printf("Worker %d starting\n", id)
     
    @@ -73,7 +75,7 @@ pointer.

    - +
        time.Sleep(time.Second)
         fmt.Printf("Worker %d done\n", id)
     
    @@ -87,7 +89,7 @@ pointer.

    - +
        wg.Done()
     }
     
    @@ -100,7 +102,7 @@ pointer.

    - +
    func main() {
     
    @@ -114,7 +116,7 @@ goroutines launched here to finish.

    - +
        var wg sync.WaitGroup
     
    @@ -128,7 +130,7 @@ counter for each.

    - +
        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()
     }
     
    @@ -162,7 +164,7 @@ all the workers notified they’re done.

    - +
    $ go run waitgroups.go
     Worker 5 starting
     Worker 3 starting
    @@ -186,7 +188,7 @@ is likely to be different for each invocation.

    - + diff --git a/public/worker-pools b/public/worker-pools index e437df8..e1170bf 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -18,7 +18,7 @@ a worker pool using goroutines and channels.

    - + @@ -28,7 +28,9 @@ a worker pool using goroutines and channels.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ a worker pool using goroutines and channels.

    - +
    import "fmt"
     import "time"
     
    @@ -58,7 +60,7 @@ simulate an expensive task.

    - +
    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() {
     
    @@ -92,7 +94,7 @@ channels for this.

    - +
        jobs := make(chan int, 100)
         results := make(chan int, 100)
     
    @@ -107,7 +109,7 @@ because there are no jobs yet.

    - +
        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
     
    diff --git a/public/writing-files b/public/writing-files index b1a3fb9..ca974bd 100644 --- a/public/writing-files +++ b/public/writing-files @@ -18,7 +18,7 @@ ones we saw earlier for reading.

    - + @@ -28,7 +28,9 @@ ones we saw earlier for reading.

    - + + +
    package main
     
    @@ -40,7 +42,7 @@ ones we saw earlier for reading.

    - +
    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() {
     
    @@ -87,7 +89,7 @@ bytes) into a file.

    - +
        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)
     
    @@ -117,7 +119,7 @@ after opening a file.

    - +
        defer f.Close()
     
    @@ -130,7 +132,7 @@ after opening a file.

    - +
        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)
     
    @@ -160,7 +162,7 @@ after opening a file.

    - +
        f.Sync()
     
    @@ -174,7 +176,7 @@ to the buffered readers we saw earlier.

    - +
        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()
     
    @@ -202,7 +204,7 @@ been applied to the underlying writer.

    - +
    }
     
    @@ -219,7 +221,7 @@ been applied to the underlying writer.

    - +
    $ 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.
     
               
               
    -	        
    +            
                 
               
             
    diff --git a/templates/example.tmpl b/templates/example.tmpl
    index b31f742..c9cfb7d 100644
    --- a/templates/example.tmpl
    +++ b/templates/example.tmpl
    @@ -16,7 +16,9 @@
                 {{.DocsRendered}}
               
               
    -	        {{if .CodeRun}}{{end}}
    +            {{if .CodeRun}}
    +              
    +            {{end}}
                 {{.CodeRendered}}
               
             
    
    From 2e3c6d3f51a99e1717807c7ae7fe1c4353c8b3bf Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Tue, 4 Jun 2019 20:32:43 -0700
    Subject: [PATCH 094/133] Initial Travis file for running CI
    
    Each run invokes tools/build, which already returns a non-zero status on errors
    and zero when OK.
    
    Updates #237
    ---
     .travis.yml | 14 ++++++++++++++
     1 file changed, 14 insertions(+)
     create mode 100644 .travis.yml
    
    diff --git a/.travis.yml b/.travis.yml
    new file mode 100644
    index 0000000..415b238
    --- /dev/null
    +++ b/.travis.yml
    @@ -0,0 +1,14 @@
    +language: go
    +
    +go:
    +  - 1.12
    +
    +before_install:
    +  - sudo apt-get update
    +  - sudo apt-get install python
    +
    +install:
    +  - go get -u github.com/russross/blackfriday
    +
    +script:
    +  - 'tools/build'
    
    From c22108bc89ae5aa0641149a9d306624275a9b4c9 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 06:37:51 -0700
    Subject: [PATCH 095/133] Comment
    
    ---
     .travis.yml | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/.travis.yml b/.travis.yml
    index 415b238..1864bc5 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -4,6 +4,7 @@ go:
       - 1.12
     
     before_install:
    +  # We need Python to run pygmentize for generating HTML.
       - sudo apt-get update
       - sudo apt-get install python
     
    
    From 82699a6deb0297d913663c701797e7a50470c144 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 09:57:37 -0700
    Subject: [PATCH 096/133] Add Travis link to README
    
    ---
     README.md | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/README.md b/README.md
    index f9454ea..b68ba5a 100644
    --- a/README.md
    +++ b/README.md
    @@ -1,9 +1,10 @@
    -## Go by Example
    +# Go by Example
    +
    +[![Build Status](https://travis-ci.com/mmcgrana/gobyexample.svg?branch=master)][travis]
     
     Content and build toolchain for [Go by Example](https://gobyexample.com),
     a site that teaches Go via annotated example programs.
     
    -
     ### Overview
     
     The Go by Example site is built by extracting code and
    
    From 5487e88919f1495857367b478726ddfca283d319 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 10:15:13 -0700
    Subject: [PATCH 097/133] Add VERBOSE option to tools/build and generate.go
    
    VERBOSE will be set by TRAVIS (but can also be set by user to diagnose slow
    builds). Using an env var so that it automatically propagates to all the
    sub-scripts and tools without having to pass it through tools/build explicitly.
    ---
     .travis.yml       |  5 ++++-
     tools/build       |  9 +++++++++
     tools/generate.go | 13 ++++++++++++-
     3 files changed, 25 insertions(+), 2 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index 1864bc5..54d1654 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -12,4 +12,7 @@ install:
       - go get -u github.com/russross/blackfriday
     
     script:
    -  - 'tools/build'
    +  - tools/build
    +
    +env:
    +  - VERBOSE=1
    diff --git a/tools/build b/tools/build
    index 3c07db8..b3205bb 100755
    --- a/tools/build
    +++ b/tools/build
    @@ -2,7 +2,16 @@
     
     set -e
     
    +verbose() [[ -v VERBOSE ]]
    +
    +verbose && echo "Running tests..."
     tools/test
    +
    +verbose && echo "Formatting code..."
     tools/format
    +
    +verbose && echo "Measuring line lengths..."
     tools/measure
    +
    +verbose && echo "Generating HTML..."
     tools/generate
    diff --git a/tools/generate.go b/tools/generate.go
    index 32f542c..c840169 100644
    --- a/tools/generate.go
    +++ b/tools/generate.go
    @@ -19,6 +19,10 @@ var cacheDir = "/tmp/gobyexample-cache"
     var siteDir = "./public"
     var pygmentizeBin = "./vendor/pygments/pygmentize"
     
    +func verbose() bool {
    +	return len(os.Getenv("VERBOSE")) > 0
    +}
    +
     func check(err error) {
     	if err != nil {
     		panic(err)
    @@ -221,6 +225,7 @@ func parseAndRenderSegs(sourcePath string) ([]*Seg, string) {
     }
     
     func parseExamples() []*Example {
    +	fmt.Println("Parsing examples")
     	exampleNames := readLines("examples.txt")
     	examples := make([]*Example, 0)
     	for _, exampleName := range exampleNames {
    @@ -261,6 +266,9 @@ func parseExamples() []*Example {
     }
     
     func renderIndex(examples []*Example) {
    +	if verbose() {
    +		fmt.Println("Rendering index")
    +	}
     	indexTmpl := template.New("index")
     	_, err := indexTmpl.Parse(mustReadFile("templates/index.tmpl"))
     	check(err)
    @@ -274,7 +282,10 @@ func renderExamples(examples []*Example) {
     	exampleTmpl := template.New("example")
     	_, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl"))
     	check(err)
    -	for _, example := range examples {
    +	for i, example := range examples {
    +		if verbose() {
    +			fmt.Printf("Rendering %s [%d/%d]\n", example.Name, i, len(examples))
    +		}
     		exampleF, err := os.Create(siteDir + "/" + example.ID)
     		check(err)
     		exampleTmpl.Execute(exampleF, example)
    
    From 3d0bde4f8f5000cbde5cf5262830e4d48401cb30 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 10:17:09 -0700
    Subject: [PATCH 098/133] Add verbose guard in parseExamples
    
    ---
     tools/generate.go | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/tools/generate.go b/tools/generate.go
    index c840169..1b79de8 100644
    --- a/tools/generate.go
    +++ b/tools/generate.go
    @@ -225,7 +225,9 @@ func parseAndRenderSegs(sourcePath string) ([]*Seg, string) {
     }
     
     func parseExamples() []*Example {
    -	fmt.Println("Parsing examples")
    +	if verbose() {
    +		fmt.Println("Parsing examples")
    +	}
     	exampleNames := readLines("examples.txt")
     	examples := make([]*Example, 0)
     	for _, exampleName := range exampleNames {
    
    From 2438aea95f80443de1ba823b9986c316bcfd820b Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 10:25:14 -0700
    Subject: [PATCH 099/133] Move the travis link / build status around
    
    ---
     README.md | 5 ++---
     1 file changed, 2 insertions(+), 3 deletions(-)
    
    diff --git a/README.md b/README.md
    index b68ba5a..42844e5 100644
    --- a/README.md
    +++ b/README.md
    @@ -1,7 +1,5 @@
     # Go by Example
     
    -[![Build Status](https://travis-ci.com/mmcgrana/gobyexample.svg?branch=master)][travis]
    -
     Content and build toolchain for [Go by Example](https://gobyexample.com),
     a site that teaches Go via annotated example programs.
     
    @@ -18,9 +16,10 @@ The built `public` directory can be served by any
     static content system. The production site uses S3 and
     CloudFront, for example.
     
    -
     ### Building
     
    +[![Build Status](https://travis-ci.com/mmcgrana/gobyexample.svg?branch=master)][travis]
    +
     To build the site you'll need Go and Python installed. Run:
     
     ```console
    
    From 09dec4f4fc3ca6923d1576db0854bb96666afeb6 Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Wed, 5 Jun 2019 10:27:39 -0700
    Subject: [PATCH 100/133] Reformat the travis link to render properly
    
    ---
     README.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/README.md b/README.md
    index 42844e5..21686c4 100644
    --- a/README.md
    +++ b/README.md
    @@ -18,7 +18,7 @@ CloudFront, for example.
     
     ### Building
     
    -[![Build Status](https://travis-ci.com/mmcgrana/gobyexample.svg?branch=master)][travis]
    +[![Build Status](https://travis-ci.com/mmcgrana/gobyexample.svg "Travis CI status")](https://travis-ci.com/mmcgrana/gobyexample)
     
     To build the site you'll need Go and Python installed. Run:
     
    
    From d34c7ac64e39abfde318e77d97df59e073e514ad Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Thu, 6 Jun 2019 05:26:20 -0700
    Subject: [PATCH 101/133] Rewrite verbose() to work in OSX bash
    
    ---
     tools/build | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/tools/build b/tools/build
    index b3205bb..f06beae 100755
    --- a/tools/build
    +++ b/tools/build
    @@ -2,7 +2,9 @@
     
     set -e
     
    -verbose() [[ -v VERBOSE ]]
    +verbose() {
    +	! test -z "$VERBOSE"
    +}
     
     verbose && echo "Running tests..."
     tools/test
    
    From 52be303a71d232a90a35e7391964dde28e2972fe Mon Sep 17 00:00:00 2001
    From: Eli Bendersky 
    Date: Thu, 6 Jun 2019 06:17:45 -0700
    Subject: [PATCH 102/133] File Paths example
    
    ---
     examples.txt                        |   1 +
     examples/file-paths/file-paths.go   |  62 ++++++++
     examples/file-paths/file-paths.hash |   2 +
     examples/file-paths/file-paths.sh   |  12 ++
     public/file-paths                   | 238 ++++++++++++++++++++++++++++
     public/index.html                   |   2 +
     public/line-filters                 |   2 +-
     7 files changed, 318 insertions(+), 1 deletion(-)
     create mode 100644 examples/file-paths/file-paths.go
     create mode 100644 examples/file-paths/file-paths.hash
     create mode 100644 examples/file-paths/file-paths.sh
     create mode 100644 public/file-paths
    
    diff --git a/examples.txt b/examples.txt
    index d4859d3..91a1fde 100644
    --- a/examples.txt
    +++ b/examples.txt
    @@ -57,6 +57,7 @@ Base64 Encoding
     Reading Files
     Writing Files
     Line Filters
    +File Paths
     Command-Line Arguments
     Command-Line Flags
     Command-Line Subcommands
    diff --git a/examples/file-paths/file-paths.go b/examples/file-paths/file-paths.go
    new file mode 100644
    index 0000000..75b017d
    --- /dev/null
    +++ b/examples/file-paths/file-paths.go
    @@ -0,0 +1,62 @@
    +// The `filepath` package provides functions to parse
    +// and construct *file paths* in a way that is portable
    +// between operating systems; `dir/file` on Linux vs.
    +// `dir\file` on Windows, for example.
    +package main
    +
    +import (
    +	"fmt"
    +	"path/filepath"
    +	"strings"
    +)
    +
    +func main() {
    +
    +	// `Join` should be used to construct paths in a
    +	// portable way. It takes any number of arguments
    +	// and constructs a hierarchical path from them.
    +	p := filepath.Join("dir1", "dir2", "filename")
    +	fmt.Println("p:", p)
    +
    +	// You should always use `Join` instead of
    +	// concatenating `/`s or `\`s manually. In addition
    +	// to providing portability, `Join` will also
    +	// normalize paths by removing superfluous separators
    +	// and directory changes.
    +	fmt.Println(filepath.Join("dir1//", "filename"))
    +	fmt.Println(filepath.Join("dir1/../dir1", "filename"))
    +
    +	// `Dir` and `Base` can be used to split a path to the
    +	// directory and the file. Alternatively, `Split` will
    +	// return both in the same call.
    +	fmt.Println("Dir(p):", filepath.Dir(p))
    +	fmt.Println("Base(p):", filepath.Base(p))
    +
    +	// To check whether a path is absolute, use `IsAbs`.
    +	fmt.Println(filepath.IsAbs("dir/file"))
    +	fmt.Println(filepath.IsAbs("/dir/file"))
    +
    +	filename := "config.json"
    +
    +	// To find a file's extension, use `Ext`.
    +	ext := filepath.Ext(filename)
    +	fmt.Println(ext)
    +
    +	// To find the file's name with the extension removed,
    +	// use `TrimSuffix`.
    +	fmt.Println(strings.TrimSuffix(filename, ext))
    +
    +	// `Rel` finds a relative path between a *base* and a
    +	// *target*.
    +	rel, err := filepath.Rel("a/b", "a/b/t/file")
    +	if err != nil {
    +		panic(err)
    +	}
    +	fmt.Println(rel)
    +
    +	rel, err = filepath.Rel("a/b", "a/c/t/file")
    +	if err != nil {
    +		panic(err)
    +	}
    +	fmt.Println(rel)
    +}
    diff --git a/examples/file-paths/file-paths.hash b/examples/file-paths/file-paths.hash
    new file mode 100644
    index 0000000..7cc06ab
    --- /dev/null
    +++ b/examples/file-paths/file-paths.hash
    @@ -0,0 +1,2 @@
    +4611ff69626490eb50673a739707d870fac79142
    +eUhAltl7_sI
    diff --git a/examples/file-paths/file-paths.sh b/examples/file-paths/file-paths.sh
    new file mode 100644
    index 0000000..4ef4251
    --- /dev/null
    +++ b/examples/file-paths/file-paths.sh
    @@ -0,0 +1,12 @@
    +$ go run file-paths.go
    +p: dir1/dir2/filename
    +dir1/filename
    +dir1/filename
    +Dir(p): dir1/dir2
    +Base(p): filename
    +false
    +true
    +.json
    +config
    +t/file
    +../c/t/file
    diff --git a/public/file-paths b/public/file-paths
    new file mode 100644
    index 0000000..9085662
    --- /dev/null
    +++ b/public/file-paths
    @@ -0,0 +1,238 @@
    +
    +
    +  
    +    
    +    Go by Example: File Paths
    +    
    +  
    +  
    +    
    +

    Go by Example: File Paths

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    The filepath package provides functions to parse +and construct file paths in a way that is portable +between operating systems; dir/file on Linux vs. +dir\file on Windows, for example.

    + +
    + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "path/filepath"
    +    "strings"
    +)
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    Join should be used to construct paths in a +portable way. It takes any number of arguments +and constructs a hierarchical path from them.

    + +
    + +
        p := filepath.Join("dir1", "dir2", "filename")
    +    fmt.Println("p:", p)
    +
    + +
    +

    You should always use Join instead of +concatenating /s or \s manually. In addition +to providing portability, Join will also +normalize paths by removing superfluous separators +and directory changes.

    + +
    + +
        fmt.Println(filepath.Join("dir1//", "filename"))
    +    fmt.Println(filepath.Join("dir1/../dir1", "filename"))
    +
    + +
    +

    Dir and Base can be used to split a path to the +directory and the file. Alternatively, Split will +return both in the same call.

    + +
    + +
        fmt.Println("Dir(p):", filepath.Dir(p))
    +    fmt.Println("Base(p):", filepath.Base(p))
    +
    + +
    +

    To check whether a path is absolute, use IsAbs.

    + +
    + +
        fmt.Println(filepath.IsAbs("dir/file"))
    +    fmt.Println(filepath.IsAbs("/dir/file"))
    +
    + +
    + + + +
        filename := "config.json"
    +
    + +
    +

    To find a file’s extension, use Ext.

    + +
    + +
        ext := filepath.Ext(filename)
    +    fmt.Println(ext)
    +
    + +
    +

    To find the file’s name with the extension removed, +use TrimSuffix.

    + +
    + +
        fmt.Println(strings.TrimSuffix(filename, ext))
    +
    + +
    +

    Rel finds a relative path between a base and a +target.

    + +
    + +
        rel, err := filepath.Rel("a/b", "a/b/t/file")
    +    if err != nil {
    +        panic(err)
    +    }
    +    fmt.Println(rel)
    +
    + +
    + + + +
        rel, err = filepath.Rel("a/b", "a/c/t/file")
    +    if err != nil {
    +        panic(err)
    +    }
    +    fmt.Println(rel)
    +}
    +
    + +
    + + + + + + + + +
    + + + +
    $ go run file-paths.go
    +p: dir1/dir2/filename
    +dir1/filename
    +dir1/filename
    +Dir(p): dir1/dir2
    +Base(p): filename
    +false
    +true
    +.json
    +config
    +t/file
    +../c/t/file
    +
    + +
    + + +

    + Next example: Command-Line Arguments. +

    + + +
    + + diff --git a/public/index.html b/public/index.html index e3960aa..ef6fe69 100644 --- a/public/index.html +++ b/public/index.html @@ -141,6 +141,8 @@
  • Line Filters
  • +
  • File Paths
  • +
  • Command-Line Arguments
  • Command-Line Flags
  • diff --git a/public/line-filters b/public/line-filters index d1dd866..d264214 100644 --- a/public/line-filters +++ b/public/line-filters @@ -183,7 +183,7 @@ lowercase lines.

    - Next example: Command-Line Arguments. + Next example: File Paths.

    package main
    @@ -109,7 +109,7 @@ return both in the same call.

    -

    To check whether a path is absolute, use IsAbs.

    +

    We can check whether a path is absolute.

    @@ -135,7 +135,8 @@ return both in the same call.

    -

    To find a file’s extension, use Ext.

    +

    Some file names have extensions following a dot. We +can split the extension out of such names with Ext.

    @@ -150,7 +151,7 @@ return both in the same call.

    To find the file’s name with the extension removed, -use TrimSuffix.

    +use strings.TrimSuffix.

    @@ -164,7 +165,8 @@ use TrimSuffix.

    Rel finds a relative path between a base and a -target.

    +target. It returns an error if the target cannot +be made relative to base.

    From cdbdae9715bf1ff501e4f22f7e066d5729ec1fb3 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 7 Jun 2019 06:12:30 -0700 Subject: [PATCH 104/133] Do progress reporting during parsing/processing stage, not HTML render stage --- tools/generate.go | 75 ++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/tools/generate.go b/tools/generate.go index 1b79de8..24a5a26 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -225,40 +225,43 @@ func parseAndRenderSegs(sourcePath string) ([]*Seg, string) { } func parseExamples() []*Example { - if verbose() { - fmt.Println("Parsing examples") - } - exampleNames := readLines("examples.txt") - examples := make([]*Example, 0) - for _, exampleName := range exampleNames { - if (exampleName != "") && !strings.HasPrefix(exampleName, "#") { - example := Example{Name: exampleName} - exampleID := strings.ToLower(exampleName) - exampleID = strings.Replace(exampleID, " ", "-", -1) - exampleID = strings.Replace(exampleID, "/", "-", -1) - exampleID = strings.Replace(exampleID, "'", "", -1) - exampleID = dashPat.ReplaceAllString(exampleID, "-") - example.ID = exampleID - example.Segs = make([][]*Seg, 0) - sourcePaths := mustGlob("examples/" + exampleID + "/*") - for _, sourcePath := range sourcePaths { - if strings.HasSuffix(sourcePath, ".hash") { - example.GoCodeHash, example.URLHash = parseHashFile(sourcePath) - } else { - sourceSegs, filecontents := parseAndRenderSegs(sourcePath) - if filecontents != "" { - example.GoCode = filecontents - } - example.Segs = append(example.Segs, sourceSegs) - } - } - newCodeHash := sha1Sum(example.GoCode) - if example.GoCodeHash != newCodeHash { - example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") - } - examples = append(examples, &example) + var exampleNames []string + for _, line := range readLines("examples.txt") { + if line != "" && !strings.HasPrefix(line, "#") { + exampleNames = append(exampleNames, line) } } + examples := make([]*Example, 0) + for i, exampleName := range exampleNames { + if verbose() { + fmt.Printf("Processing %s [%d/%d]\n", exampleName, i+1, len(exampleNames)) + } + example := Example{Name: exampleName} + exampleID := strings.ToLower(exampleName) + exampleID = strings.Replace(exampleID, " ", "-", -1) + exampleID = strings.Replace(exampleID, "/", "-", -1) + exampleID = strings.Replace(exampleID, "'", "", -1) + exampleID = dashPat.ReplaceAllString(exampleID, "-") + example.ID = exampleID + example.Segs = make([][]*Seg, 0) + sourcePaths := mustGlob("examples/" + exampleID + "/*") + for _, sourcePath := range sourcePaths { + if strings.HasSuffix(sourcePath, ".hash") { + example.GoCodeHash, example.URLHash = parseHashFile(sourcePath) + } else { + sourceSegs, filecontents := parseAndRenderSegs(sourcePath) + if filecontents != "" { + example.GoCode = filecontents + } + example.Segs = append(example.Segs, sourceSegs) + } + } + newCodeHash := sha1Sum(example.GoCode) + if example.GoCodeHash != newCodeHash { + example.URLHash = resetURLHashFile(newCodeHash, example.GoCode, "examples/"+example.ID+"/"+example.ID+".hash") + } + examples = append(examples, &example) + } for i, example := range examples { if i < (len(examples) - 1) { example.NextExample = examples[i+1] @@ -281,13 +284,13 @@ func renderIndex(examples []*Example) { } func renderExamples(examples []*Example) { + if verbose() { + fmt.Println("Generating HTML") + } exampleTmpl := template.New("example") _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) check(err) - for i, example := range examples { - if verbose() { - fmt.Printf("Rendering %s [%d/%d]\n", example.Name, i, len(examples)) - } + for _, example := range examples { exampleF, err := os.Create(siteDir + "/" + example.ID) check(err) exampleTmpl.Execute(exampleF, example) From cb0f0a305624f6dd0b50b374ebb5d0a5f21a5e1d Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 7 Jun 2019 06:17:26 -0700 Subject: [PATCH 105/133] Tweak logged text --- tools/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generate.go b/tools/generate.go index 24a5a26..4872b3b 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -285,7 +285,7 @@ func renderIndex(examples []*Example) { func renderExamples(examples []*Example) { if verbose() { - fmt.Println("Generating HTML") + fmt.Println("Rendering templates") } exampleTmpl := template.New("example") _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) From 70cb6ffb45bd8a39365b4da3ae4a23488a0a1038 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 7 Jun 2019 06:26:27 -0700 Subject: [PATCH 106/133] Add printout when sending a request to play.golang.org --- tools/generate.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/generate.go b/tools/generate.go index 4872b3b..51b4a04 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -143,6 +143,9 @@ func parseHashFile(sourcePath string) (string, string) { } func resetURLHashFile(codehash, code, sourcePath string) string { + if verbose() { + fmt.Println(" Sending request to play.golang.org") + } payload := strings.NewReader(code) resp, err := http.Post("https://play.golang.org/share", "text/plain", payload) if err != nil { From 447d77234f9d90ed8cf9b938f38dddc5fa021641 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 8 Jun 2019 06:11:13 -0700 Subject: [PATCH 107/133] Add directories example --- examples.txt | 1 + examples/directories/directories.go | 77 +++++++ examples/directories/directories.hash | 2 + examples/directories/directories.sh | 7 + public/directories | 297 ++++++++++++++++++++++++++ public/file-paths | 2 +- public/index.html | 2 + 7 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 examples/directories/directories.go create mode 100644 examples/directories/directories.hash create mode 100644 examples/directories/directories.sh create mode 100644 public/directories diff --git a/examples.txt b/examples.txt index 91a1fde..887ef69 100644 --- a/examples.txt +++ b/examples.txt @@ -58,6 +58,7 @@ Reading Files Writing Files Line Filters File Paths +Directories Command-Line Arguments Command-Line Flags Command-Line Subcommands diff --git a/examples/directories/directories.go b/examples/directories/directories.go new file mode 100644 index 0000000..1d4eec9 --- /dev/null +++ b/examples/directories/directories.go @@ -0,0 +1,77 @@ +// Go has several useful functions for working with +// *directories* in the file system. + +package main + +import ( + "fmt" + "io/ioutil" + "os" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + + // Create a new sub-directory in the current working + // directory. + err := os.Mkdir("subdir", 0755) + check(err) + + // When creating temporary directories, it's good + // practice to `defer` their removal. `os.RemoveAll` + // will delete a whole directory tree (similarly to + // `rm -rf`). + defer os.RemoveAll("subdir") + + // Helper function to create a new empty file. + createEmptyFile := func(name string) { + d := []byte("") + check(ioutil.WriteFile(name, d, 0644)) + } + + createEmptyFile("subdir/file1") + + // We can create a hierarchy of directories, including + // parents wiht `MkdirAll`. This is similar to the + // command-line `mkdir -p`. + err = os.MkdirAll("subdir/parent/child", 0755) + check(err) + + createEmptyFile("subdir/parent/file2") + createEmptyFile("subdir/parent/file3") + createEmptyFile("subdir/parent/child/file4") + + // `ReadDir` lists directory contents, returning a + // slice of `os.FileInfo` objects. + c, err := ioutil.ReadDir("subdir/parent") + check(err) + + fmt.Println("Listing subdir/parent") + for _, entry := range c { + fmt.Println(entry.Name(), entry.IsDir()) + } + + // `Chdir` lets us change the current working directory, + // similarly to `cd`. + err = os.Chdir("subdir/parent/child") + check(err) + + // Now we'll see the contents of "subdir/parent/child" + // when listing the *current* directory. + c, err = ioutil.ReadDir(".") + check(err) + + fmt.Println("Listing subdir/parent/child") + for _, entry := range c { + fmt.Println(entry.Name(), entry.IsDir()) + } + + // `cd` back to where we started. + err = os.Chdir("../../..") + check(err) +} diff --git a/examples/directories/directories.hash b/examples/directories/directories.hash new file mode 100644 index 0000000..b599edd --- /dev/null +++ b/examples/directories/directories.hash @@ -0,0 +1,2 @@ +7b2eed223a00c8a84df582bd254a642c7a57dd9b +UnjBL6NmR8- diff --git a/examples/directories/directories.sh b/examples/directories/directories.sh new file mode 100644 index 0000000..cc48f74 --- /dev/null +++ b/examples/directories/directories.sh @@ -0,0 +1,7 @@ +$ go run directories.go +Listing subdir/parent +child true +file2 false +file3 false +Listing subdir/parent/child +file4 false diff --git a/public/directories b/public/directories new file mode 100644 index 0000000..f80b48f --- /dev/null +++ b/public/directories @@ -0,0 +1,297 @@ + + + + + Go by Example: Directories + + + +
    +

    Go by Example: Directories

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Go has several useful functions for working with +directories in the file system.

    + +
    + + +
    + + + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "io/ioutil"
    +    "os"
    +)
    +
    + +
    + + + +
    func check(e error) {
    +    if e != nil {
    +        panic(e)
    +    }
    +}
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    Create a new sub-directory in the current working +directory.

    + +
    + +
        err := os.Mkdir("subdir", 0755)
    +    check(err)
    +
    + +
    +

    When creating temporary directories, it’s good +practice to defer their removal. os.RemoveAll +will delete a whole directory tree (similarly to +rm -rf).

    + +
    + +
        defer os.RemoveAll("subdir")
    +
    + +
    +

    Helper function to create a new empty file.

    + +
    + +
        createEmptyFile := func(name string) {
    +        d := []byte("")
    +        check(ioutil.WriteFile(name, d, 0644))
    +    }
    +
    + +
    + + + +
        createEmptyFile("subdir/file1")
    +
    + +
    +

    We can create a hierarchy of directories, including +parents wiht MkdirAll. This is similar to the +command-line mkdir -p.

    + +
    + +
        err = os.MkdirAll("subdir/parent/child", 0755)
    +    check(err)
    +
    + +
    + + + +
        createEmptyFile("subdir/parent/file2")
    +    createEmptyFile("subdir/parent/file3")
    +    createEmptyFile("subdir/parent/child/file4")
    +
    + +
    +

    ReadDir lists directory contents, returning a +slice of os.FileInfo objects.

    + +
    + +
        c, err := ioutil.ReadDir("subdir/parent")
    +    check(err)
    +
    + +
    + + + +
        fmt.Println("Listing subdir/parent")
    +    for _, entry := range c {
    +        fmt.Println(entry.Name(), entry.IsDir())
    +    }
    +
    + +
    +

    Chdir lets us change the current working directory, +similarly to cd.

    + +
    + +
        err = os.Chdir("subdir/parent/child")
    +    check(err)
    +
    + +
    +

    Now we’ll see the contents of “subdir/parent/child” +when listing the current directory.

    + +
    + +
        c, err = ioutil.ReadDir(".")
    +    check(err)
    +
    + +
    + + + +
        fmt.Println("Listing subdir/parent/child")
    +    for _, entry := range c {
    +        fmt.Println(entry.Name(), entry.IsDir())
    +    }
    +
    + +
    +

    cd back to where we started.

    + +
    + +
        err = os.Chdir("../../..")
    +    check(err)
    +}
    +
    + +
    + + + + + + + + +
    + + + +
    $ go run directories.go
    +Listing subdir/parent
    +child true
    +file2 false
    +file3 false
    +Listing subdir/parent/child
    +file4 false
    +
    + +
    + + +

    + Next example: Command-Line Arguments. +

    + + +
    + + diff --git a/public/file-paths b/public/file-paths index 65e3886..f7b24a1 100644 --- a/public/file-paths +++ b/public/file-paths @@ -229,7 +229,7 @@ be made relative to base.

    - Next example: Command-Line Arguments. + Next example: Directories.

  • File Paths
  • +
  • Directories
  • +
  • Command-Line Arguments
  • Command-Line Flags
  • From bee52f22ce5faaef01bb4318220ad3b7dc787b65 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Sat, 8 Jun 2019 11:21:40 -0400 Subject: [PATCH 108/133] Change word --- tools/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generate.go b/tools/generate.go index 51b4a04..97d8ab5 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -288,7 +288,7 @@ func renderIndex(examples []*Example) { func renderExamples(examples []*Example) { if verbose() { - fmt.Println("Rendering templates") + fmt.Println("Rendering examples") } exampleTmpl := template.New("example") _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) From ee8c401ac383887e769f0348a4df6f5a11e38836 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 8 Jun 2019 11:11:58 -0700 Subject: [PATCH 109/133] Update examples/directories/directories.go Co-Authored-By: Mark McGranaghan --- examples/directories/directories.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/directories/directories.go b/examples/directories/directories.go index 1d4eec9..0384354 100644 --- a/examples/directories/directories.go +++ b/examples/directories/directories.go @@ -37,7 +37,7 @@ func main() { createEmptyFile("subdir/file1") // We can create a hierarchy of directories, including - // parents wiht `MkdirAll`. This is similar to the + // parents with `MkdirAll`. This is similar to the // command-line `mkdir -p`. err = os.MkdirAll("subdir/parent/child", 0755) check(err) From 1be2c1c9100d53294505f42e9d8e468a4cbe7fce Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 8 Jun 2019 11:20:00 -0700 Subject: [PATCH 110/133] Add Walk --- examples/directories/directories.go | 22 ++++++++- examples/directories/directories.hash | 4 +- examples/directories/directories.sh | 16 +++++-- public/directories | 64 +++++++++++++++++++++++---- 4 files changed, 89 insertions(+), 17 deletions(-) diff --git a/examples/directories/directories.go b/examples/directories/directories.go index 0384354..8abdb51 100644 --- a/examples/directories/directories.go +++ b/examples/directories/directories.go @@ -7,6 +7,7 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" ) func check(e error) { @@ -53,7 +54,7 @@ func main() { fmt.Println("Listing subdir/parent") for _, entry := range c { - fmt.Println(entry.Name(), entry.IsDir()) + fmt.Println(" ", entry.Name(), entry.IsDir()) } // `Chdir` lets us change the current working directory, @@ -68,10 +69,27 @@ func main() { fmt.Println("Listing subdir/parent/child") for _, entry := range c { - fmt.Println(entry.Name(), entry.IsDir()) + fmt.Println(" ", entry.Name(), entry.IsDir()) } // `cd` back to where we started. err = os.Chdir("../../..") check(err) + + // We can also visit a directory *recursively*, + // including all its sub-directories. `Walk` accepts + // a callback function to handle every file or + // directory visited. + fmt.Println("Visiting subdir") + err = filepath.Walk("subdir", visit) +} + +// visit is called for every file or directory found +// recursively by `filepath.Walk`. +func visit(p string, info os.FileInfo, err error) error { + if err != nil { + return err + } + fmt.Println(" ", p, info.IsDir()) + return nil } diff --git a/examples/directories/directories.hash b/examples/directories/directories.hash index b599edd..75cb9fa 100644 --- a/examples/directories/directories.hash +++ b/examples/directories/directories.hash @@ -1,2 +1,2 @@ -7b2eed223a00c8a84df582bd254a642c7a57dd9b -UnjBL6NmR8- +57a8f629f040270c15a0375be4424b392edf3c95 +LI7ty_KDozd diff --git a/examples/directories/directories.sh b/examples/directories/directories.sh index cc48f74..31a8f0c 100644 --- a/examples/directories/directories.sh +++ b/examples/directories/directories.sh @@ -1,7 +1,15 @@ $ go run directories.go Listing subdir/parent -child true -file2 false -file3 false + child true + file2 false + file3 false Listing subdir/parent/child -file4 false + file4 false +Visiting subdir + subdir true + subdir/file1 false + subdir/parent true + subdir/parent/child true + subdir/parent/child/file4 false + subdir/parent/file2 false + subdir/parent/file3 false diff --git a/public/directories b/public/directories index f80b48f..a1bfce5 100644 --- a/public/directories +++ b/public/directories @@ -28,7 +28,7 @@ - +
    package main
    @@ -47,6 +47,7 @@
         "fmt"
         "io/ioutil"
         "os"
    +    "path/filepath"
     )
     
    @@ -143,7 +144,7 @@ will delete a whole directory tree (similarly to

    We can create a hierarchy of directories, including -parents wiht MkdirAll. This is similar to the +parents with MkdirAll. This is similar to the command-line mkdir -p.

    @@ -193,7 +194,7 @@ slice of os.FileInfo objects.

        fmt.Println("Listing subdir/parent")
         for _, entry := range c {
    -        fmt.Println(entry.Name(), entry.IsDir())
    +        fmt.Println(" ", entry.Name(), entry.IsDir())
         }
     
    @@ -238,7 +239,7 @@ when listing the current directory.

        fmt.Println("Listing subdir/parent/child")
         for _, entry := range c {
    -        fmt.Println(entry.Name(), entry.IsDir())
    +        fmt.Println(" ", entry.Name(), entry.IsDir())
         }
     
    @@ -250,10 +251,47 @@ when listing the current directory.

    cd back to where we started.

    - +
        err = os.Chdir("../../..")
         check(err)
    +
    + + + + + + +

    We can also visit a directory recursively, +including all its sub-directories. Walk accepts +a callback function to handle every file or +directory visited.

    + + + + +
        fmt.Println("Visiting subdir")
    +    err = filepath.Walk("subdir", visit)
    +}
    +
    + + + + + + +

    visit is called for every file or directory found +recursively by filepath.Walk.

    + + + + +
    func visit(p string, info os.FileInfo, err error) error {
    +    if err != nil {
    +        return err
    +    }
    +    fmt.Println(" ", p, info.IsDir())
    +    return nil
     }
     
    @@ -272,11 +310,19 @@ when listing the current directory.

    $ go run directories.go
     Listing subdir/parent
    -child true
    -file2 false
    -file3 false
    +  child true
    +  file2 false
    +  file3 false
     Listing subdir/parent/child
    -file4 false
    +  file4 false
    +Visiting subdir
    +  subdir true
    +  subdir/file1 false
    +  subdir/parent true
    +  subdir/parent/child true
    +  subdir/parent/child/file4 false
    +  subdir/parent/file2 false
    +  subdir/parent/file3 false
     
    From 39cc92ae7f31de3943567e340aab729214eb9fa5 Mon Sep 17 00:00:00 2001 From: Ross Eskridge Date: Wed, 12 Jun 2019 20:18:46 +0000 Subject: [PATCH 111/133] Fix forward reference in command line flags text Text in command line flags referenced environment variables, moved that to subcommands to read correctly. --- examples/command-line-flags/command-line-flags.sh | 3 --- examples/command-line-subcommands/command-line-subcommands.sh | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/command-line-flags/command-line-flags.sh b/examples/command-line-flags/command-line-flags.sh index d8fb754..246f4c7 100644 --- a/examples/command-line-flags/command-line-flags.sh +++ b/examples/command-line-flags/command-line-flags.sh @@ -54,6 +54,3 @@ $ ./command-line-flags -wat flag provided but not defined: -wat Usage of ./command-line-flags: ... - -# Next we'll look at environment variables, another common -# way to parameterize programs. diff --git a/examples/command-line-subcommands/command-line-subcommands.sh b/examples/command-line-subcommands/command-line-subcommands.sh index c5948e8..32531ed 100644 --- a/examples/command-line-subcommands/command-line-subcommands.sh +++ b/examples/command-line-subcommands/command-line-subcommands.sh @@ -19,3 +19,6 @@ flag provided but not defined: -enable Usage of bar: -level int level + +# Next we'll look at environment variables, another common +# way to parameterize programs. From d18911d3e835b25b0d3dd3b5bc91f6b4f93f618f Mon Sep 17 00:00:00 2001 From: Ross Eskridge Date: Thu, 13 Jun 2019 13:59:54 +0000 Subject: [PATCH 112/133] Generate html with textual reference fix --- public/command-line-flags | 14 +------------- public/command-line-subcommands | 14 +++++++++++++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/public/command-line-flags b/public/command-line-flags index 42dad0b..43ec18f 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -272,7 +272,7 @@ generated help text for the command-line program.

    and show the help text again.

    - +
    $ ./command-line-flags -wat
     flag provided but not defined: -wat
    @@ -283,18 +283,6 @@ and show the help text again.

    - - -

    Next we’ll look at environment variables, another common -way to parameterize programs.

    - - - - - - - - diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 945f646..39b385b 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -214,7 +214,7 @@ have access to trailing positional arguments.

    But bar won’t accept foo’s flags.

    - +
    $ ./command-line-subcommands bar -enable a1
     flag provided but not defined: -enable
    @@ -226,6 +226,18 @@ have access to trailing positional arguments.

    + + +

    Next we’ll look at environment variables, another common +way to parameterize programs.

    + + + + + + + + From 3b153c7d805c3ed5374923480f42b7561af655b2 Mon Sep 17 00:00:00 2001 From: Maciek Niemczyk Date: Mon, 17 Jun 2019 14:25:41 +0200 Subject: [PATCH 113/133] according to https://www.joeshaw.org/dont-defer-close-on-writable-files/ one should not use defer file.close(), its a bad pattern --- examples/defer/defer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 06c827f..8d1c3ed 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -40,5 +40,9 @@ func writeFile(f *os.File) { func closeFile(f *os.File) { fmt.Println("closing") - f.Close() + err := f.Close() + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } } From 862833fcb87968830c9a7cb533d198dbfbddb06d Mon Sep 17 00:00:00 2001 From: Maciek Niemczyk Date: Mon, 17 Jun 2019 14:46:02 +0200 Subject: [PATCH 114/133] CDR request --- examples/defer/defer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 8d1c3ed..0eca985 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -42,7 +42,7 @@ func closeFile(f *os.File) { fmt.Println("closing") err := f.Close() if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "error: %v\n", err) + fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } } From b00cb1ec7eb532ddc1bf5a27fd1303fc78714b49 Mon Sep 17 00:00:00 2001 From: Maciek Niemczyk Date: Mon, 17 Jun 2019 14:47:46 +0200 Subject: [PATCH 115/133] CDR request 2 --- examples/defer/defer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 0eca985..0941d10 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -41,6 +41,7 @@ func writeFile(f *os.File) { func closeFile(f *os.File) { fmt.Println("closing") err := f.Close() + // It is important to check for errors when closing a file, even in a deferred function. if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) From 1aa6ac2a7a747405c1bc993ebbcca9cb47e20e26 Mon Sep 17 00:00:00 2001 From: Maciek Niemczyk Date: Mon, 17 Jun 2019 15:13:11 +0200 Subject: [PATCH 116/133] those files has been changed after running tools/build --- examples/defer/defer.hash | 4 ++-- public/defer | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/examples/defer/defer.hash b/examples/defer/defer.hash index 2994617..5e437d4 100644 --- a/examples/defer/defer.hash +++ b/examples/defer/defer.hash @@ -1,2 +1,2 @@ -570699fc50a1d39e9d0ad6a4461aef3248b080e1 -xPbQ5SGkH2O +4e2229c593e102d4efd101a7e9aa21f3345e90d1 +S2RuPTkABip diff --git a/public/defer b/public/defer index 43445ec..8f0b130 100644 --- a/public/defer +++ b/public/defer @@ -30,7 +30,7 @@ purposes of cleanup. defer is often used where e.g. - +
    package main
    @@ -132,15 +132,31 @@ of the enclosing function (main), after
               
             
             
    +        
    +          
    +            

    It is important to check for errors when closing a file, even in a deferred function.

    + + + + +
    func closeFile(f *os.File) {
    +    fmt.Println("closing")
    +    err := f.Close()
    +
    + + + + -
    func closeFile(f *os.File) {
    -    fmt.Println("closing")
    -    f.Close()
    +            
        if err != nil {
    +        fmt.Fprintf(os.Stderr, "error: %v\n", err)
    +        os.Exit(1)
    +    }
     }
     
    From 751eeda8b2117d0f7fd00c6444f25237694eab48 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Sun, 30 Jun 2019 13:55:57 -0700 Subject: [PATCH 117/133] Code styling for symbol references --- examples/directories/directories.go | 4 ++-- examples/directories/directories.hash | 4 ++-- public/directories | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/directories/directories.go b/examples/directories/directories.go index 8abdb51..9b71274 100644 --- a/examples/directories/directories.go +++ b/examples/directories/directories.go @@ -62,7 +62,7 @@ func main() { err = os.Chdir("subdir/parent/child") check(err) - // Now we'll see the contents of "subdir/parent/child" + // Now we'll see the contents of `subdir/parent/child` // when listing the *current* directory. c, err = ioutil.ReadDir(".") check(err) @@ -84,7 +84,7 @@ func main() { err = filepath.Walk("subdir", visit) } -// visit is called for every file or directory found +// `visit` is called for every file or directory found // recursively by `filepath.Walk`. func visit(p string, info os.FileInfo, err error) error { if err != nil { diff --git a/examples/directories/directories.hash b/examples/directories/directories.hash index 75cb9fa..cebae56 100644 --- a/examples/directories/directories.hash +++ b/examples/directories/directories.hash @@ -1,2 +1,2 @@ -57a8f629f040270c15a0375be4424b392edf3c95 -LI7ty_KDozd +83f67db91816b4544072d0a4d099111a21c60723 +-7kWq0PmATF diff --git a/public/directories b/public/directories index a1bfce5..e0746ba 100644 --- a/public/directories +++ b/public/directories @@ -28,7 +28,7 @@ - +
    package main
    @@ -218,7 +218,7 @@ similarly to cd.

    -

    Now we’ll see the contents of “subdir/parent/child” +

    Now we’ll see the contents of subdir/parent/child when listing the current directory.

    @@ -280,7 +280,7 @@ directory visited.

    -

    visit is called for every file or directory found +

    visit is called for every file or directory found recursively by filepath.Walk.

    From 8219122e44d0dd7a40b082db37a0baed94246204 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 17 Jun 2019 06:01:41 -0700 Subject: [PATCH 118/133] Temporary files and directories sample Followup on discussion in #243 --- examples.txt | 1 + .../temporary-files-and-directories.go | 65 +++++ .../temporary-files-and-directories.hash | 2 + .../temporary-files-and-directories.sh | 4 + public/index.html | 2 + public/temporary-files-and-directories | 232 ++++++++++++++++++ public/writing-files | 2 +- 7 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 examples/temporary-files-and-directories/temporary-files-and-directories.go create mode 100644 examples/temporary-files-and-directories/temporary-files-and-directories.hash create mode 100644 examples/temporary-files-and-directories/temporary-files-and-directories.sh create mode 100644 public/temporary-files-and-directories diff --git a/examples.txt b/examples.txt index 887ef69..ae601df 100644 --- a/examples.txt +++ b/examples.txt @@ -56,6 +56,7 @@ SHA1 Hashes Base64 Encoding Reading Files Writing Files +Temporary Files and Directories Line Filters File Paths Directories diff --git a/examples/temporary-files-and-directories/temporary-files-and-directories.go b/examples/temporary-files-and-directories/temporary-files-and-directories.go new file mode 100644 index 0000000..abed14e --- /dev/null +++ b/examples/temporary-files-and-directories/temporary-files-and-directories.go @@ -0,0 +1,65 @@ +// Throughout program execution, we often want to create +// data that isn't needed after the program exits. +// *Temporary files and directories* are useful for this +// purpose since they don't pollute the file system over +// time. + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + + // The easiest way to create a temporary file is by + // calling `ioutil.TempFile`. It creates a file *and* + // opens it for reading and writing. We provide `""` + // as the first argument, so `ioutil.TempFile` will + // create the file in the default location for our OS. + f, err := ioutil.TempFile("", "sample") + check(err) + + // Display the name of the temporary file. On + // Unix-based OSes the directory will likely be `/tmp`. + // The file name starts with the prefix given as the + // second argument to `ioutil.TempFile` and the rest + // is chosen automatically to ensure that concurrent + // calls will always create different file names. + fmt.Println("Temp file name:", f.Name()) + + // Clean up the file after we're done. The OS is + // likely to clean up temporary files by itself after + // some time, but it's good practice to do this + // explicitly. + defer os.Remove(f.Name()) + + // We can write some data to the file. + _, err = f.Write([]byte{1, 2, 3, 4}) + check(err) + + // If we intend to write many temporary files, we may + // prefer to create a temporary *directory*. + // `ioutil.TempDir`'s arguments are the same as + // `TempFile`'s, but it returns a directory *name* + // rather than an open file. + dname, err := ioutil.TempDir("", "sampledir") + fmt.Println("Temp dir name:", dname) + + defer os.RemoveAll(dname) + + // Now we can synthesize temporary file names by + // prefixing them with our temporary directory. + fname := filepath.Join(dname, "file1") + err = ioutil.WriteFile(fname, []byte{1, 2}, 0666) + check(err) +} diff --git a/examples/temporary-files-and-directories/temporary-files-and-directories.hash b/examples/temporary-files-and-directories/temporary-files-and-directories.hash new file mode 100644 index 0000000..f523002 --- /dev/null +++ b/examples/temporary-files-and-directories/temporary-files-and-directories.hash @@ -0,0 +1,2 @@ +5f7d0c43988d7dce235adb06ec02f4d2026b7f83 +pxE20wGTFjv diff --git a/examples/temporary-files-and-directories/temporary-files-and-directories.sh b/examples/temporary-files-and-directories/temporary-files-and-directories.sh new file mode 100644 index 0000000..1854a19 --- /dev/null +++ b/examples/temporary-files-and-directories/temporary-files-and-directories.sh @@ -0,0 +1,4 @@ +# The exact names printed out will likely be different. +$ go run temporary-files-and-directories.go +Temp file name: /tmp/sample610887201 +Temp dir name: /tmp/sampledir898854668 diff --git a/public/index.html b/public/index.html index b11b9ef..e3cb506 100644 --- a/public/index.html +++ b/public/index.html @@ -139,6 +139,8 @@
  • Writing Files
  • +
  • Temporary Files and Directories
  • +
  • Line Filters
  • File Paths
  • diff --git a/public/temporary-files-and-directories b/public/temporary-files-and-directories new file mode 100644 index 0000000..e8336ca --- /dev/null +++ b/public/temporary-files-and-directories @@ -0,0 +1,232 @@ + + + + + Go by Example: Temporary Files and Directories + + + +
    +

    Go by Example: Temporary Files and Directories

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Throughout program execution, we often want to create +data that isn’t needed after the program exits. +Temporary files and directories are useful for this +purpose since they don’t pollute the file system over +time.

    + +
    + + +
    + + + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "fmt"
    +    "io/ioutil"
    +    "os"
    +    "path/filepath"
    +)
    +
    + +
    + + + +
    func check(e error) {
    +    if e != nil {
    +        panic(e)
    +    }
    +}
    +
    + +
    + + + +
    func main() {
    +
    + +
    +

    The easiest way to create a temporary file is by +calling ioutil.TempFile. It creates a file and +opens it for reading and writing. We provide "" +as the first argument, so ioutil.TempFile will +create the file in the default location for our OS.

    + +
    + +
        f, err := ioutil.TempFile("", "sample")
    +    check(err)
    +
    + +
    +

    Display the name of the temporary file. On +Unix-based OSes the directory will likely be /tmp. +The file name starts with the prefix given as the +second argument to ioutil.TempFile and the rest +is chosen automatically to ensure that concurrent +calls will always create different file names.

    + +
    + +
        fmt.Println("Temp file name:", f.Name())
    +
    + +
    +

    Clean up the file after we’re done. The OS is +likely to clean up temporary files by itself after +some time, but it’s good practice to do this +explicitly.

    + +
    + +
        defer os.Remove(f.Name())
    +
    + +
    +

    We can write some data to the file.

    + +
    + +
        _, err = f.Write([]byte{1, 2, 3, 4})
    +    check(err)
    +
    + +
    +

    If we intend to write many temporary files, we may +prefer to create a temporary directory. +ioutil.TempDir’s arguments are the same as +TempFile’s, but it returns a directory name +rather than an open file.

    + +
    + +
        dname, err := ioutil.TempDir("", "sampledir")
    +    fmt.Println("Temp dir name:", dname)
    +
    + +
    + + + +
        defer os.RemoveAll(dname)
    +
    + +
    +

    Now we can synthesize temporary file names by +prefixing them with our temporary directory.

    + +
    + +
        fname := filepath.Join(dname, "file1")
    +    err = ioutil.WriteFile(fname, []byte{1, 2}, 0666)
    +    check(err)
    +}
    +
    + +
    + + + + + + + + +
    +

    The exact names printed out will likely be different.

    + +
    + +
    $ go run temporary-files-and-directories.go
    +Temp file name: /tmp/sample610887201
    +Temp dir name: /tmp/sampledir898854668
    +
    + +
    + + +

    + Next example: Line Filters. +

    + + +
    + + diff --git a/public/writing-files b/public/writing-files index ca974bd..98401c2 100644 --- a/public/writing-files +++ b/public/writing-files @@ -266,7 +266,7 @@ we’ve just seen to the stdin and stdout streams.

    - Next example: Line Filters. + Next example: Temporary Files and Directories.

    - Next example: Command-Line Arguments. + Next example: Temporary Files and Directories.

  • Writing Files
  • -
  • Temporary Files and Directories
  • -
  • Line Filters
  • File Paths
  • Directories
  • +
  • Temporary Files and Directories
  • +
  • Command-Line Arguments
  • Command-Line Flags
  • diff --git a/public/temporary-files-and-directories b/public/temporary-files-and-directories index e8336ca..3b3bfc1 100644 --- a/public/temporary-files-and-directories +++ b/public/temporary-files-and-directories @@ -221,7 +221,7 @@ prefixing them with our temporary directory.

    - Next example: Line Filters. + Next example: Command-Line Arguments.

    - Next example: Temporary Files and Directories. + Next example: Line Filters.

    -

    The exact names printed out will likely be different.

    - + From 3d55c3ae33390451d13e26a06f7487d03355155c Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Sun, 30 Jun 2019 14:11:14 -0700 Subject: [PATCH 121/133] Tweak comment --- examples/defer/defer.go | 3 ++- examples/defer/defer.hash | 4 ++-- public/defer | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 0941d10..724e698 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -41,7 +41,8 @@ func writeFile(f *os.File) { func closeFile(f *os.File) { fmt.Println("closing") err := f.Close() - // It is important to check for errors when closing a file, even in a deferred function. + // It's important to check for errors when closing a + // file, even in a deferred function. if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) diff --git a/examples/defer/defer.hash b/examples/defer/defer.hash index 5e437d4..78d3e35 100644 --- a/examples/defer/defer.hash +++ b/examples/defer/defer.hash @@ -1,2 +1,2 @@ -4e2229c593e102d4efd101a7e9aa21f3345e90d1 -S2RuPTkABip +fadbe9c05bb42db672316ba19adf3c2189c7b3f5 +OrCaBiCrTKq diff --git a/public/defer b/public/defer index 8f0b130..445d689 100644 --- a/public/defer +++ b/public/defer @@ -30,7 +30,7 @@ purposes of cleanup. defer is often used where e.g. - +
    package main
    @@ -134,7 +134,8 @@ of the enclosing function (main), after
             
             
               
    -            

    It is important to check for errors when closing a file, even in a deferred function.

    +

    It’s important to check for errors when closing a +file, even in a deferred function.

    From fb2c28e58a562d847d24c97abbdabbf5aef8de24 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 1 Jul 2019 06:44:09 -0700 Subject: [PATCH 122/133] When testing on Travis, verify that tools/build was run This is done by routing the generation of HTML into a temporary directory, and checking its diff agains the existing public/ when running tests. Fixes #237 --- .travis.yml | 1 + tools/build | 26 ++++++++++++++++++++++++-- tools/generate | 2 +- tools/generate.go | 11 ++++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 54d1654..25b9ffc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,3 +16,4 @@ script: env: - VERBOSE=1 + - TESTING=1 diff --git a/tools/build b/tools/build index f06beae..4f66902 100755 --- a/tools/build +++ b/tools/build @@ -15,5 +15,27 @@ tools/format verbose && echo "Measuring line lengths..." tools/measure -verbose && echo "Generating HTML..." -tools/generate +# SITE_DIR is the final location where we want generated content to be +SITE_DIR="public" + +# GENERATE_DIR is where the content will be generated initially +GENERATE_DIR="$(mktemp -d)" + +function cleanup() { + rm -rf "$GENERATE_DIR" +} +trap cleanup EXIT + +verbose && echo "Generating HTML to $GENERATE_DIR..." +tools/generate $GENERATE_DIR + +# In TESTING mode, make sure that the generated content is identical to +# what's already in SITE_DIR. If a difference is found, this script exits +# with an error. +if [[ ! -z "$TESTING" ]]; then + echo "Comparing $GENERATE_DIR with $SITE_DIR..." + diff -r "$GENERATE_DIR" "$SITE_DIR" +fi + +verbose && echo "Copying $GENERATE_DIR to $SITE_DIR" +cp -rf "${GENERATE_DIR}/." "$SITE_DIR" diff --git a/tools/generate b/tools/generate index 83ed0e7..af897e5 100755 --- a/tools/generate +++ b/tools/generate @@ -1,3 +1,3 @@ #!/bin/bash -exec go run tools/generate.go +exec go run tools/generate.go $@ diff --git a/tools/generate.go b/tools/generate.go index 97d8ab5..a332128 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -15,8 +15,12 @@ import ( "github.com/russross/blackfriday" ) -var cacheDir = "/tmp/gobyexample-cache" +// siteDir is the target directory into which the HTML gets generated. Its +// default is set here but can be changed by an argument passed into the +// program. var siteDir = "./public" + +var cacheDir = "/tmp/gobyexample-cache" var pygmentizeBin = "./vendor/pygments/pygmentize" func verbose() bool { @@ -301,6 +305,11 @@ func renderExamples(examples []*Example) { } func main() { + if len(os.Args) > 1 { + siteDir = os.Args[1] + } + ensureDir(siteDir) + copyFile("templates/site.css", siteDir+"/site.css") copyFile("templates/favicon.ico", siteDir+"/favicon.ico") copyFile("templates/404.html", siteDir+"/404.html") From fe1443c7ed2d1ea56bf19ee45a28ffd8d9952ae4 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 1 Jul 2019 06:51:20 -0700 Subject: [PATCH 123/133] Combine testing environments on travis --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25b9ffc..96a94a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,5 +15,4 @@ script: - tools/build env: - - VERBOSE=1 - - TESTING=1 + - VERBOSE=1 TESTING=1 From c127e2898e6f63bdf0733b8c6b636ad9bb32b51c Mon Sep 17 00:00:00 2001 From: PeterBocan Date: Mon, 1 Jul 2019 16:45:01 +0200 Subject: [PATCH 124/133] Added a constructor to structs --- examples/structs/structs.go | 13 ++++++++++ examples/structs/structs.hash | 4 +-- examples/structs/structs.sh | 1 + public/structs | 47 +++++++++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/examples/structs/structs.go b/examples/structs/structs.go index 6cf5629..21584a2 100644 --- a/examples/structs/structs.go +++ b/examples/structs/structs.go @@ -12,6 +12,16 @@ type person struct { age int } +// A de facto constructor of type `person`. +func NewPerson(name string) *person { + + // You can safely return a pointer to local variable + // as a local variable will survive the scope of the function. + p := person{name: name} + p.age = 42 + return &p +} + func main() { // This syntax creates a new struct. @@ -38,4 +48,7 @@ func main() { // Structs are mutable. sp.age = 51 fmt.Println(sp.age) + + // Call our constructor + fmt.Println(NewPerson("Jon")) } diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index 2c0e37f..a1194e9 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ -49cad39331ee5e9fb8d8dad99d3aff7f18a4e6d0 -XMZpGsF4sWM +71e8ecdcf8c8fbddbb250ada5bbe8659b68d5229 +nHvnHAGTYHq diff --git a/examples/structs/structs.sh b/examples/structs/structs.sh index 6d82fa0..f0d6025 100644 --- a/examples/structs/structs.sh +++ b/examples/structs/structs.sh @@ -6,3 +6,4 @@ $ go run structs.go Sean 50 51 +&{Jon 42} \ No newline at end of file diff --git a/public/structs b/public/structs index 31c03d0..22fd85f 100644 --- a/public/structs +++ b/public/structs @@ -29,7 +29,7 @@ records.

    - +
    package main
    @@ -66,6 +66,36 @@ records.

    + + +

    A de facto constructor of type person.

    + + + + +
    func NewPerson(name string) *person {
    +
    + + + + + + +

    You can safely return a pointer to local variable +as a local variable will survive the scope of the function.

    + + + + +
        p := person{name: name}
    +    p.age = 42
    +    return &p
    +}
    +
    + + + + @@ -164,10 +194,23 @@ pointers are automatically dereferenced.

    Structs are mutable.

    - +
        sp.age = 51
         fmt.Println(sp.age)
    +
    + + + + + + +

    Call our constructor

    + + + + +
        fmt.Println(NewPerson("Jon"))
     }
     
    From 615d5e2eb460851838448c5b1bd7a768b79c9ab9 Mon Sep 17 00:00:00 2001 From: PeterBocan Date: Tue, 2 Jul 2019 15:46:54 +0200 Subject: [PATCH 125/133] Struct allocation fixes. --- examples/structs/structs.go | 8 ++++---- examples/structs/structs.hash | 4 ++-- public/structs | 24 ++++++++++++++++++------ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/examples/structs/structs.go b/examples/structs/structs.go index 21584a2..e2546fe 100644 --- a/examples/structs/structs.go +++ b/examples/structs/structs.go @@ -12,9 +12,8 @@ type person struct { age int } -// A de facto constructor of type `person`. +// NewPerson constructs a new person struct with the given name func NewPerson(name string) *person { - // You can safely return a pointer to local variable // as a local variable will survive the scope of the function. p := person{name: name} @@ -36,6 +35,9 @@ func main() { // An `&` prefix yields a pointer to the struct. fmt.Println(&person{name: "Ann", age: 40}) + // It's idiomatic to encapsulate new struct creation in constructor functions + fmt.Println(NewPerson("Jon")) + // Access struct fields with a dot. s := person{name: "Sean", age: 50} fmt.Println(s.name) @@ -49,6 +51,4 @@ func main() { sp.age = 51 fmt.Println(sp.age) - // Call our constructor - fmt.Println(NewPerson("Jon")) } diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index a1194e9..50e4d67 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ -71e8ecdcf8c8fbddbb250ada5bbe8659b68d5229 -nHvnHAGTYHq +cd504951e9f8504c159a66714b04bfda0629e58c +ezfE4eojTS7 diff --git a/public/structs b/public/structs index 22fd85f..0ea36aa 100644 --- a/public/structs +++ b/public/structs @@ -29,7 +29,7 @@ records.

    - +
    package main
    @@ -68,7 +68,7 @@ records.

    -

    A de facto constructor of type person.

    +

    NewPerson constructs a new person struct with the given name

    @@ -160,6 +160,19 @@ as a local variable will survive the scope of the function.

    + + +

    It’s idiomatic to encapsulate new struct creation in constructor functions

    + + + + +
        fmt.Println(NewPerson("Jon"))
    +
    + + + +

    Access struct fields with a dot.

    @@ -205,13 +218,11 @@ pointers are automatically dereferenced.

    -

    Call our constructor

    - + -
        fmt.Println(NewPerson("Jon"))
    -}
    +            
    }
     
    @@ -235,6 +246,7 @@ pointers are automatically dereferenced.

    Sean 50 51 +&{Jon 42}
    From c22f42f03cb1511c24e573374390ec261d6e2704 Mon Sep 17 00:00:00 2001 From: PeterBocan Date: Tue, 2 Jul 2019 16:30:42 +0200 Subject: [PATCH 126/133] Remove extra whitespace --- examples/structs/structs.go | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/structs/structs.go b/examples/structs/structs.go index e2546fe..384b57c 100644 --- a/examples/structs/structs.go +++ b/examples/structs/structs.go @@ -50,5 +50,4 @@ func main() { // Structs are mutable. sp.age = 51 fmt.Println(sp.age) - } From 1943fe080370d47556cfdc96f62c83a446f7e84d Mon Sep 17 00:00:00 2001 From: Shivam Rathore Date: Mon, 24 Jun 2019 00:41:52 +0530 Subject: [PATCH 127/133] arrow keys navigation added | fixes mmcgrana/gobyexample#222 --- .gitignore | 2 ++ public/arrays | 14 ++++++++++++++ public/atomic-counters | 14 ++++++++++++++ public/base64-encoding | 14 ++++++++++++++ public/channel-buffering | 14 ++++++++++++++ public/channel-directions | 14 ++++++++++++++ public/channel-synchronization | 14 ++++++++++++++ public/channels | 14 ++++++++++++++ public/closing-channels | 14 ++++++++++++++ public/closures | 14 ++++++++++++++ public/collection-functions | 14 ++++++++++++++ public/command-line-arguments | 14 ++++++++++++++ public/command-line-flags | 14 ++++++++++++++ public/command-line-subcommands | 14 ++++++++++++++ public/constants | 14 ++++++++++++++ public/defer | 14 ++++++++++++++ public/environment-variables | 14 ++++++++++++++ public/epoch | 14 ++++++++++++++ public/errors | 14 ++++++++++++++ public/execing-processes | 14 ++++++++++++++ public/exit | 10 ++++++++++ public/file-paths | 14 ++++++++++++++ public/for | 14 ++++++++++++++ public/functions | 14 ++++++++++++++ public/goroutines | 14 ++++++++++++++ public/hello-world | 10 ++++++++++ public/http-clients | 14 ++++++++++++++ public/http-servers | 14 ++++++++++++++ public/if-else | 14 ++++++++++++++ public/interfaces | 14 ++++++++++++++ public/json | 14 ++++++++++++++ public/line-filters | 14 ++++++++++++++ public/maps | 14 ++++++++++++++ public/methods | 14 ++++++++++++++ public/multiple-return-values | 14 ++++++++++++++ public/mutexes | 14 ++++++++++++++ public/non-blocking-channel-operations | 14 ++++++++++++++ public/number-parsing | 14 ++++++++++++++ public/panic | 14 ++++++++++++++ public/pointers | 14 ++++++++++++++ public/random-numbers | 14 ++++++++++++++ public/range | 14 ++++++++++++++ public/range-over-channels | 14 ++++++++++++++ public/rate-limiting | 14 ++++++++++++++ public/reading-files | 14 ++++++++++++++ public/recursion | 14 ++++++++++++++ public/regular-expressions | 14 ++++++++++++++ public/select | 14 ++++++++++++++ public/sha1-hashes | 14 ++++++++++++++ public/signals | 14 ++++++++++++++ public/slices | 14 ++++++++++++++ public/sorting | 14 ++++++++++++++ public/sorting-by-functions | 14 ++++++++++++++ public/spawning-processes | 14 ++++++++++++++ public/stateful-goroutines | 14 ++++++++++++++ public/string-formatting | 14 ++++++++++++++ public/string-functions | 14 ++++++++++++++ public/structs | 14 ++++++++++++++ public/switch | 14 ++++++++++++++ public/tickers | 14 ++++++++++++++ public/time | 14 ++++++++++++++ public/time-formatting-parsing | 14 ++++++++++++++ public/timeouts | 14 ++++++++++++++ public/timers | 14 ++++++++++++++ public/url-parsing | 14 ++++++++++++++ public/values | 14 ++++++++++++++ public/variables | 14 ++++++++++++++ public/variadic-functions | 14 ++++++++++++++ public/waitgroups | 14 ++++++++++++++ public/worker-pools | 14 ++++++++++++++ public/writing-files | 14 ++++++++++++++ templates/example.tmpl | 14 ++++++++++++++ tools/generate.go | 4 ++++ 73 files changed, 992 insertions(+) diff --git a/.gitignore b/.gitignore index 0d20b64..acb800c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.pyc +.idea +.vscode diff --git a/public/arrays b/public/arrays index 9f12e9d..b9f36ce 100644 --- a/public/arrays +++ b/public/arrays @@ -5,6 +5,20 @@ Go by Example: Arrays +

    Go by Example: Arrays

    diff --git a/public/atomic-counters b/public/atomic-counters index 9ba1895..c4df533 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -5,6 +5,20 @@ Go by Example: Atomic Counters +

    Go by Example: Atomic Counters

    diff --git a/public/base64-encoding b/public/base64-encoding index 2c1da0d..fdbaaed 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -5,6 +5,20 @@ Go by Example: Base64 Encoding +

    Go by Example: Base64 Encoding

    diff --git a/public/channel-buffering b/public/channel-buffering index 2734939..a11749b 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -5,6 +5,20 @@ Go by Example: Channel Buffering +

    Go by Example: Channel Buffering

    diff --git a/public/channel-directions b/public/channel-directions index 02c7c0a..2c95a14 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -5,6 +5,20 @@ Go by Example: Channel Directions +

    Go by Example: Channel Directions

    diff --git a/public/channel-synchronization b/public/channel-synchronization index 00076f9..595487d 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -5,6 +5,20 @@ Go by Example: Channel Synchronization +

    Go by Example: Channel Synchronization

    diff --git a/public/channels b/public/channels index 94b14d7..25995b6 100644 --- a/public/channels +++ b/public/channels @@ -5,6 +5,20 @@ Go by Example: Channels +

    Go by Example: Channels

    diff --git a/public/closing-channels b/public/closing-channels index d873cd8..ff67861 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -5,6 +5,20 @@ Go by Example: Closing Channels +

    Go by Example: Closing Channels

    diff --git a/public/closures b/public/closures index d85af28..0bb3852 100644 --- a/public/closures +++ b/public/closures @@ -5,6 +5,20 @@ Go by Example: Closures +

    Go by Example: Closures

    diff --git a/public/collection-functions b/public/collection-functions index 07e970b..fce4ddd 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -5,6 +5,20 @@ Go by Example: Collection Functions +

    Go by Example: Collection Functions

    diff --git a/public/command-line-arguments b/public/command-line-arguments index b649bd2..a585d22 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -5,6 +5,20 @@ Go by Example: Command-Line Arguments +

    Go by Example: Command-Line Arguments

    diff --git a/public/command-line-flags b/public/command-line-flags index 43ec18f..32c7abe 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -5,6 +5,20 @@ Go by Example: Command-Line Flags +

    Go by Example: Command-Line Flags

    diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 39b385b..333e048 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -5,6 +5,20 @@ Go by Example: Command-Line Subcommands +

    Go by Example: Command-Line Subcommands

    diff --git a/public/constants b/public/constants index c564424..0609217 100644 --- a/public/constants +++ b/public/constants @@ -5,6 +5,20 @@ Go by Example: Constants +

    Go by Example: Constants

    diff --git a/public/defer b/public/defer index 445d689..42299e5 100644 --- a/public/defer +++ b/public/defer @@ -5,6 +5,20 @@ Go by Example: Defer +

    Go by Example: Defer

    diff --git a/public/environment-variables b/public/environment-variables index 3d2e54c..56a1cc3 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -5,6 +5,20 @@ Go by Example: Environment Variables +

    Go by Example: Environment Variables

    diff --git a/public/epoch b/public/epoch index 46d62e7..60ecde3 100644 --- a/public/epoch +++ b/public/epoch @@ -5,6 +5,20 @@ Go by Example: Epoch +

    Go by Example: Epoch

    diff --git a/public/errors b/public/errors index 489f119..a473c1b 100644 --- a/public/errors +++ b/public/errors @@ -5,6 +5,20 @@ Go by Example: Errors +

    Go by Example: Errors

    diff --git a/public/execing-processes b/public/execing-processes index 85b155d..2d26b21 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -5,6 +5,20 @@ Go by Example: Exec'ing Processes +

    Go by Example: Exec'ing Processes

    diff --git a/public/exit b/public/exit index 4c6975d..7b32b81 100644 --- a/public/exit +++ b/public/exit @@ -5,6 +5,16 @@ Go by Example: Exit +

    Go by Example: Exit

    diff --git a/public/file-paths b/public/file-paths index f7b24a1..9dae4c6 100644 --- a/public/file-paths +++ b/public/file-paths @@ -5,6 +5,20 @@ Go by Example: File Paths +

    Go by Example: File Paths

    diff --git a/public/for b/public/for index 314f139..47f39c9 100644 --- a/public/for +++ b/public/for @@ -5,6 +5,20 @@ Go by Example: For +

    Go by Example: For

    diff --git a/public/functions b/public/functions index 7c89d83..8eeca6c 100644 --- a/public/functions +++ b/public/functions @@ -5,6 +5,20 @@ Go by Example: Functions +

    Go by Example: Functions

    diff --git a/public/goroutines b/public/goroutines index 40ba434..06f5e9b 100644 --- a/public/goroutines +++ b/public/goroutines @@ -5,6 +5,20 @@ Go by Example: Goroutines +

    Go by Example: Goroutines

    diff --git a/public/hello-world b/public/hello-world index d8b1872..f33d703 100644 --- a/public/hello-world +++ b/public/hello-world @@ -5,6 +5,16 @@ Go by Example: Hello World +

    Go by Example: Hello World

    diff --git a/public/http-clients b/public/http-clients index 5d5bf04..d1a9f50 100644 --- a/public/http-clients +++ b/public/http-clients @@ -5,6 +5,20 @@ Go by Example: HTTP Clients +

    Go by Example: HTTP Clients

    diff --git a/public/http-servers b/public/http-servers index 2dedf1a..68431cf 100644 --- a/public/http-servers +++ b/public/http-servers @@ -5,6 +5,20 @@ Go by Example: HTTP Servers +

    Go by Example: HTTP Servers

    diff --git a/public/if-else b/public/if-else index 2ed0680..dcc5aec 100644 --- a/public/if-else +++ b/public/if-else @@ -5,6 +5,20 @@ Go by Example: If/Else +

    Go by Example: If/Else

    diff --git a/public/interfaces b/public/interfaces index 277c8f8..909465b 100644 --- a/public/interfaces +++ b/public/interfaces @@ -5,6 +5,20 @@ Go by Example: Interfaces +

    Go by Example: Interfaces

    diff --git a/public/json b/public/json index 54979d2..f6a4146 100644 --- a/public/json +++ b/public/json @@ -5,6 +5,20 @@ Go by Example: JSON +

    Go by Example: JSON

    diff --git a/public/line-filters b/public/line-filters index d264214..d673b55 100644 --- a/public/line-filters +++ b/public/line-filters @@ -5,6 +5,20 @@ Go by Example: Line Filters +

    Go by Example: Line Filters

    diff --git a/public/maps b/public/maps index bf31208..bfaefce 100644 --- a/public/maps +++ b/public/maps @@ -5,6 +5,20 @@ Go by Example: Maps +

    Go by Example: Maps

    diff --git a/public/methods b/public/methods index c1ae6d0..cf9f7f7 100644 --- a/public/methods +++ b/public/methods @@ -5,6 +5,20 @@ Go by Example: Methods +

    Go by Example: Methods

    diff --git a/public/multiple-return-values b/public/multiple-return-values index 5392875..1bd021d 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -5,6 +5,20 @@ Go by Example: Multiple Return Values +

    Go by Example: Multiple Return Values

    diff --git a/public/mutexes b/public/mutexes index efc2253..f3c8476 100644 --- a/public/mutexes +++ b/public/mutexes @@ -5,6 +5,20 @@ Go by Example: Mutexes +

    Go by Example: Mutexes

    diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index ada60a3..64c17ca 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -5,6 +5,20 @@ Go by Example: Non-Blocking Channel Operations +

    Go by Example: Non-Blocking Channel Operations

    diff --git a/public/number-parsing b/public/number-parsing index 35e768e..e8c4f81 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -5,6 +5,20 @@ Go by Example: Number Parsing +

    Go by Example: Number Parsing

    diff --git a/public/panic b/public/panic index 59198af..4b08f98 100644 --- a/public/panic +++ b/public/panic @@ -5,6 +5,20 @@ Go by Example: Panic +

    Go by Example: Panic

    diff --git a/public/pointers b/public/pointers index 16687f5..2caca80 100644 --- a/public/pointers +++ b/public/pointers @@ -5,6 +5,20 @@ Go by Example: Pointers +

    Go by Example: Pointers

    diff --git a/public/random-numbers b/public/random-numbers index 5de950f..29f47e9 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -5,6 +5,20 @@ Go by Example: Random Numbers +

    Go by Example: Random Numbers

    diff --git a/public/range b/public/range index e9aa99e..688bbdb 100644 --- a/public/range +++ b/public/range @@ -5,6 +5,20 @@ Go by Example: Range +

    Go by Example: Range

    diff --git a/public/range-over-channels b/public/range-over-channels index a3ba422..5b6e160 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -5,6 +5,20 @@ Go by Example: Range over Channels +

    Go by Example: Range over Channels

    diff --git a/public/rate-limiting b/public/rate-limiting index 07dc185..30b739f 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -5,6 +5,20 @@ Go by Example: Rate Limiting +

    Go by Example: Rate Limiting

    diff --git a/public/reading-files b/public/reading-files index d51206c..af5009b 100644 --- a/public/reading-files +++ b/public/reading-files @@ -5,6 +5,20 @@ Go by Example: Reading Files +

    Go by Example: Reading Files

    diff --git a/public/recursion b/public/recursion index bedbf2f..db074e2 100644 --- a/public/recursion +++ b/public/recursion @@ -5,6 +5,20 @@ Go by Example: Recursion +

    Go by Example: Recursion

    diff --git a/public/regular-expressions b/public/regular-expressions index 8db2fbd..237af8e 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -5,6 +5,20 @@ Go by Example: Regular Expressions +

    Go by Example: Regular Expressions

    diff --git a/public/select b/public/select index d6733a1..af53205 100644 --- a/public/select +++ b/public/select @@ -5,6 +5,20 @@ Go by Example: Select +

    Go by Example: Select

    diff --git a/public/sha1-hashes b/public/sha1-hashes index c28cf1d..f3e4155 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -5,6 +5,20 @@ Go by Example: SHA1 Hashes +

    Go by Example: SHA1 Hashes

    diff --git a/public/signals b/public/signals index 50f0ec1..9a1d9f5 100644 --- a/public/signals +++ b/public/signals @@ -5,6 +5,20 @@ Go by Example: Signals +

    Go by Example: Signals

    diff --git a/public/slices b/public/slices index fba69c9..4e30c3f 100644 --- a/public/slices +++ b/public/slices @@ -5,6 +5,20 @@ Go by Example: Slices +

    Go by Example: Slices

    diff --git a/public/sorting b/public/sorting index 73f22b1..219bc63 100644 --- a/public/sorting +++ b/public/sorting @@ -5,6 +5,20 @@ Go by Example: Sorting +

    Go by Example: Sorting

    diff --git a/public/sorting-by-functions b/public/sorting-by-functions index 92c0f41..a2efcc8 100644 --- a/public/sorting-by-functions +++ b/public/sorting-by-functions @@ -5,6 +5,20 @@ Go by Example: Sorting by Functions +

    Go by Example: Sorting by Functions

    diff --git a/public/spawning-processes b/public/spawning-processes index c6ba21e..d8396b9 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -5,6 +5,20 @@ Go by Example: Spawning Processes +

    Go by Example: Spawning Processes

    diff --git a/public/stateful-goroutines b/public/stateful-goroutines index a14245a..da6329c 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -5,6 +5,20 @@ Go by Example: Stateful Goroutines +

    Go by Example: Stateful Goroutines

    diff --git a/public/string-formatting b/public/string-formatting index c3118b0..c0652e6 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -5,6 +5,20 @@ Go by Example: String Formatting +

    Go by Example: String Formatting

    diff --git a/public/string-functions b/public/string-functions index 73b6019..4882c60 100644 --- a/public/string-functions +++ b/public/string-functions @@ -5,6 +5,20 @@ Go by Example: String Functions +

    Go by Example: String Functions

    diff --git a/public/structs b/public/structs index 31c03d0..ac4a3cb 100644 --- a/public/structs +++ b/public/structs @@ -5,6 +5,20 @@ Go by Example: Structs +

    Go by Example: Structs

    diff --git a/public/switch b/public/switch index c739ea3..fae75e8 100644 --- a/public/switch +++ b/public/switch @@ -5,6 +5,20 @@ Go by Example: Switch +

    Go by Example: Switch

    diff --git a/public/tickers b/public/tickers index 64f1044..286dfff 100644 --- a/public/tickers +++ b/public/tickers @@ -5,6 +5,20 @@ Go by Example: Tickers +

    Go by Example: Tickers

    diff --git a/public/time b/public/time index 443f568..90fbf1f 100644 --- a/public/time +++ b/public/time @@ -5,6 +5,20 @@ Go by Example: Time +

    Go by Example: Time

    diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index f16fbc9..602c729 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -5,6 +5,20 @@ Go by Example: Time Formatting / Parsing +

    Go by Example: Time Formatting / Parsing

    diff --git a/public/timeouts b/public/timeouts index 449446a..35315f4 100644 --- a/public/timeouts +++ b/public/timeouts @@ -5,6 +5,20 @@ Go by Example: Timeouts +

    Go by Example: Timeouts

    diff --git a/public/timers b/public/timers index 7004b5f..3ba794e 100644 --- a/public/timers +++ b/public/timers @@ -5,6 +5,20 @@ Go by Example: Timers +

    Go by Example: Timers

    diff --git a/public/url-parsing b/public/url-parsing index 8b17377..71874e9 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -5,6 +5,20 @@ Go by Example: URL Parsing +

    Go by Example: URL Parsing

    diff --git a/public/values b/public/values index 38966a3..648aed8 100644 --- a/public/values +++ b/public/values @@ -5,6 +5,20 @@ Go by Example: Values +

    Go by Example: Values

    diff --git a/public/variables b/public/variables index 9c1156a..0779d1c 100644 --- a/public/variables +++ b/public/variables @@ -5,6 +5,20 @@ Go by Example: Variables +

    Go by Example: Variables

    diff --git a/public/variadic-functions b/public/variadic-functions index 75ce887..f0355c4 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -5,6 +5,20 @@ Go by Example: Variadic Functions +

    Go by Example: Variadic Functions

    diff --git a/public/waitgroups b/public/waitgroups index 45792a8..5962f99 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -5,6 +5,20 @@ Go by Example: WaitGroups +

    Go by Example: WaitGroups

    diff --git a/public/worker-pools b/public/worker-pools index e1170bf..ddabd53 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -5,6 +5,20 @@ Go by Example: Worker Pools +

    Go by Example: Worker Pools

    diff --git a/public/writing-files b/public/writing-files index ca974bd..f4dd30d 100644 --- a/public/writing-files +++ b/public/writing-files @@ -5,6 +5,20 @@ Go by Example: Writing Files +

    Go by Example: Writing Files

    diff --git a/templates/example.tmpl b/templates/example.tmpl index c9cfb7d..8d6f1aa 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -5,6 +5,20 @@ Go by Example: {{.Name}} +

    Go by Example: {{.Name}}

    diff --git a/tools/generate.go b/tools/generate.go index a332128..33acb60 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -138,6 +138,7 @@ type Example struct { ID, Name string GoCode, GoCodeHash, URLHash string Segs [][]*Seg + PrevExample *Example NextExample *Example } @@ -270,6 +271,9 @@ func parseExamples() []*Example { examples = append(examples, &example) } for i, example := range examples { + if i > 0 { + example.PrevExample = examples[i-1] + } if i < (len(examples) - 1) { example.NextExample = examples[i+1] } From 53a1b7a10762a3a7b8d5ec5e46b0ca37e95e724e Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Mon, 8 Jul 2019 19:04:48 -0700 Subject: [PATCH 128/133] Regenerate --- public/command-line-arguments | 2 +- public/directories | 14 ++++++++++++++ public/file-paths | 2 +- public/temporary-files-and-directories | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/public/command-line-arguments b/public/command-line-arguments index a585d22..fc80282 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -9,7 +9,7 @@ onkeydown = (e) => { if (e.key == "ArrowLeft") { - window.location.href = 'file-paths'; + window.location.href = 'temporary-files-and-directories'; } diff --git a/public/directories b/public/directories index 25fc6d4..beb7a7e 100644 --- a/public/directories +++ b/public/directories @@ -5,6 +5,20 @@ Go by Example: Directories +

    Go by Example: Directories

    diff --git a/public/file-paths b/public/file-paths index 9dae4c6..44a1faf 100644 --- a/public/file-paths +++ b/public/file-paths @@ -14,7 +14,7 @@ if (e.key == "ArrowRight") { - window.location.href = 'command-line-arguments'; + window.location.href = 'directories'; } } diff --git a/public/temporary-files-and-directories b/public/temporary-files-and-directories index ddc5e39..ce479ca 100644 --- a/public/temporary-files-and-directories +++ b/public/temporary-files-and-directories @@ -5,6 +5,20 @@ Go by Example: Temporary Files and Directories +

    Go by Example: Temporary Files and Directories

    From 2862b97d01f4f2dc8294a758998f917f0b521e6e Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 12 Jul 2019 06:14:47 -0700 Subject: [PATCH 129/133] Update CONTRIBUTING.md --- CONTRIBUTING.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2366de8..40439fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,9 +2,11 @@ Thanks for your interest in contributing to Go by Example! -* If you see a typo or would like to suggest another small change, editing the - .go or .sh source file should be sufficient for the PR. I can rebuild the - HTML when I review the change. +* When sending a PR that affects the displayed contents of the site, run + `tools/build` locally and include the generated HTML in the PR. If you + only want to submit a simple typo suggestion (for example, through the + Github website), feel free to send a PR anyway - we'll regenerate the + HTML and merge with your commit. * We're open to adding more examples to the site. They should be on things used by many programmers and only require the standard library. If you're From 482bd86963754fe2bae6a005508153573388487f Mon Sep 17 00:00:00 2001 From: Julian Zucker Date: Wed, 24 Jul 2019 18:27:04 -0600 Subject: [PATCH 130/133] Fix typo in http servers example --- examples/http-servers/http-servers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/http-servers/http-servers.go b/examples/http-servers/http-servers.go index 72726b4..42a83b3 100644 --- a/examples/http-servers/http-servers.go +++ b/examples/http-servers/http-servers.go @@ -17,7 +17,7 @@ func hello(w http.ResponseWriter, req *http.Request) { // Functions serving as handlers take a // `http.ResponseWriter` and a `http.Request` as // arguments. The response writer is used to fill in the - // HTTP response. Here out simple response is just + // HTTP response. Here our simple response is just // "hello\n". fmt.Fprintf(w, "hello\n") } From 0198f3e8246fad0c4baff11cca7dc95d9c20ecc6 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 24 Aug 2019 06:28:01 -0700 Subject: [PATCH 131/133] Fix up language attribution for the Github UI Currently gobyexample is flagged as a CSS repository because of all the generated HTML. Following instructions at https://github.com/github/linguist#vendored-code to ask Github to ignore files that are not actual origin code. --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ac8f8c3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +public/* linguist-generated=true +vendor/* linguist-vendored=true + From 490c0e759913e5269a6515e128ced6b914d7dc4b Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Sun, 1 Sep 2019 15:11:49 -0700 Subject: [PATCH 132/133] Regenerate --- examples/http-servers/http-servers.hash | 4 ++-- public/http-servers | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/http-servers/http-servers.hash b/examples/http-servers/http-servers.hash index 6a0a323..a491ac1 100644 --- a/examples/http-servers/http-servers.hash +++ b/examples/http-servers/http-servers.hash @@ -1,2 +1,2 @@ -ac2909e69be30862bd9f18db954d9ee10f57ec6a -8GBAW6yNcbn +a4e8d30b7a6f3a6abd96b916d81ce5930bad94f9 +lNuS9ysZmxH diff --git a/public/http-servers b/public/http-servers index 68431cf..b9f74d6 100644 --- a/public/http-servers +++ b/public/http-servers @@ -32,7 +32,7 @@ - +
    package main
    @@ -78,7 +78,7 @@ on functions with the appropriate signature.

    Functions serving as handlers take a http.ResponseWriter and a http.Request as arguments. The response writer is used to fill in the -HTTP response. Here out simple response is just +HTTP response. Here our simple response is just “hello\n”.

    From 99505c39540b37c763ec1183e4878f98632293e8 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Sun, 1 Sep 2019 15:30:27 -0700 Subject: [PATCH 133/133] Regnerate --- examples/structs/structs.hash | 4 ++-- public/structs | 17 +++-------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index 50e4d67..15fcdc0 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ -cd504951e9f8504c159a66714b04bfda0629e58c -ezfE4eojTS7 +c5caaf1eefaf084d688afb70d2ee5884a4983182 +00Yiw6xuICq diff --git a/public/structs b/public/structs index 0ca3b3e..b550a3c 100644 --- a/public/structs +++ b/public/structs @@ -43,7 +43,7 @@ records.

    - +
    package main
    @@ -221,22 +221,11 @@ pointers are automatically dereferenced.

    Structs are mutable.

    - +
        sp.age = 51
         fmt.Println(sp.age)
    -
    - - - - - - - - - - -
    }
    +}