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 + diff --git a/.gitignore b/.gitignore index 0d20b64..acb800c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.pyc +.idea +.vscode diff --git a/.travis.yml b/.travis.yml index 54d1654..96a94a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ script: - tools/build env: - - VERBOSE=1 + - VERBOSE=1 TESTING=1 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 diff --git a/examples.txt b/examples.txt index 91a1fde..880802f 100644 --- a/examples.txt +++ b/examples.txt @@ -46,6 +46,7 @@ String Functions String Formatting Regular Expressions JSON +XML Time Epoch Time Formatting / Parsing @@ -58,6 +59,8 @@ Reading Files Writing Files Line Filters File Paths +Directories +Temporary Files and Directories Command-Line Arguments Command-Line Flags Command-Line Subcommands diff --git a/examples/atomic-counters/atomic-counters.go b/examples/atomic-counters/atomic-counters.go index 9df3276..046a347 100644 --- a/examples/atomic-counters/atomic-counters.go +++ b/examples/atomic-counters/atomic-counters.go @@ -7,9 +7,11 @@ package main -import "fmt" -import "time" -import "sync/atomic" +import ( + "fmt" + "sync" + "sync/atomic" +) func main() { @@ -17,33 +19,34 @@ func main() { // (always-positive) counter. var ops uint64 - // To simulate concurrent updates, we'll start 50 - // goroutines that each increment the counter about - // once a millisecond. + // A WaitGroup will help us wait for all goroutines + // to finish their work. + var wg sync.WaitGroup + + // We'll start 50 goroutines that each increment the + // counter exactly 1000 times. for i := 0; i < 50; i++ { + wg.Add(1) + go func() { - for { + for c := 0; c < 1000; c++ { // 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) } + wg.Done() }() } - // Wait a second to allow some ops to accumulate. - time.Sleep(time.Second) + // Wait until all the goroutines are done. + wg.Wait() - // 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) + // It's safe to access `ops` now because we know + // no other goroutine is writing to it. Reading + // atomics safely while they are being updated is + // also possible, using functions like + // `atomic.LoadUint64`. + fmt.Println("ops:", ops) } diff --git a/examples/atomic-counters/atomic-counters.hash b/examples/atomic-counters/atomic-counters.hash index c1b531a..989ed19 100644 --- a/examples/atomic-counters/atomic-counters.hash +++ b/examples/atomic-counters/atomic-counters.hash @@ -1,2 +1,2 @@ -a4190094ea0405b5f2733101beb97939a1d43aee -KDr9EMMPMgi +8ebec0be3b167021c96b8b497d0e8c0a2ea99385 +F2pJfduyQiA diff --git a/examples/atomic-counters/atomic-counters.sh b/examples/atomic-counters/atomic-counters.sh index e4523f9..1680a10 100644 --- a/examples/atomic-counters/atomic-counters.sh +++ b/examples/atomic-counters/atomic-counters.sh @@ -1,7 +1,11 @@ -# Running the program shows that we executed about -# 40,000 operations. +# We expect to get exactly 50,000 operations. Had we +# used the non-atomic `ops++` to increment the counter, +# we'd likely get a different number, changing between +# runs, because the goroutines would interfere with +# each other. Moreover, we'd get data race failures +# when running with the `-race` flag. $ go run atomic-counters.go -ops: 41419 +ops: 50000 # Next we'll look at mutexes, another tool for managing # state. diff --git a/examples/base64-encoding/base64-encoding.go b/examples/base64-encoding/base64-encoding.go index 4bdeaf1..09e94fd 100644 --- a/examples/base64-encoding/base64-encoding.go +++ b/examples/base64-encoding/base64-encoding.go @@ -6,8 +6,10 @@ package main // This syntax imports the `encoding/base64` package with // the `b64` name instead of the default `base64`. It'll // save us some space below. -import b64 "encoding/base64" -import "fmt" +import ( + b64 "encoding/base64" + "fmt" +) func main() { diff --git a/examples/base64-encoding/base64-encoding.hash b/examples/base64-encoding/base64-encoding.hash index 1cb409a..717ff3f 100644 --- a/examples/base64-encoding/base64-encoding.hash +++ b/examples/base64-encoding/base64-encoding.hash @@ -1,2 +1,2 @@ -c20da14820b656c867790f2e99bc37140babca8c -y_QTcqdkvZh +e0148b9b4acb01e849b8f678cba03f549d250c44 +V3oV1bvh94k diff --git a/examples/channel-synchronization/channel-synchronization.go b/examples/channel-synchronization/channel-synchronization.go index 79ceafe..889b97b 100644 --- a/examples/channel-synchronization/channel-synchronization.go +++ b/examples/channel-synchronization/channel-synchronization.go @@ -6,8 +6,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) // This is the function we'll run in a goroutine. The // `done` channel will be used to notify another diff --git a/examples/channel-synchronization/channel-synchronization.hash b/examples/channel-synchronization/channel-synchronization.hash index e906123..9dea9a0 100644 --- a/examples/channel-synchronization/channel-synchronization.hash +++ b/examples/channel-synchronization/channel-synchronization.hash @@ -1,2 +1,2 @@ -eb022977181884c2ab0f2b69e50311769e67a509 -8lmP8beav0p +0d5a9de912e2a4a18943e082e2f8107cb75d0ce4 +fe9If6OhYMk diff --git a/examples/collection-functions/collection-functions.go b/examples/collection-functions/collection-functions.go index b6ff547..730644c 100644 --- a/examples/collection-functions/collection-functions.go +++ b/examples/collection-functions/collection-functions.go @@ -18,8 +18,10 @@ package main -import "strings" -import "fmt" +import ( + "fmt" + "strings" +) // Index returns the first index of the target string `t`, or // -1 if no match is found. diff --git a/examples/collection-functions/collection-functions.hash b/examples/collection-functions/collection-functions.hash index 4c45952..abbd3d5 100644 --- a/examples/collection-functions/collection-functions.hash +++ b/examples/collection-functions/collection-functions.hash @@ -1,2 +1,2 @@ -d961fc0e0074aed46cfd1516efdadea78781af56 -BJB_npWH516 +28456737ea996664bdaeb8e1e821d95697d00646 +8hI6oPNEfyh diff --git a/examples/command-line-arguments/command-line-arguments.go b/examples/command-line-arguments/command-line-arguments.go index e000e13..1104113 100644 --- a/examples/command-line-arguments/command-line-arguments.go +++ b/examples/command-line-arguments/command-line-arguments.go @@ -5,8 +5,10 @@ package main -import "os" -import "fmt" +import ( + "fmt" + "os" +) func main() { diff --git a/examples/command-line-arguments/command-line-arguments.hash b/examples/command-line-arguments/command-line-arguments.hash index 5bf53c7..ad22b59 100644 --- a/examples/command-line-arguments/command-line-arguments.hash +++ b/examples/command-line-arguments/command-line-arguments.hash @@ -1,2 +1,2 @@ -41c970a1ef29ad2a05307e6c783ff52ab80eaccd -6pFdjf800jj +9c80d495201148bbeb0fd0a5a2ce1735aeb34b60 +myJy_-H8Fo_Q diff --git a/examples/command-line-flags/command-line-flags.go b/examples/command-line-flags/command-line-flags.go index ab9c1b7..96647f5 100644 --- a/examples/command-line-flags/command-line-flags.go +++ b/examples/command-line-flags/command-line-flags.go @@ -8,8 +8,10 @@ package main // Go provides a `flag` package supporting basic // command-line flag parsing. We'll use this package to // implement our example command-line program. -import "flag" -import "fmt" +import ( + "flag" + "fmt" +) func main() { diff --git a/examples/command-line-flags/command-line-flags.hash b/examples/command-line-flags/command-line-flags.hash index 1b8f3ac..abee236 100644 --- a/examples/command-line-flags/command-line-flags.hash +++ b/examples/command-line-flags/command-line-flags.hash @@ -1,2 +1,2 @@ -e2ba0461c090789168c712cc7ed0f66aab09a8c8 -klFR5DitrCy +ab08bf890dcd87b807956b5bee441d59efe458e3 +lPaZodnG9TF diff --git a/examples/constants/constants.go b/examples/constants/constants.go index 50ce8f2..e7af860 100644 --- a/examples/constants/constants.go +++ b/examples/constants/constants.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "math" +import ( + "fmt" + "math" +) // `const` declares a constant value. const s string = "constant" diff --git a/examples/constants/constants.hash b/examples/constants/constants.hash index 1e282aa..93d42ca 100644 --- a/examples/constants/constants.hash +++ b/examples/constants/constants.hash @@ -1,2 +1,2 @@ -2f2ec3a5ff4eef280199da1908eed261346fb40e -VhP0f8moZd3 +7cc09460e8dc6fffd0ba811679f92a85eb51e927 +gmjHSglwLic diff --git a/examples/defer/defer.go b/examples/defer/defer.go index 06c827f..b4077c7 100644 --- a/examples/defer/defer.go +++ b/examples/defer/defer.go @@ -5,8 +5,10 @@ package main -import "fmt" -import "os" +import ( + "fmt" + "os" +) // Suppose we wanted to create a file, write to it, // and then close when we're done. Here's how we could @@ -40,5 +42,11 @@ func writeFile(f *os.File) { func closeFile(f *os.File) { fmt.Println("closing") - f.Close() + err := f.Close() + // 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 2994617..d45bfd7 100644 --- a/examples/defer/defer.hash +++ b/examples/defer/defer.hash @@ -1,2 +1,2 @@ -570699fc50a1d39e9d0ad6a4461aef3248b080e1 -xPbQ5SGkH2O +4fc23579a9bd5d8512884902394f4dce51eb7d60 +QJJ2R6kv6K5 diff --git a/examples/directories/directories.go b/examples/directories/directories.go new file mode 100644 index 0000000..9b71274 --- /dev/null +++ b/examples/directories/directories.go @@ -0,0 +1,95 @@ +// Go has several useful functions for working with +// *directories* in the file system. + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +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 with `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) + + // 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 new file mode 100644 index 0000000..cebae56 --- /dev/null +++ b/examples/directories/directories.hash @@ -0,0 +1,2 @@ +83f67db91816b4544072d0a4d099111a21c60723 +-7kWq0PmATF diff --git a/examples/directories/directories.sh b/examples/directories/directories.sh new file mode 100644 index 0000000..31a8f0c --- /dev/null +++ b/examples/directories/directories.sh @@ -0,0 +1,15 @@ +$ go run directories.go +Listing subdir/parent + child true + file2 false + file3 false +Listing subdir/parent/child + 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/examples/environment-variables/environment-variables.go b/examples/environment-variables/environment-variables.go index beca4e7..b316b8a 100644 --- a/examples/environment-variables/environment-variables.go +++ b/examples/environment-variables/environment-variables.go @@ -5,9 +5,11 @@ package main -import "os" -import "strings" -import "fmt" +import ( + "fmt" + "os" + "strings" +) func main() { diff --git a/examples/environment-variables/environment-variables.hash b/examples/environment-variables/environment-variables.hash index 81632ac..b245851 100644 --- a/examples/environment-variables/environment-variables.hash +++ b/examples/environment-variables/environment-variables.hash @@ -1,2 +1,2 @@ -4d0832c5a1ddd4e95474791e8802c15452358214 -CZJ4R_uu6Uu +db2e203da519a22943753295e9cc27d89e4347b0 +bKuCOOD16KH diff --git a/examples/epoch/epoch.go b/examples/epoch/epoch.go index 63cffbb..ed7f442 100644 --- a/examples/epoch/epoch.go +++ b/examples/epoch/epoch.go @@ -5,8 +5,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) func main() { diff --git a/examples/epoch/epoch.hash b/examples/epoch/epoch.hash index 3899c7f..d37c230 100644 --- a/examples/epoch/epoch.hash +++ b/examples/epoch/epoch.hash @@ -1,2 +1,2 @@ -61a498229c8878a97d729cfdd215e5f3960f87ac -eN1Qv2ATB-C +184c8f3e94dd28176be81956115ac417e33513a6 +3uYNHHRplmQ diff --git a/examples/errors/errors.go b/examples/errors/errors.go index 0b69bad..b850139 100644 --- a/examples/errors/errors.go +++ b/examples/errors/errors.go @@ -9,8 +9,10 @@ package main -import "errors" -import "fmt" +import ( + "errors" + "fmt" +) // By convention, errors are the last return value and // have type `error`, a built-in interface. diff --git a/examples/errors/errors.hash b/examples/errors/errors.hash index d0b2112..b650d25 100644 --- a/examples/errors/errors.hash +++ b/examples/errors/errors.hash @@ -1,2 +1,2 @@ -210ba0f8196006c0380acaec01655816848ef168 -mP_ZR1qjUvA +ed58ad3162d93c723d3efe72529a61ce7041fe13 +vrwN32gxaYx diff --git a/examples/execing-processes/execing-processes.go b/examples/execing-processes/execing-processes.go index b9caed1..18eb283 100644 --- a/examples/execing-processes/execing-processes.go +++ b/examples/execing-processes/execing-processes.go @@ -10,9 +10,11 @@ package main -import "syscall" -import "os" -import "os/exec" +import ( + "os" + "os/exec" + "syscall" +) func main() { diff --git a/examples/execing-processes/execing-processes.hash b/examples/execing-processes/execing-processes.hash index 4701404..020f78e 100644 --- a/examples/execing-processes/execing-processes.hash +++ b/examples/execing-processes/execing-processes.hash @@ -1,2 +1,2 @@ -b527bbb76a42dd4bae541b73a7377b7e83e79905 -bf11ADw-2Ho +e6b4830d4264f307506b54726ec79b25a0363874 +ahZjpJaZz44 diff --git a/examples/exit/exit.go b/examples/exit/exit.go index d1e3646..578e553 100644 --- a/examples/exit/exit.go +++ b/examples/exit/exit.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "os" +import ( + "fmt" + "os" +) func main() { diff --git a/examples/exit/exit.hash b/examples/exit/exit.hash index 988b8f3..234717b 100644 --- a/examples/exit/exit.hash +++ b/examples/exit/exit.hash @@ -1,2 +1,2 @@ -dc0bb3eaafa045d6aa05e88aff39322a1ccf822e -vDaM0-MGJ_k +2316e6c8e364e2066c6bd350dc9b0b2af85b63fe +OX997ykuOGx 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") } 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/examples/interfaces/interfaces.go b/examples/interfaces/interfaces.go index 2ac30bd..806ffa7 100644 --- a/examples/interfaces/interfaces.go +++ b/examples/interfaces/interfaces.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "math" +import ( + "fmt" + "math" +) // Here's a basic interface for geometric shapes. type geometry interface { diff --git a/examples/interfaces/interfaces.hash b/examples/interfaces/interfaces.hash index d9daece..b6fa983 100644 --- a/examples/interfaces/interfaces.hash +++ b/examples/interfaces/interfaces.hash @@ -1,2 +1,2 @@ -3547b935d1e0322c0fb696726c27cae53a275e0a -0EwsqIn3TTi +aac1328f5a04568272b82753ff0762b9eacff4fc +hXTlbUAGcvn diff --git a/examples/json/json.go b/examples/json/json.go index 62bc1ea..2594786 100644 --- a/examples/json/json.go +++ b/examples/json/json.go @@ -4,9 +4,11 @@ package main -import "encoding/json" -import "fmt" -import "os" +import ( + "encoding/json" + "fmt" + "os" +) // We'll use these two structs to demonstrate encoding and // decoding of custom types below. @@ -14,6 +16,9 @@ type response1 struct { Page int Fruits []string } + +// Only exported fields will be encoded/decoded in JSON. +// Fields must start with capital letters to be exported. type response2 struct { Page int `json:"page"` Fruits []string `json:"fruits"` diff --git a/examples/json/json.hash b/examples/json/json.hash index 3acb1f6..8c217d6 100644 --- a/examples/json/json.hash +++ b/examples/json/json.hash @@ -1,2 +1,2 @@ -d4dc2281f64061f077d8f1e9687538f41a339b25 -xC6SHbzGBZC +c751bc7223b8bc615f82fe7643ab98ce2b80240f +ROikmz5tRhZ diff --git a/examples/number-parsing/number-parsing.go b/examples/number-parsing/number-parsing.go index 15a03bf..6371637 100644 --- a/examples/number-parsing/number-parsing.go +++ b/examples/number-parsing/number-parsing.go @@ -5,8 +5,10 @@ package main // The built-in package `strconv` provides the number // parsing. -import "strconv" -import "fmt" +import ( + "fmt" + "strconv" +) func main() { diff --git a/examples/number-parsing/number-parsing.hash b/examples/number-parsing/number-parsing.hash index 3249903..eeaf3cd 100644 --- a/examples/number-parsing/number-parsing.hash +++ b/examples/number-parsing/number-parsing.hash @@ -1,2 +1,2 @@ -0d2155e9863a73c098d44637e92403d7f5e8e965 -NZh4LjhguvN +0191c7e43706640207c403ba92dd2272d66fc868 +t2q4KnWWTAw diff --git a/examples/random-numbers/random-numbers.go b/examples/random-numbers/random-numbers.go index b27c200..ebb6a8c 100644 --- a/examples/random-numbers/random-numbers.go +++ b/examples/random-numbers/random-numbers.go @@ -4,9 +4,11 @@ package main -import "time" -import "fmt" -import "math/rand" +import ( + "fmt" + "math/rand" + "time" +) func main() { diff --git a/examples/random-numbers/random-numbers.hash b/examples/random-numbers/random-numbers.hash index 87959ee..3ebbc4a 100644 --- a/examples/random-numbers/random-numbers.hash +++ b/examples/random-numbers/random-numbers.hash @@ -1,2 +1,2 @@ -8e97de760147b061dd09939db294c892211b6b80 -jiJaIjxL2sP +9374869a809d28ea784a9e1181b4aa1988018776 +DVHO7SjJZnp diff --git a/examples/rate-limiting/rate-limiting.go b/examples/rate-limiting/rate-limiting.go index 175bbcc..c32483d 100644 --- a/examples/rate-limiting/rate-limiting.go +++ b/examples/rate-limiting/rate-limiting.go @@ -6,8 +6,10 @@ package main -import "time" -import "fmt" +import ( + "fmt" + "time" +) func main() { diff --git a/examples/rate-limiting/rate-limiting.hash b/examples/rate-limiting/rate-limiting.hash index ccbbc49..be48802 100644 --- a/examples/rate-limiting/rate-limiting.hash +++ b/examples/rate-limiting/rate-limiting.hash @@ -1,2 +1,2 @@ -edad78bf3b36ddc9bec30b344b8a72be4de90f3b -l4uDE-RCDpa +357d83df3e48675eb1e135188cb9f07448c1f146 +AJ-MJephNib diff --git a/examples/regular-expressions/regular-expressions.go b/examples/regular-expressions/regular-expressions.go index 5d5ee8c..52ec06d 100644 --- a/examples/regular-expressions/regular-expressions.go +++ b/examples/regular-expressions/regular-expressions.go @@ -4,9 +4,11 @@ package main -import "bytes" -import "fmt" -import "regexp" +import ( + "bytes" + "fmt" + "regexp" +) func main() { diff --git a/examples/regular-expressions/regular-expressions.hash b/examples/regular-expressions/regular-expressions.hash index abc14cd..236706c 100644 --- a/examples/regular-expressions/regular-expressions.hash +++ b/examples/regular-expressions/regular-expressions.hash @@ -1,2 +1,2 @@ -7cde6b9af5cf6c47606001dd54eee468a6c61dbb -qR5gn2l0AGa +de24265897edf1d3913e3b87f70757284a66ecea +urHlUNDVenk diff --git a/examples/select/select.go b/examples/select/select.go index c05aacb..d2ce16e 100644 --- a/examples/select/select.go +++ b/examples/select/select.go @@ -4,8 +4,10 @@ package main -import "time" -import "fmt" +import ( + "fmt" + "time" +) func main() { diff --git a/examples/select/select.hash b/examples/select/select.hash index 5037668..ea97b26 100644 --- a/examples/select/select.hash +++ b/examples/select/select.hash @@ -1,2 +1,2 @@ -8d743edffd7de6bf7bccdf4437f45672b6adc75e -ZdSOPe1Gj13 +6e1125087bc036ebd905452300575f160d683918 +yF-xgN7Xf9P diff --git a/examples/sha1-hashes/sha1-hashes.go b/examples/sha1-hashes/sha1-hashes.go index db8bb39..24e5921 100644 --- a/examples/sha1-hashes/sha1-hashes.go +++ b/examples/sha1-hashes/sha1-hashes.go @@ -9,8 +9,10 @@ package main // Go implements several hash functions in various // `crypto/*` packages. -import "crypto/sha1" -import "fmt" +import ( + "crypto/sha1" + "fmt" +) func main() { s := "sha1 this string" diff --git a/examples/sha1-hashes/sha1-hashes.hash b/examples/sha1-hashes/sha1-hashes.hash index e56a014..5af2939 100644 --- a/examples/sha1-hashes/sha1-hashes.hash +++ b/examples/sha1-hashes/sha1-hashes.hash @@ -1,2 +1,2 @@ -6a896270e34f2696b881a8fa7e68bfff57dee51f -1oT-5GBUkLr +4cda643ba233014fe6b30966c37d4d0fcd4edbe8 +oqcrTfY4Ykd diff --git a/examples/signals/signals.go b/examples/signals/signals.go index 38e17ad..4cd373b 100644 --- a/examples/signals/signals.go +++ b/examples/signals/signals.go @@ -7,10 +7,12 @@ package main -import "fmt" -import "os" -import "os/signal" -import "syscall" +import ( + "fmt" + "os" + "os/signal" + "syscall" +) func main() { diff --git a/examples/signals/signals.hash b/examples/signals/signals.hash index 94e8edb..82345ca 100644 --- a/examples/signals/signals.hash +++ b/examples/signals/signals.hash @@ -1,2 +1,2 @@ -9720d747e3ab2893df508a70cbb341c90fdd7ca1 -9koJAW1raI5 +1e43c6f63f1d57e1a52c89f52d35b68757e9676b +_6oj-T3Gko2 diff --git a/examples/sorting-by-functions/sorting-by-functions.go b/examples/sorting-by-functions/sorting-by-functions.go index b880564..8524f66 100644 --- a/examples/sorting-by-functions/sorting-by-functions.go +++ b/examples/sorting-by-functions/sorting-by-functions.go @@ -6,8 +6,10 @@ package main -import "sort" -import "fmt" +import ( + "fmt" + "sort" +) // In order to sort by a custom function in Go, we need a // corresponding type. Here we've created a `byLength` diff --git a/examples/sorting-by-functions/sorting-by-functions.hash b/examples/sorting-by-functions/sorting-by-functions.hash index 776dde8..d62f035 100644 --- a/examples/sorting-by-functions/sorting-by-functions.hash +++ b/examples/sorting-by-functions/sorting-by-functions.hash @@ -1,2 +1,2 @@ -6a04058b564d5741815e523f97f240ee6563cb15 -y3kuCwIFRYK +f7d0b7840dd12601fb86946f9dc4c38fb1c0501f +Jtxf94x94Hx diff --git a/examples/sorting/sorting.go b/examples/sorting/sorting.go index b6317ed..acc67d8 100644 --- a/examples/sorting/sorting.go +++ b/examples/sorting/sorting.go @@ -4,8 +4,10 @@ package main -import "fmt" -import "sort" +import ( + "fmt" + "sort" +) func main() { diff --git a/examples/sorting/sorting.hash b/examples/sorting/sorting.hash index ae5e449..d72396f 100644 --- a/examples/sorting/sorting.hash +++ b/examples/sorting/sorting.hash @@ -1,2 +1,2 @@ -4e576421f2bdbd11847c367d223bd30d0e301990 -e6hp3Rn-oH6 +e11e944d34b21e75ce4f7c91026d4200ce592dc5 +tAWAkRlBJNX diff --git a/examples/spawning-processes/spawning-processes.go b/examples/spawning-processes/spawning-processes.go index 98e0f65..58fdae8 100644 --- a/examples/spawning-processes/spawning-processes.go +++ b/examples/spawning-processes/spawning-processes.go @@ -7,9 +7,11 @@ package main -import "fmt" -import "io/ioutil" -import "os/exec" +import ( + "fmt" + "io/ioutil" + "os/exec" +) func main() { diff --git a/examples/spawning-processes/spawning-processes.hash b/examples/spawning-processes/spawning-processes.hash index dd1b749..bcde707 100644 --- a/examples/spawning-processes/spawning-processes.hash +++ b/examples/spawning-processes/spawning-processes.hash @@ -1,2 +1,2 @@ -0b676b93e41ac5434003c194bc038d5f3ce76bc8 -6HRWVK5gPYU +cc68e4290f10209ad2fa8db74fdfaea7fdb44d5c +QS_Nkoe8VLG diff --git a/examples/string-formatting/string-formatting.go b/examples/string-formatting/string-formatting.go index de7c285..958cb64 100644 --- a/examples/string-formatting/string-formatting.go +++ b/examples/string-formatting/string-formatting.go @@ -4,8 +4,10 @@ package main -import "fmt" -import "os" +import ( + "fmt" + "os" +) type point struct { x, y int diff --git a/examples/string-formatting/string-formatting.hash b/examples/string-formatting/string-formatting.hash index ba1b396..c339d9b 100644 --- a/examples/string-formatting/string-formatting.hash +++ b/examples/string-formatting/string-formatting.hash @@ -1,2 +1,2 @@ -5f39ae6d8f26d59a688a9a9d7d13a5c1d0f7a08b -CkBQ3CFpHQ9 +12b245c576b43537c092a5b84995ebca8ce78a57 +vmYSdxfUcRh diff --git a/examples/string-functions/string-functions.go b/examples/string-functions/string-functions.go index c8f2b54..676e904 100644 --- a/examples/string-functions/string-functions.go +++ b/examples/string-functions/string-functions.go @@ -4,8 +4,10 @@ package main -import s "strings" -import "fmt" +import ( + "fmt" + s "strings" +) // We alias `fmt.Println` to a shorter name as we'll use // it a lot below. diff --git a/examples/string-functions/string-functions.hash b/examples/string-functions/string-functions.hash index 068746c..568c7c6 100644 --- a/examples/string-functions/string-functions.hash +++ b/examples/string-functions/string-functions.hash @@ -1,2 +1,2 @@ -17aa523bbd606fa0b624fae44b89812d46330755 -Vn4D3y4_711 +bf39c7540bd78eba38eb5a9047a9d0ffc7235f85 +xoRUhG86wsF diff --git a/examples/structs/structs.go b/examples/structs/structs.go index 6cf5629..384b57c 100644 --- a/examples/structs/structs.go +++ b/examples/structs/structs.go @@ -12,6 +12,15 @@ type person struct { age int } +// 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} + p.age = 42 + return &p +} + func main() { // This syntax creates a new struct. @@ -26,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) diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index 2c0e37f..15fcdc0 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ -49cad39331ee5e9fb8d8dad99d3aff7f18a4e6d0 -XMZpGsF4sWM +c5caaf1eefaf084d688afb70d2ee5884a4983182 +00Yiw6xuICq 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/examples/switch/switch.go b/examples/switch/switch.go index 8d72bee..2d2ec2e 100644 --- a/examples/switch/switch.go +++ b/examples/switch/switch.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) func main() { diff --git a/examples/switch/switch.hash b/examples/switch/switch.hash index 5559e1a..54d2e9f 100644 --- a/examples/switch/switch.hash +++ b/examples/switch/switch.hash @@ -1,2 +1,2 @@ -b47004b3e3b6d787ea98642dc5b955df57cd2bcd -TJ4Az0KuLfL +2486fc553301cdeac9a26f3d0b3aed4143d9f4f0 +ZcDzdx3nYQn 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..c855624 --- /dev/null +++ b/examples/temporary-files-and-directories/temporary-files-and-directories.sh @@ -0,0 +1,3 @@ +$ go run temporary-files-and-directories.go +Temp file name: /tmp/sample610887201 +Temp dir name: /tmp/sampledir898854668 diff --git a/examples/tickers/tickers.go b/examples/tickers/tickers.go index 110a192..c23dd5c 100644 --- a/examples/tickers/tickers.go +++ b/examples/tickers/tickers.go @@ -6,8 +6,10 @@ package main -import "time" -import "fmt" +import ( + "fmt" + "time" +) func main() { @@ -16,9 +18,16 @@ func main() { // `range` builtin on the channel to iterate over // the values as they arrive every 500ms. ticker := time.NewTicker(500 * time.Millisecond) + done := make(chan bool) + go func() { - for t := range ticker.C { - fmt.Println("Tick at", t) + for { + select { + case <-done: + return + case t := <-ticker.C: + fmt.Println("Tick at", t) + } } }() @@ -27,5 +36,6 @@ func main() { // channel. We'll stop ours after 1600ms. time.Sleep(1600 * time.Millisecond) ticker.Stop() + done <- true fmt.Println("Ticker stopped") } diff --git a/examples/tickers/tickers.hash b/examples/tickers/tickers.hash index 0404929..e724ec1 100644 --- a/examples/tickers/tickers.hash +++ b/examples/tickers/tickers.hash @@ -1,2 +1,2 @@ -7dc6447323f493f72aa70952bf3e3f2c6156f82f -Rgc_UDvHv6a +4a42333d14f902e890902343c7bd9b9c735fd8ad +n1q1sSGEvmv diff --git a/examples/time-formatting-parsing/time-formatting-parsing.go b/examples/time-formatting-parsing/time-formatting-parsing.go index a213baf..2968c3c 100644 --- a/examples/time-formatting-parsing/time-formatting-parsing.go +++ b/examples/time-formatting-parsing/time-formatting-parsing.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) func main() { p := fmt.Println diff --git a/examples/time-formatting-parsing/time-formatting-parsing.hash b/examples/time-formatting-parsing/time-formatting-parsing.hash index 0d05bde..eee6d65 100644 --- a/examples/time-formatting-parsing/time-formatting-parsing.hash +++ b/examples/time-formatting-parsing/time-formatting-parsing.hash @@ -1,2 +1,2 @@ -1f9962260f5c92efe57db0b96099b3dd06c90333 -nHAisH6amZG +9e3f17061fef280191e3e8518365e231e17a5d5a +1410R7Fcyx0 diff --git a/examples/time/time.go b/examples/time/time.go index 1d01432..db96527 100644 --- a/examples/time/time.go +++ b/examples/time/time.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) func main() { p := fmt.Println diff --git a/examples/time/time.hash b/examples/time/time.hash index 9542207..2c9d415 100644 --- a/examples/time/time.hash +++ b/examples/time/time.hash @@ -1,2 +1,2 @@ -b6308f1fea7665e89a28f54aac6cb49b95685eb5 -PZMCzzaJURJ +c47d853fa7527a652ce78b0285e452c6cd740050 +u-7i_p8BHVt diff --git a/examples/timeouts/timeouts.go b/examples/timeouts/timeouts.go index ccc9ecb..3f25aec 100644 --- a/examples/timeouts/timeouts.go +++ b/examples/timeouts/timeouts.go @@ -5,14 +5,19 @@ package main -import "time" -import "fmt" +import ( + "fmt" + "time" +) func main() { // For our example, suppose we're executing an external // call that returns its result on a channel `c1` - // after 2s. + // after 2s. Note that the channel is buffered, so the + // send in the goroutine is nonblocking. This is a + // common pattern to prevent goroutine leaks in case the + // channel is never read. c1 := make(chan string, 1) go func() { time.Sleep(2 * time.Second) diff --git a/examples/timeouts/timeouts.hash b/examples/timeouts/timeouts.hash index 64d1c5a..f622aeb 100644 --- a/examples/timeouts/timeouts.hash +++ b/examples/timeouts/timeouts.hash @@ -1,2 +1,2 @@ -93343e1aacb14f818c87732914c29ba57afab245 -MgcfA-xpJO9 +b8d3e745539b24d3530ca21efcdc924f08769edb +TYJgoFjlTd6 diff --git a/examples/timeouts/timeouts.sh b/examples/timeouts/timeouts.sh index 8a9dfb4..3c4344f 100644 --- a/examples/timeouts/timeouts.sh +++ b/examples/timeouts/timeouts.sh @@ -3,9 +3,3 @@ $ go run timeouts.go timeout 1 result 2 - -# Using this `select` timeout pattern requires -# communicating results over channels. This is a good -# idea in general because other important Go features are -# based on channels and `select`. We'll look at two -# examples of this next: timers and tickers. diff --git a/examples/timers/timers.go b/examples/timers/timers.go index 939cf11..d0256e6 100644 --- a/examples/timers/timers.go +++ b/examples/timers/timers.go @@ -6,8 +6,10 @@ package main -import "time" -import "fmt" +import ( + "fmt" + "time" +) func main() { diff --git a/examples/timers/timers.hash b/examples/timers/timers.hash index f51b1f0..8c0f2c4 100644 --- a/examples/timers/timers.hash +++ b/examples/timers/timers.hash @@ -1,2 +1,2 @@ -e10c601ab3b702dfcea728c1edb31673561484b5 -pybl9hRvJq2 +e8e501d6083bea786629ca5e485e8b18caab4815 +pLnKEIesooU diff --git a/examples/url-parsing/url-parsing.go b/examples/url-parsing/url-parsing.go index b4e0050..f7590f1 100644 --- a/examples/url-parsing/url-parsing.go +++ b/examples/url-parsing/url-parsing.go @@ -3,9 +3,11 @@ package main -import "fmt" -import "net" -import "net/url" +import ( + "fmt" + "net" + "net/url" +) func main() { diff --git a/examples/url-parsing/url-parsing.hash b/examples/url-parsing/url-parsing.hash index 019a1a6..77021f1 100644 --- a/examples/url-parsing/url-parsing.hash +++ b/examples/url-parsing/url-parsing.hash @@ -1,2 +1,2 @@ -b7a0813e9413bfcc956cc58b850f655dd129ebb7 -AL79Lv-9CWo +babc12f5066652f4cb0151231c06f1037298ff28 +M218D9Tldlr diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index 84c8bf1..1584d59 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -3,8 +3,10 @@ package main -import "fmt" -import "time" +import ( + "fmt" + "time" +) // Here's the worker, of which we'll run several // concurrent instances. These workers will receive diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index 9f101b7..dbfeb88 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -bc69c6602d438413dcb9ceac112299ee253e4575 -yuHsGf712D1 +9b30cdfc3f46d634c3b8671a7ae1551c133fb6e2 +IiKZ-nj-nKY diff --git a/examples/xml/xml.go b/examples/xml/xml.go new file mode 100644 index 0000000..e545106 --- /dev/null +++ b/examples/xml/xml.go @@ -0,0 +1,69 @@ +// Go offers built-in support for XML and XML-like +// formats with the `encoding.xml` package. + +package main + +import ( + "encoding/xml" + "fmt" +) + +// This type will be mapped to XML. Similarly to the +// JSON examples, field tags contain directives for the +// encoder and decoder. Here we use some special features +// of the XML package: the `XMLName` field name dictates +// the name of the XML element representing this struct; +// `id,attr` means that the `Id` field is an XML +// _attribute_ rather than a nested element. +type Plant struct { + XMLName xml.Name `xml:"plant"` + Id int `xml:"id,attr"` + Name string `xml:"name"` + Origin []string `xml:"origin"` +} + +func (p Plant) String() string { + return fmt.Sprintf("Plant id=%v, name=%v, origin=%v", + p.Id, p.Name, p.Origin) +} + +func main() { + coffee := &Plant{Id: 27, Name: "Coffee"} + coffee.Origin = []string{"Ethiopia", "Brazil"} + + // Emit XML representing our plant; using + // `MarshalIndent` to produce a more + // human-readable output. + out, _ := xml.MarshalIndent(coffee, " ", " ") + fmt.Println(string(out)) + + // To add a generic XML header to the output, append + // it explicitly. + fmt.Println(xml.Header + string(out)) + + // Use `Unmarhshal` to parse a stream of bytes with XML + // into a data structure. If the XML is malformed or + // cannot be mapped onto Plant, a descriptive error + // will be returned. + var p Plant + if err := xml.Unmarshal(out, &p); err != nil { + panic(err) + } + fmt.Println(p) + + tomato := &Plant{Id: 81, Name: "Tomato"} + tomato.Origin = []string{"Mexico", "California"} + + // The `parent>child>plant` field tag tells the encoder + // to nest all `plant`s under `...` + type Nesting struct { + XMLName xml.Name `xml:"nesting"` + Plants []*Plant `xml:"parent>child>plant"` + } + + nesting := &Nesting{} + nesting.Plants = []*Plant{coffee, tomato} + + out, _ = xml.MarshalIndent(nesting, " ", " ") + fmt.Println(string(out)) +} diff --git a/examples/xml/xml.hash b/examples/xml/xml.hash new file mode 100644 index 0000000..104125d --- /dev/null +++ b/examples/xml/xml.hash @@ -0,0 +1,2 @@ +18ada773098bca38778a58b438d6af70529f18b0 +qd9Ii_3AW0s diff --git a/examples/xml/xml.sh b/examples/xml/xml.sh new file mode 100644 index 0000000..0e8d2cd --- /dev/null +++ b/examples/xml/xml.sh @@ -0,0 +1,29 @@ +$ go run xml.go + + Coffee + Ethiopia + Brazil + + + + Coffee + Ethiopia + Brazil + +Plant id=27, name=Coffee, origin=[Ethiopia Brazil] + + + + + Coffee + Ethiopia + Brazil + + + Tomato + Mexico + California + + + + diff --git a/public/arrays b/public/arrays index 9f12e9d..d8273e0 100644 --- a/public/arrays +++ b/public/arrays @@ -5,6 +5,20 @@ Go by Example: Arrays +

Go by Example: Arrays

@@ -19,7 +33,7 @@ specific length.

- + @@ -28,10 +42,8 @@ specific length.

- - - -
package main
+            
+          
package main
 
@@ -43,7 +55,7 @@ specific length.

-
import "fmt"
+          
import "fmt"
 
@@ -55,7 +67,7 @@ specific length.

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

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

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

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

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

-
    var twoD [2][3]int
+          
    var twoD [2][3]int
     for i := 0; i < 2; i++ {
         for j := 0; j < 3; j++ {
             twoD[i][j] = i + j
@@ -157,7 +169,7 @@ when printed with fmt.Println.

-
$ go run arrays.go
+          
$ go run arrays.go
 emp: [0 0 0 0 0]
 set: [0 0 0 0 100]
 get: 100
@@ -177,7 +189,7 @@ typical Go. We’ll look at slices next.

- + @@ -192,5 +204,10 @@ typical Go. We’ll look at slices next.

by Mark McGranaghan | source | license

+ + diff --git a/public/atomic-counters b/public/atomic-counters index 9ba1895..9627c97 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -5,6 +5,20 @@ Go by Example: Atomic Counters +

Go by Example: Atomic Counters

@@ -23,7 +37,7 @@ counters accessed by multiple goroutines.

- + @@ -32,10 +46,8 @@ counters accessed by multiple goroutines.

- - - -
package main
+            
+          
package main
 
@@ -47,9 +59,11 @@ counters accessed by multiple goroutines.

-
import "fmt"
-import "time"
-import "sync/atomic"
+          
import (
+    "fmt"
+    "sync"
+    "sync/atomic"
+)
 
@@ -61,7 +75,7 @@ counters accessed by multiple goroutines.

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

-
    var ops uint64
+          
    var ops uint64
 
@@ -83,16 +97,28 @@ counters accessed by multiple goroutines.

-

To simulate concurrent updates, we’ll start 50 -goroutines that each increment the counter about -once a millisecond.

+

A WaitGroup will help us wait for all goroutines +to finish their work.

-
    for i := 0; i < 50; i++ {
-        go func() {
-            for {
+          
    var wg sync.WaitGroup
+
+ + + + + + +

We’ll start 50 goroutines that each increment the +counter exactly 1000 times.

+ + + + +
    for i := 0; i < 50; i++ {
+        wg.Add(1)
 
@@ -108,7 +134,8 @@ address of our ops counter with the -
                atomic.AddUint64(&ops, 1)
+          
        go func() {
+            for c := 0; c < 1000; c++ {
 
@@ -116,13 +143,13 @@ address of our ops counter with the -

Wait a bit between increments.

- + -
                time.Sleep(time.Millisecond)
+          
                atomic.AddUint64(&ops, 1)
             }
+            wg.Done()
         }()
     }
 
@@ -132,12 +159,12 @@ address of our ops counter with the -

Wait a second to allow some ops to accumulate.

+

Wait until all the goroutines are done.

-
    time.Sleep(time.Second)
+          
    wg.Wait()
 
@@ -145,18 +172,16 @@ address of our ops counter with the -

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.

+

It’s safe to access ops now because we know +no other goroutine is writing to it. Reading +atomics safely while they are being updated is +also possible, using functions like +atomic.LoadUint64.

-
    opsFinal := atomic.LoadUint64(&ops)
-    fmt.Println("ops:", opsFinal)
+          
    fmt.Println("ops:", ops)
 }
 
@@ -169,14 +194,18 @@ fetch the value.

-

Running the program shows that we executed about -40,000 operations.

+

We expect to get exactly 50,000 operations. Had we +used the non-atomic ops++ to increment the counter, +we’d likely get a different number, changing between +runs, because the goroutines would interfere with +each other. Moreover, we’d get data race failures +when running with the -race flag.

-
$ go run atomic-counters.go
-ops: 41419
+          
$ go run atomic-counters.go
+ops: 50000
 
@@ -190,7 +219,7 @@ state.

- + @@ -205,5 +234,10 @@ state.

by Mark McGranaghan | source | license

+ + diff --git a/public/base64-encoding b/public/base64-encoding index 2c1da0d..7bf8d28 100644 --- a/public/base64-encoding +++ b/public/base64-encoding @@ -5,6 +5,20 @@ Go by Example: Base64 Encoding +

Go by Example: Base64 Encoding

@@ -19,7 +33,7 @@ encoding/decoding.

- + @@ -28,10 +42,8 @@ encoding/decoding.

- - - -
package main
+            
+          
package main
 
@@ -46,8 +58,10 @@ save us some space below.

-
import b64 "encoding/base64"
-import "fmt"
+          
import (
+    b64 "encoding/base64"
+    "fmt"
+)
 
@@ -59,7 +73,7 @@ save us some space below.

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

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

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

-
    sDec, _ := b64.StdEncoding.DecodeString(sEnc)
+          
    sDec, _ := b64.StdEncoding.DecodeString(sEnc)
     fmt.Println(string(sDec))
     fmt.Println()
 
@@ -120,7 +134,7 @@ format.

-
    uEnc := b64.URLEncoding.EncodeToString([]byte(data))
+          
    uEnc := b64.URLEncoding.EncodeToString([]byte(data))
     fmt.Println(uEnc)
     uDec, _ := b64.URLEncoding.DecodeString(uEnc)
     fmt.Println(string(uDec))
@@ -143,7 +157,7 @@ but they both decode to the original string as desired.

-
$ go run base64-encoding.go
+          
$ go run base64-encoding.go
 YWJjMTIzIT8kKiYoKSctPUB+
 abc123!?$*&()'-=@~
 
@@ -157,7 +171,7 @@ but they both decode to the original string as desired.

-
YWJjMTIzIT8kKiYoKSctPUB-
+          
YWJjMTIzIT8kKiYoKSctPUB-
 abc123!?$*&()'-=@~
 
@@ -175,5 +189,10 @@ but they both decode to the original string as desired.

by Mark McGranaghan | source | license

+ + diff --git a/public/channel-buffering b/public/channel-buffering index 2734939..eab9a6e 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -5,6 +5,20 @@ Go by Example: Channel Buffering +

Go by Example: Channel Buffering

@@ -23,7 +37,7 @@ those values.

- + @@ -32,10 +46,8 @@ those values.

- - - -
package main
+            
+          
package main
 
@@ -47,7 +59,7 @@ those values.

-
import "fmt"
+          
import "fmt"
 
@@ -59,7 +71,7 @@ those values.

-
func main() {
+          
func main() {
 
@@ -73,7 +85,7 @@ those values.

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

-
    messages <- "buffered"
+          
    messages <- "buffered"
     messages <- "channel"
 
@@ -102,7 +114,7 @@ concurrent receive.

-
    fmt.Println(<-messages)
+          
    fmt.Println(<-messages)
     fmt.Println(<-messages)
 }
 
@@ -120,7 +132,7 @@ concurrent receive.

-
$ go run channel-buffering.go 
+          
$ go run channel-buffering.go 
 buffered
 channel
 
@@ -139,5 +151,10 @@ concurrent receive.

by Mark McGranaghan | source | license

+ + diff --git a/public/channel-directions b/public/channel-directions index 02c7c0a..fbbe7b5 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -5,6 +5,20 @@ Go by Example: Channel Directions +

Go by Example: Channel Directions

@@ -21,7 +35,7 @@ the program.

- + @@ -30,10 +44,8 @@ the program.

- - - -
package main
+            
+          
package main
 
@@ -45,7 +57,7 @@ the program.

-
import "fmt"
+          
import "fmt"
 
@@ -60,7 +72,7 @@ receive on this channel.

-
func ping(pings chan<- string, msg string) {
+          
func ping(pings chan<- string, msg string) {
     pings <- msg
 }
 
@@ -76,7 +88,7 @@ receive on this channel.

-
func pong(pings <-chan string, pongs chan<- string) {
+          
func pong(pings <-chan string, pongs chan<- string) {
     msg := <-pings
     pongs <- msg
 }
@@ -91,7 +103,7 @@ receive on this channel.

-
func main() {
+          
func main() {
     pings := make(chan string, 1)
     pongs := make(chan string, 1)
     ping(pings, "passed message")
@@ -113,7 +125,7 @@ receive on this channel.

-
$ go run channel-directions.go
+          
$ go run channel-directions.go
 passed message
 
@@ -131,5 +143,10 @@ receive on this channel.

by Mark McGranaghan | source | license

+ + diff --git a/public/channel-synchronization b/public/channel-synchronization index 00076f9..7a0d3a3 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -5,6 +5,20 @@ Go by Example: Channel Synchronization +

Go by Example: Channel Synchronization

@@ -22,7 +36,7 @@ you may prefer to use a WaitGroup.

- + @@ -31,10 +45,8 @@ you may prefer to use a WaitGroup.

- - - -
package main
+            
+          
package main
 
@@ -46,8 +58,10 @@ you may prefer to use a WaitGroup.

-
import "fmt"
-import "time"
+          
import (
+    "fmt"
+    "time"
+)
 
@@ -62,7 +76,7 @@ goroutine that this function’s work is done.

-
func worker(done chan bool) {
+          
func worker(done chan bool) {
     fmt.Print("working...")
     time.Sleep(time.Second)
     fmt.Println("done")
@@ -78,7 +92,7 @@ goroutine that this function’s work is done.

-
    done <- true
+          
    done <- true
 }
 
@@ -91,7 +105,7 @@ goroutine that this function’s work is done.

-
func main() {
+          
func main() {
 
@@ -105,7 +119,7 @@ notify on.

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

-
    <-done
+          
    <-done
 }
 
@@ -137,7 +151,7 @@ worker on the channel.

-
$ go run channel-synchronization.go      
+          
$ go run channel-synchronization.go      
 working...done                  
 
@@ -153,7 +167,7 @@ started.

- + @@ -168,5 +182,10 @@ started.

by Mark McGranaghan | source | license

+ + diff --git a/public/channels b/public/channels index 94b14d7..704c9f4 100644 --- a/public/channels +++ b/public/channels @@ -5,6 +5,20 @@ Go by Example: Channels +

Go by Example: Channels

@@ -21,7 +35,7 @@ goroutine.

- + @@ -30,10 +44,8 @@ goroutine.

- - - -
package main
+            
+          
package main
 
@@ -45,7 +57,7 @@ goroutine.

-
import "fmt"
+          
import "fmt"
 
@@ -57,7 +69,7 @@ goroutine.

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

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

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

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

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

- + @@ -154,5 +166,10 @@ message without having to use any other synchronization.

by Mark McGranaghan | source | license

+ + diff --git a/public/clipboard.png b/public/clipboard.png new file mode 100644 index 0000000..0e262fe Binary files /dev/null and b/public/clipboard.png differ diff --git a/public/closing-channels b/public/closing-channels index d873cd8..8566518 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -5,6 +5,20 @@ Go by Example: Closing Channels +

Go by Example: Closing Channels

@@ -20,7 +34,7 @@ completion to the channel’s receivers.

- + @@ -29,10 +43,8 @@ completion to the channel’s receivers.

- - - -
package main
+            
+          
package main
 
@@ -44,7 +56,7 @@ completion to the channel’s receivers.

-
import "fmt"
+          
import "fmt"
 
@@ -60,7 +72,7 @@ the worker we’ll close the jobs channel.

-
func main() {
+          
func main() {
     jobs := make(chan int, 5)
     done := make(chan bool)
 
@@ -81,7 +93,7 @@ all our jobs.

-
    go func() {
+          
    go func() {
         for {
             j, more := <-jobs
             if more {
@@ -106,7 +118,7 @@ channel, then closes it.

-
    for j := 1; j <= 3; j++ {
+          
    for j := 1; j <= 3; j++ {
         jobs <- j
         fmt.Println("sent job", j)
     }
@@ -126,7 +138,7 @@ we saw earlier.

-
    <-done
+          
    <-done
 }
 
@@ -143,7 +155,7 @@ we saw earlier.

-
$ go run closing-channels.go 
+          
$ go run closing-channels.go 
 sent job 1
 received job 1
 sent job 2
@@ -165,7 +177,7 @@ example: range over channels.

- + @@ -180,5 +192,10 @@ example: range over channels.

by Mark McGranaghan | source | license

+ + diff --git a/public/closures b/public/closures index d85af28..36d6dc4 100644 --- a/public/closures +++ b/public/closures @@ -5,6 +5,20 @@ Go by Example: Closures +

Go by Example: Closures

@@ -21,7 +35,7 @@ a function inline without having to name it.

- + @@ -30,10 +44,8 @@ a function inline without having to name it.

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

-
import "fmt"
+          
import "fmt"
 
@@ -61,7 +73,7 @@ form a closure.

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

-
func main() {
+          
func main() {
 
@@ -95,7 +107,7 @@ we call nextInt.

-
    nextInt := intSeq()
+          
    nextInt := intSeq()
 
@@ -109,7 +121,7 @@ a few times.

-
    fmt.Println(nextInt())
+          
    fmt.Println(nextInt())
     fmt.Println(nextInt())
     fmt.Println(nextInt())
 
@@ -125,7 +137,7 @@ particular function, create and test a new one.

-
    newInts := intSeq()
+          
    newInts := intSeq()
     fmt.Println(newInts())
 }
 
@@ -143,7 +155,7 @@ particular function, create and test a new one.

-
$ go run closures.go
+          
$ go run closures.go
 1
 2
 3
@@ -161,7 +173,7 @@ recursion.

- + @@ -176,5 +188,10 @@ recursion.

by Mark McGranaghan | source | license

+ + diff --git a/public/collection-functions b/public/collection-functions index 07e970b..569c4b3 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -5,6 +5,20 @@ Go by Example: Collection Functions +

Go by Example: Collection Functions

@@ -21,7 +35,7 @@ collection with a custom function.

- + @@ -36,7 +50,7 @@ your program and data types.

- + @@ -52,7 +66,7 @@ helper function.

- + @@ -61,10 +75,8 @@ helper function.

- - - -
package main
+            
+          
package main
 
@@ -76,8 +88,10 @@ helper function.

-
import "strings"
-import "fmt"
+          
import (
+    "fmt"
+    "strings"
+)
 
@@ -91,7 +105,7 @@ helper function.

-
func Index(vs []string, t string) int {
+          
func Index(vs []string, t string) int {
     for i, v := range vs {
         if v == t {
             return i
@@ -112,7 +126,7 @@ slice.

-
func Include(vs []string, t string) bool {
+          
func Include(vs []string, t string) bool {
     return Index(vs, t) >= 0
 }
 
@@ -128,7 +142,7 @@ satisfies the predicate f.

-
func Any(vs []string, f func(string) bool) bool {
+          
func Any(vs []string, f func(string) bool) bool {
     for _, v := range vs {
         if f(v) {
             return true
@@ -149,7 +163,7 @@ satisfy the predicate f.

-
func All(vs []string, f func(string) bool) bool {
+          
func All(vs []string, f func(string) bool) bool {
     for _, v := range vs {
         if !f(v) {
             return false
@@ -170,7 +184,7 @@ slice that satisfy the predicate f.

-
func Filter(vs []string, f func(string) bool) []string {
+          
func Filter(vs []string, f func(string) bool) []string {
     vsf := make([]string, 0)
     for _, v := range vs {
         if f(v) {
@@ -192,7 +206,7 @@ the function f to each string in the original slice.

-
func Map(vs []string, f func(string) string) []string {
+          
func Map(vs []string, f func(string) string) []string {
     vsm := make([]string, len(vs))
     for i, v := range vs {
         vsm[i] = f(v)
@@ -210,7 +224,7 @@ the function f to each string in the original slice.

-
func main() {
+          
func main() {
 
@@ -223,7 +237,7 @@ the function f to each string in the original slice.

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

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

-
    fmt.Println(Include(strs, "grape"))
+          
    fmt.Println(Include(strs, "grape"))
 
@@ -259,7 +273,7 @@ the function f to each string in the original slice.

-
    fmt.Println(Any(strs, func(v string) bool {
+          
    fmt.Println(Any(strs, func(v string) bool {
         return strings.HasPrefix(v, "p")
     }))
 
@@ -273,7 +287,7 @@ the function f to each string in the original slice.

-
    fmt.Println(All(strs, func(v string) bool {
+          
    fmt.Println(All(strs, func(v string) bool {
         return strings.HasPrefix(v, "p")
     }))
 
@@ -287,7 +301,7 @@ the function f to each string in the original slice.

-
    fmt.Println(Filter(strs, func(v string) bool {
+          
    fmt.Println(Filter(strs, func(v string) bool {
         return strings.Contains(v, "e")
     }))
 
@@ -304,7 +318,7 @@ type.

-
    fmt.Println(Map(strs, strings.ToUpper))
+          
    fmt.Println(Map(strs, strings.ToUpper))
 
@@ -316,7 +330,7 @@ type.

-
}
+          
}
 
@@ -332,7 +346,7 @@ type.

-
$ go run collection-functions.go 
+          
$ go run collection-functions.go 
 2
 false
 true
@@ -355,5 +369,10 @@ type.

by Mark McGranaghan | source | license

+ + diff --git a/public/command-line-arguments b/public/command-line-arguments index b649bd2..a2aa9ff 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

@@ -21,7 +35,7 @@ For example, go run hello.go uses run and - + @@ -30,10 +44,8 @@ For example, go run hello.go uses run and - - - -
package main
+            
+          
package main
 
@@ -45,8 +57,10 @@ For example, go run hello.go uses run and -
import "os"
-import "fmt"
+          
import (
+    "fmt"
+    "os"
+)
 
@@ -58,7 +72,7 @@ For example, go run hello.go uses run and -
func main() {
+          
func main() {
 
@@ -74,7 +88,7 @@ holds the arguments to the program.

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

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

-
    fmt.Println(argsWithProg)
+          
    fmt.Println(argsWithProg)
     fmt.Println(argsWithoutProg)
     fmt.Println(arg)
 }
@@ -121,7 +135,7 @@ build a binary with go build first.

-
$ go build command-line-arguments.go
+          
$ go build command-line-arguments.go
 $ ./command-line-arguments a b c d
 [./command-line-arguments a b c d]       
 [a b c d]
@@ -139,7 +153,7 @@ with flags.

- + @@ -154,5 +168,10 @@ with flags.

by Mark McGranaghan | source | license

+ + diff --git a/public/command-line-flags b/public/command-line-flags index 43ec18f..76e2bfc 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

@@ -21,7 +35,7 @@ command-line flag.

- + @@ -30,10 +44,8 @@ command-line flag.

- - - -
package main
+            
+          
package main
 
@@ -48,8 +60,10 @@ implement our example command-line program.

-
import "flag"
-import "fmt"
+          
import (
+    "flag"
+    "fmt"
+)
 
@@ -61,7 +75,7 @@ implement our example command-line program.

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

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

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

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

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

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

-
$ go build command-line-flags.go
+          
$ go build command-line-flags.go
 
@@ -179,7 +193,7 @@ all flags.

-
$ ./command-line-flags -word=opt -numb=7 -fork -svar=flag
+          
$ ./command-line-flags -word=opt -numb=7 -fork -svar=flag
 word: opt
 numb: 7
 fork: true
@@ -198,7 +212,7 @@ their default values.

-
$ ./command-line-flags -word=opt
+          
$ ./command-line-flags -word=opt
 word: opt
 numb: 42
 fork: false
@@ -217,7 +231,7 @@ any flags.

-
$ ./command-line-flags -word=opt a1 a2 a3
+          
$ ./command-line-flags -word=opt a1 a2 a3
 word: opt
 ...
 tail: [a1 a2 a3]
@@ -235,7 +249,7 @@ will be interpreted as positional arguments).

-
$ ./command-line-flags -word=opt a1 a2 a3 -numb=7
+          
$ ./command-line-flags -word=opt a1 a2 a3 -numb=7
 word: opt
 numb: 42
 fork: false
@@ -254,7 +268,7 @@ generated help text for the command-line program.

-
$ ./command-line-flags -h
+          
$ ./command-line-flags -h
 Usage of ./command-line-flags:
   -fork=false: a bool
   -numb=42: an int
@@ -274,7 +288,7 @@ and show the help text again.

-
$ ./command-line-flags -wat
+          
$ ./command-line-flags -wat
 flag provided but not defined: -wat
 Usage of ./command-line-flags:
 ...
@@ -294,5 +308,10 @@ and show the help text again.

by Mark McGranaghan | source | license

+ + diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 39b385b..f5add93 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

@@ -23,7 +37,7 @@ subcommands that have their own flags.

- + @@ -32,10 +46,8 @@ subcommands that have their own flags.

- - - -
package main
+            
+          
package main
 
@@ -47,7 +59,7 @@ subcommands that have their own flags.

-
import (
+          
import (
     "flag"
     "fmt"
     "os"
@@ -63,7 +75,7 @@ subcommands that have their own flags.

-
func main() {
+          
func main() {
 
@@ -78,7 +90,7 @@ for this subcommand.

-
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
+          
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
     fooEnable := fooCmd.Bool("enable", false, "enable")
     fooName := fooCmd.String("name", "", "name")
 
@@ -94,7 +106,7 @@ supported flags.

-
    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
+          
    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
     barLevel := barCmd.Int("level", 0, "level")
 
@@ -109,7 +121,7 @@ to the program.

-
    if len(os.Args) < 2 {
+          
    if len(os.Args) < 2 {
         fmt.Println("expected 'foo' or 'bar' subcommands")
         os.Exit(1)
     }
@@ -125,7 +137,7 @@ to the program.

-
    switch os.Args[1] {
+          
    switch os.Args[1] {
 
@@ -139,7 +151,7 @@ have access to trailing positional arguments.

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

-
$ go build command-line-subcommands.go 
+          
$ go build command-line-subcommands.go 
 
@@ -183,7 +195,7 @@ have access to trailing positional arguments.

-
$ ./command-line-subcommands foo -enable -name=joe a1 a2
+          
$ ./command-line-subcommands foo -enable -name=joe a1 a2
 subcommand 'foo'
   enable: true
   name: joe
@@ -200,7 +212,7 @@ have access to trailing positional arguments.

-
$ ./command-line-subcommands bar -level 8 a1
+          
$ ./command-line-subcommands bar -level 8 a1
 subcommand 'bar'
   level: 8
   tail: [a1]
@@ -216,7 +228,7 @@ have access to trailing positional arguments.

-
$ ./command-line-subcommands bar -enable a1
+          
$ ./command-line-subcommands bar -enable a1
 flag provided but not defined: -enable
 Usage of bar:
   -level int
@@ -234,7 +246,7 @@ way to parameterize programs.

- + @@ -249,5 +261,10 @@ way to parameterize programs.

by Mark McGranaghan | source | license

+ + diff --git a/public/constants b/public/constants index c564424..31e2c7b 100644 --- a/public/constants +++ b/public/constants @@ -5,6 +5,20 @@ Go by Example: Constants +

Go by Example: Constants

@@ -19,7 +33,7 @@ and numeric values.

- + @@ -28,10 +42,8 @@ and numeric values.

- - - -
package main
+            
+          
package main
 
@@ -43,8 +55,10 @@ and numeric values.

-
import "fmt"
-import "math"
+          
import (
+    "fmt"
+    "math"
+)
 
@@ -57,7 +71,7 @@ and numeric values.

-
const s string = "constant"
+          
const s string = "constant"
 
@@ -69,7 +83,7 @@ and numeric values.

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

-
    const n = 500000000
+          
    const n = 500000000
 
@@ -98,7 +112,7 @@ arbitrary precision.

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

-
    fmt.Println(int64(d))
+          
    fmt.Println(int64(d))
 
@@ -129,7 +143,7 @@ assignment or function call. For example, here -
    fmt.Println(math.Sin(n))
+          
    fmt.Println(math.Sin(n))
 }
 
@@ -146,7 +160,7 @@ assignment or function call. For example, here -
$ go run constant.go 
+          
$ go run constant.go 
 constant
 6e+11
 600000000000
@@ -167,5 +181,10 @@ assignment or function call. For example, here
         by Mark McGranaghan | source | license
       

+ + diff --git a/public/defer b/public/defer index 43445ec..f99d59d 100644 --- a/public/defer +++ b/public/defer @@ -5,6 +5,20 @@ Go by Example: Defer +

Go by Example: Defer

@@ -21,7 +35,7 @@ purposes of cleanup. defer is often used where e.g. - + @@ -30,10 +44,8 @@ purposes of cleanup. defer is often used where e.g. - - - -
package main
+            
+          
package main
 
@@ -45,8 +57,10 @@ purposes of cleanup. defer is often used where e.g. -
import "fmt"
-import "os"
+          
import (
+    "fmt"
+    "os"
+)
 
@@ -61,7 +75,7 @@ do that with defer.

-
func main() {
+          
func main() {
 
@@ -78,7 +92,7 @@ of the enclosing function (main), after -
    f := createFile("/tmp/defer.txt")
+          
    f := createFile("/tmp/defer.txt")
     defer closeFile(f)
     writeFile(f)
 }
@@ -93,7 +107,7 @@ of the enclosing function (main), after
           
           
             
-            
func createFile(p string) *os.File {
+          
func createFile(p string) *os.File {
     fmt.Println("creating")
     f, err := os.Create(p)
     if err != nil {
@@ -112,7 +126,7 @@ of the enclosing function (main), after
           
           
             
-            
func writeFile(f *os.File) {
+          
func writeFile(f *os.File) {
     fmt.Println("writing")
     fmt.Fprintln(f, "data")
 
@@ -126,7 +140,23 @@ of the enclosing function (main), after -
}
+          
}
+
+ + + + + + +

It’s 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()
 
@@ -138,9 +168,10 @@ of the enclosing function (main), after -
func closeFile(f *os.File) {
-    fmt.Println("closing")
-    f.Close()
+          
    if err != nil {
+        fmt.Fprintf(os.Stderr, "error: %v\n", err)
+        os.Exit(1)
+    }
 }
 
@@ -159,7 +190,7 @@ after being written.

-
$ go run defer.go
+          
$ go run defer.go
 creating
 writing
 closing
@@ -179,5 +210,10 @@ after being written.

by Mark McGranaghan | source | license

+ + diff --git a/public/directories b/public/directories new file mode 100644 index 0000000..5cfc5b0 --- /dev/null +++ b/public/directories @@ -0,0 +1,360 @@ + + + + + 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"
+    "path/filepath"
+)
+
+ +
+ + + +
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 with 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)
+
+ +
+

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
+}
+
+ +
+ + + + + + + + +
+ + + +
$ go run directories.go
+Listing subdir/parent
+  child true
+  file2 false
+  file3 false
+Listing subdir/parent/child
+  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
+
+ +
+ + +

+ Next example: Temporary Files and Directories. +

+ + +
+ + + + diff --git a/public/environment-variables b/public/environment-variables index 3d2e54c..25504ae 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -5,6 +5,20 @@ Go by Example: Environment Variables +

Go by Example: Environment Variables

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

- + @@ -30,10 +44,8 @@ Let’s look at how to set, get, and list environment variables.

- - - -
package main
+            
+          
package main
 
@@ -45,9 +57,11 @@ Let’s look at how to set, get, and list environment variables.

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

-
func main() {
+          
func main() {
 
@@ -75,7 +89,7 @@ environment.

-
    os.Setenv("FOO", "1")
+          
    os.Setenv("FOO", "1")
     fmt.Println("FOO:", os.Getenv("FOO"))
     fmt.Println("BAR:", os.Getenv("BAR"))
 
@@ -93,7 +107,7 @@ get the key and value. Here we print all the keys.

-
    fmt.Println()
+          
    fmt.Println()
     for _, e := range os.Environ() {
         pair := strings.Split(e, "=")
         fmt.Println(pair[0])
@@ -117,7 +131,7 @@ for FOO that we set in the program, but that
           
           
             
-            
$ go run environment-variables.go
+          
$ go run environment-variables.go
 FOO: 1
 BAR: 
 
@@ -133,7 +147,7 @@ particular machine.

-
TERM_PROGRAM
+          
TERM_PROGRAM
 PATH
 SHELL
 ...
@@ -150,7 +164,7 @@ program picks that value up.

-
$ BAR=2 go run environment-variables.go
+          
$ BAR=2 go run environment-variables.go
 FOO: 1
 BAR: 2
 ...
@@ -170,5 +184,10 @@ program picks that value up.

by Mark McGranaghan | source | license

+ + diff --git a/public/epoch b/public/epoch index 46d62e7..76a9b20 100644 --- a/public/epoch +++ b/public/epoch @@ -5,6 +5,20 @@ Go by Example: Epoch +

Go by Example: Epoch

@@ -21,7 +35,7 @@ Here’s how to do it in Go.

- + @@ -30,10 +44,8 @@ Here’s how to do it in Go.

- - - -
package main
+            
+          
package main
 
@@ -45,8 +57,10 @@ Here’s how to do it in Go.

-
import "fmt"
-import "time"
+          
import (
+    "fmt"
+    "time"
+)
 
@@ -58,7 +72,7 @@ Here’s how to do it in Go.

-
func main() {
+          
func main() {
 
@@ -73,7 +87,7 @@ nanoseconds, respectively.

-
    now := time.Now()
+          
    now := time.Now()
     secs := now.Unix()
     nanos := now.UnixNano()
     fmt.Println(now)
@@ -91,7 +105,7 @@ divide from nanoseconds.

-
    millis := nanos / 1000000
+          
    millis := nanos / 1000000
     fmt.Println(secs)
     fmt.Println(millis)
     fmt.Println(nanos)
@@ -108,7 +122,7 @@ since the epoch into the corresponding time.

-
    fmt.Println(time.Unix(secs, 0))
+          
    fmt.Println(time.Unix(secs, 0))
     fmt.Println(time.Unix(0, nanos))
 }
 
@@ -126,7 +140,7 @@ since the epoch into the corresponding time.

-
$ go run epoch.go 
+          
$ go run epoch.go 
 2012-10-31 16:13:58.292387 +0000 UTC
 1351700038
 1351700038292
@@ -146,7 +160,7 @@ parsing and formatting.

- + @@ -161,5 +175,10 @@ parsing and formatting.

by Mark McGranaghan | source | license

+ + diff --git a/public/errors b/public/errors index 489f119..351cb86 100644 --- a/public/errors +++ b/public/errors @@ -5,6 +5,20 @@ Go by Example: Errors +

Go by Example: Errors

@@ -25,7 +39,7 @@ non-error tasks.

- + @@ -34,10 +48,8 @@ non-error tasks.

- - - -
package main
+            
+          
package main
 
@@ -49,8 +61,10 @@ non-error tasks.

-
import "errors"
-import "fmt"
+          
import (
+    "errors"
+    "fmt"
+)
 
@@ -64,7 +78,7 @@ have type error, a built-in interface.

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

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

-
    }
+          
    }
 
@@ -105,7 +119,7 @@ there was no error.

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

-
type argError struct {
+          
type argError struct {
     arg  int
     prob string
 }
@@ -137,7 +151,7 @@ to explicitly represent an argument error.

-
func (e *argError) Error() string {
+          
func (e *argError) Error() string {
     return fmt.Sprintf("%d - %s", e.arg, e.prob)
 }
 
@@ -151,7 +165,7 @@ to explicitly represent an argument error.

-
func f2(arg int) (int, error) {
+          
func f2(arg int) (int, error) {
     if arg == 42 {
 
@@ -167,7 +181,7 @@ fields arg and prob.

-
        return -1, &argError{arg, "can't work with it"}
+          
        return -1, &argError{arg, "can't work with it"}
     }
     return arg + 3, nil
 }
@@ -182,7 +196,7 @@ fields arg and prob.

-
func main() {
+          
func main() {
 
@@ -198,7 +212,7 @@ idiom in Go code.

-
    for _, i := range []int{7, 42} {
+          
    for _, i := range []int{7, 42} {
         if r, e := f1(i); e != nil {
             fmt.Println("f1 failed:", e)
         } else {
@@ -227,7 +241,7 @@ assertion.

-
    _, e := f2(42)
+          
    _, e := f2(42)
     if ae, ok := e.(*argError); ok {
         fmt.Println(ae.arg)
         fmt.Println(ae.prob)
@@ -248,7 +262,7 @@ assertion.

-
$ go run errors.go
+          
$ go run errors.go
 f1 worked: 10
 f1 failed: can't work with 42
 f2 worked: 10
@@ -268,7 +282,7 @@ on the Go blog for more on error handling.

- + @@ -283,5 +297,10 @@ on the Go blog for more on error handling.

by Mark McGranaghan | source | license

+ + diff --git a/public/execing-processes b/public/execing-processes index 85b155d..98ce62a 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

@@ -26,7 +40,7 @@ function.

- + @@ -35,10 +49,8 @@ function.

- - - -
package main
+            
+          
package main
 
@@ -50,9 +62,11 @@ function.

-
import "syscall"
-import "os"
-import "os/exec"
+          
import (
+    "os"
+    "os/exec"
+    "syscall"
+)
 
@@ -64,7 +78,7 @@ function.

-
func main() {
+          
func main() {
 
@@ -80,7 +94,7 @@ we’ll use exec.LookPath to find it (probably -
    binary, lookErr := exec.LookPath("ls")
+          
    binary, lookErr := exec.LookPath("ls")
     if lookErr != nil {
         panic(lookErr)
     }
@@ -99,7 +113,7 @@ be the program name.

-
    args := []string{"ls", "-a", "-l", "-h"}
+          
    args := []string{"ls", "-a", "-l", "-h"}
 
@@ -114,7 +128,7 @@ environment.

-
    env := os.Environ()
+          
    env := os.Environ()
 
@@ -131,7 +145,7 @@ value.

-
    execErr := syscall.Exec(binary, args, env)
+          
    execErr := syscall.Exec(binary, args, env)
     if execErr != nil {
         panic(execErr)
     }
@@ -152,7 +166,7 @@ value.

-
$ go run execing-processes.go
+          
$ go run execing-processes.go
 total 16
 drwxr-xr-x  4 mark 136B Oct 3 16:29 .
 drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
@@ -172,7 +186,7 @@ processes covers most use cases for fork.

- + @@ -187,5 +201,10 @@ processes covers most use cases for fork.

by Mark McGranaghan | source | license

+ + diff --git a/public/exit b/public/exit index 4c6975d..5929eb6 100644 --- a/public/exit +++ b/public/exit @@ -5,6 +5,16 @@ Go by Example: Exit +

Go by Example: Exit

@@ -19,7 +29,7 @@ status.

- + @@ -28,10 +38,8 @@ status.

- - - -
package main
+            
+          
package main
 
@@ -43,8 +51,10 @@ status.

-
import "fmt"
-import "os"
+          
import (
+    "fmt"
+    "os"
+)
 
@@ -56,7 +66,7 @@ status.

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

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

-
    os.Exit(3)
+          
    os.Exit(3)
 }
 
@@ -100,7 +110,7 @@ use os.Exit.

- + @@ -116,7 +126,7 @@ will be picked up by go and printed.

-
$ go run exit.go
+          
$ go run exit.go
 exit status 3
 
@@ -131,7 +141,7 @@ the status in the terminal.

-
$ go build exit.go
+          
$ go build exit.go
 $ ./exit
 $ echo $?
 3
@@ -147,7 +157,7 @@ the status in the terminal.

- + @@ -158,5 +168,10 @@ the status in the terminal.

by Mark McGranaghan | source | license

+ + diff --git a/public/file-paths b/public/file-paths index 65e3886..2351954 100644 --- a/public/file-paths +++ b/public/file-paths @@ -5,6 +5,20 @@ Go by Example: File Paths +

Go by Example: File Paths

@@ -20,10 +34,8 @@ between operating systems; dir/file on Linux vs. - - - -
package main
+            
+          
package main
 
@@ -35,7 +47,7 @@ between operating systems; dir/file on Linux vs. -
import (
+          
import (
     "fmt"
     "path/filepath"
     "strings"
@@ -51,7 +63,7 @@ between operating systems; dir/file on Linux vs.
           
           
             
-            
func main() {
+          
func main() {
 
@@ -66,7 +78,7 @@ and constructs a hierarchical path from them.

-
    p := filepath.Join("dir1", "dir2", "filename")
+          
    p := filepath.Join("dir1", "dir2", "filename")
     fmt.Println("p:", p)
 
@@ -84,7 +96,7 @@ and directory changes.

-
    fmt.Println(filepath.Join("dir1//", "filename"))
+          
    fmt.Println(filepath.Join("dir1//", "filename"))
     fmt.Println(filepath.Join("dir1/../dir1", "filename"))
 
@@ -100,7 +112,7 @@ return both in the same call.

-
    fmt.Println("Dir(p):", filepath.Dir(p))
+          
    fmt.Println("Dir(p):", filepath.Dir(p))
     fmt.Println("Base(p):", filepath.Base(p))
 
@@ -114,7 +126,7 @@ return both in the same call.

-
    fmt.Println(filepath.IsAbs("dir/file"))
+          
    fmt.Println(filepath.IsAbs("dir/file"))
     fmt.Println(filepath.IsAbs("/dir/file"))
 
@@ -127,7 +139,7 @@ return both in the same call.

-
    filename := "config.json"
+          
    filename := "config.json"
 
@@ -141,7 +153,7 @@ can split the extension out of such names with Ext.

-
    ext := filepath.Ext(filename)
+          
    ext := filepath.Ext(filename)
     fmt.Println(ext)
 
@@ -156,7 +168,7 @@ use strings.TrimSuffix.

-
    fmt.Println(strings.TrimSuffix(filename, ext))
+          
    fmt.Println(strings.TrimSuffix(filename, ext))
 
@@ -171,7 +183,7 @@ be made relative to base.

-
    rel, err := filepath.Rel("a/b", "a/b/t/file")
+          
    rel, err := filepath.Rel("a/b", "a/b/t/file")
     if err != nil {
         panic(err)
     }
@@ -187,7 +199,7 @@ be made relative to base.

-
    rel, err = filepath.Rel("a/b", "a/c/t/file")
+          
    rel, err = filepath.Rel("a/b", "a/c/t/file")
     if err != nil {
         panic(err)
     }
@@ -208,7 +220,7 @@ be made relative to base.

-
$ go run file-paths.go
+          
$ go run file-paths.go
 p: dir1/dir2/filename
 dir1/filename
 dir1/filename
@@ -229,12 +241,17 @@ be made relative to base.

- Next example: Command-Line Arguments. + Next example: Directories.

+ + diff --git a/public/for b/public/for index 314f139..81b98d9 100644 --- a/public/for +++ b/public/for @@ -5,6 +5,20 @@ Go by Example: For +

Go by Example: For

@@ -19,7 +33,7 @@ three basic types of for loops.

- + @@ -28,10 +42,8 @@ three basic types of for loops.

- - - -
package main
+            
+          
package main
 
@@ -43,7 +55,7 @@ three basic types of for loops.

-
import "fmt"
+          
import "fmt"
 
@@ -55,7 +67,7 @@ three basic types of for loops.

-
func main() {
+          
func main() {
 
@@ -68,7 +80,7 @@ three basic types of for loops.

-
    i := 1
+          
    i := 1
     for i <= 3 {
         fmt.Println(i)
         i = i + 1
@@ -85,7 +97,7 @@ three basic types of for loops.

-
    for j := 7; j <= 9; j++ {
+          
    for j := 7; j <= 9; j++ {
         fmt.Println(j)
     }
 
@@ -102,7 +114,7 @@ the enclosing function.

-
    for {
+          
    for {
         fmt.Println("loop")
         break
     }
@@ -119,7 +131,7 @@ the loop.

-
    for n := 0; n <= 5; n++ {
+          
    for n := 0; n <= 5; n++ {
         if n%2 == 0 {
             continue
         }
@@ -141,7 +153,7 @@ the loop.

-
$ go run for.go
+          
$ go run for.go
 1
 2
 3
@@ -166,7 +178,7 @@ structures.

- + @@ -181,5 +193,10 @@ structures.

by Mark McGranaghan | source | license

+ + diff --git a/public/functions b/public/functions index 7c89d83..8880847 100644 --- a/public/functions +++ b/public/functions @@ -5,6 +5,20 @@ Go by Example: Functions +

Go by Example: Functions

@@ -19,7 +33,7 @@ functions with a few different examples.

- + @@ -28,10 +42,8 @@ functions with a few different examples.

- - - -
package main
+            
+          
package main
 
@@ -43,7 +55,7 @@ functions with a few different examples.

-
import "fmt"
+          
import "fmt"
 
@@ -57,7 +69,7 @@ their sum as an int.

-
func plus(a int, b int) int {
+          
func plus(a int, b int) int {
 
@@ -72,7 +84,7 @@ expression.

-
    return a + b
+          
    return a + b
 }
 
@@ -89,7 +101,7 @@ declares the type.

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

-
func main() {
+          
func main() {
 
@@ -117,7 +129,7 @@ declares the type.

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

-
    res = plusPlus(1, 2, 3)
+          
    res = plusPlus(1, 2, 3)
     fmt.Println("1+2+3 =", res)
 }
 
@@ -148,7 +160,7 @@ declares the type.

-
$ go run functions.go 
+          
$ go run functions.go 
 1+2 = 3
 1+2+3 = 6
 
@@ -164,7 +176,7 @@ multiple return values, which we’ll look at next.

- + @@ -179,5 +191,10 @@ multiple return values, which we’ll look at next.

by Mark McGranaghan | source | license

+ + diff --git a/public/goroutines b/public/goroutines index 40ba434..a7a4222 100644 --- a/public/goroutines +++ b/public/goroutines @@ -5,6 +5,20 @@ Go by Example: Goroutines +

Go by Example: Goroutines

@@ -18,7 +32,7 @@ - + @@ -27,10 +41,8 @@ - - - -
package main
+            
+          
package main
 
@@ -42,7 +54,7 @@ -
import "fmt"
+          
import "fmt"
 
@@ -54,7 +66,7 @@ -
func f(from string) {
+          
func f(from string) {
     for i := 0; i < 3; i++ {
         fmt.Println(from, ":", i)
     }
@@ -70,7 +82,7 @@
           
           
             
-            
func main() {
+          
func main() {
 
@@ -85,7 +97,7 @@ synchronously.

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

-
    go f("goroutine")
+          
    go f("goroutine")
 
@@ -114,7 +126,7 @@ function call.

-
    go func(msg string) {
+          
    go func(msg string) {
         fmt.Println(msg)
     }("going")
 
@@ -132,7 +144,7 @@ before the program exits.

-
    fmt.Scanln()
+          
    fmt.Scanln()
     fmt.Println("done")
 }
 
@@ -154,7 +166,7 @@ goroutines being run concurrently by the Go runtime.

-
$ go run goroutines.go
+          
$ go run goroutines.go
 direct : 0
 direct : 1
 direct : 2
@@ -177,7 +189,7 @@ concurrent Go programs: channels.

- + @@ -192,5 +204,10 @@ concurrent Go programs: channels.

by Mark McGranaghan | source | license

+ + diff --git a/public/hello-world b/public/hello-world index d8b1872..4c2373a 100644 --- a/public/hello-world +++ b/public/hello-world @@ -5,6 +5,16 @@ Go by Example: Hello World +

Go by Example: Hello World

@@ -18,10 +28,8 @@ message. Here’s the full source code.

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

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

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

-
$ go run hello-world.go
+          
$ go run hello-world.go
 hello world
 
@@ -80,7 +88,7 @@ binaries. We can do this using go build.

-
$ go build hello-world.go
+          
$ go build hello-world.go
 $ ls
 hello-world    hello-world.go
 
@@ -95,7 +103,7 @@ binaries. We can do this using go build.

-
$ ./hello-world
+          
$ ./hello-world
 hello world
 
@@ -110,7 +118,7 @@ learn more about the language.

- + @@ -125,5 +133,10 @@ learn more about the language.

by Mark McGranaghan | source | license

+ + diff --git a/public/http-clients b/public/http-clients index 5d5bf04..7bdaa06 100644 --- a/public/http-clients +++ b/public/http-clients @@ -5,6 +5,20 @@ Go by Example: HTTP Clients +

Go by Example: HTTP Clients

@@ -20,10 +34,8 @@ HTTP requests.

- - - -
package main
+            
+          
package main
 
@@ -35,7 +47,7 @@ HTTP requests.

-
import (
+          
import (
     "bufio"
     "fmt"
     "net/http"
@@ -51,7 +63,7 @@ HTTP requests.

-
func main() {
+          
func main() {
 
@@ -68,7 +80,7 @@ settings.

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

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

-
    scanner := bufio.NewScanner(resp.Body)
+          
    scanner := bufio.NewScanner(resp.Body)
     for i := 0; scanner.Scan() && i < 5; i++ {
         fmt.Println(scanner.Text())
     }
@@ -113,7 +125,7 @@ settings.

-
    if err := scanner.Err(); err != nil {
+          
    if err := scanner.Err(); err != nil {
         panic(err)
     }
 }
@@ -132,7 +144,7 @@ settings.

-
$ go run http-clients.go
+          
$ go run http-clients.go
 Response status: 200 OK
 <!DOCTYPE html>
 <html>
@@ -155,5 +167,10 @@ settings.

by Mark McGranaghan | source | license

+ + diff --git a/public/http-servers b/public/http-servers index 2dedf1a..aa2802d 100644 --- a/public/http-servers +++ b/public/http-servers @@ -5,6 +5,20 @@ Go by Example: HTTP Servers +

Go by Example: HTTP Servers

@@ -18,10 +32,8 @@ - - - -
package main
+            
+          
package main
 
@@ -33,7 +45,7 @@ -
import (
+          
import (
     "fmt"
     "net/http"
 )
@@ -53,7 +65,7 @@ on functions with the appropriate signature.

-
func hello(w http.ResponseWriter, req *http.Request) {
+          
func hello(w http.ResponseWriter, req *http.Request) {
 
@@ -64,13 +76,13 @@ 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”.

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

-
    for name, headers := range req.Header {
+          
    for name, headers := range req.Header {
         for _, h := range headers {
             fmt.Fprintf(w, "%v: %v\n", name, h)
         }
@@ -115,7 +127,7 @@ headers and echoing them into the response body.

-
func main() {
+          
func main() {
 
@@ -131,7 +143,7 @@ takes a function as an argument.

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

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

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

-
$ curl localhost:8090/hello
+          
$ curl localhost:8090/hello
 hello
 
@@ -196,5 +208,10 @@ router we’ve just set up.

by Mark McGranaghan | source | license

+ + diff --git a/public/if-else b/public/if-else index 2ed0680..f00d6b5 100644 --- a/public/if-else +++ b/public/if-else @@ -5,6 +5,20 @@ Go by Example: If/Else +

Go by Example: If/Else

@@ -19,7 +33,7 @@ straight-forward.

- + @@ -28,10 +42,8 @@ straight-forward.

- - - -
package main
+            
+          
package main
 
@@ -43,7 +55,7 @@ straight-forward.

-
import "fmt"
+          
import "fmt"
 
@@ -55,7 +67,7 @@ straight-forward.

-
func main() {
+          
func main() {
 
@@ -68,7 +80,7 @@ straight-forward.

-
    if 7%2 == 0 {
+          
    if 7%2 == 0 {
         fmt.Println("7 is even")
     } else {
         fmt.Println("7 is odd")
@@ -85,7 +97,7 @@ straight-forward.

-
    if 8%4 == 0 {
+          
    if 8%4 == 0 {
         fmt.Println("8 is divisible by 4")
     }
 
@@ -102,7 +114,7 @@ branches.

-
    if num := 9; num < 0 {
+          
    if num := 9; num < 0 {
         fmt.Println(num, "is negative")
     } else if num < 10 {
         fmt.Println(num, "has 1 digit")
@@ -123,7 +135,7 @@ in Go, but that the braces are required.

- + @@ -137,7 +149,7 @@ in Go, but that the braces are required.

-
$ go run if-else.go 
+          
$ go run if-else.go 
 7 is odd
 8 is divisible by 4
 9 has 1 digit
@@ -155,7 +167,7 @@ for basic conditions.

- + @@ -170,5 +182,10 @@ for basic conditions.

by Mark McGranaghan | source | license

+ + diff --git a/public/index.html b/public/index.html index ef6fe69..74ff261 100644 --- a/public/index.html +++ b/public/index.html @@ -119,6 +119,8 @@
  • JSON
  • +
  • XML
  • +
  • Time
  • Epoch
  • @@ -143,6 +145,10 @@
  • File Paths
  • +
  • Directories
  • + +
  • Temporary Files and Directories
  • +
  • Command-Line Arguments
  • Command-Line Flags
  • diff --git a/public/interfaces b/public/interfaces index 277c8f8..fad0ed0 100644 --- a/public/interfaces +++ b/public/interfaces @@ -5,6 +5,20 @@ Go by Example: Interfaces +

    Go by Example: Interfaces

    @@ -19,7 +33,7 @@ signatures.

    - + @@ -28,10 +42,8 @@ signatures.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,8 +55,10 @@ signatures.

    -
    import "fmt"
    -import "math"
    +          
    import (
    +    "fmt"
    +    "math"
    +)
     
    @@ -57,7 +71,7 @@ signatures.

    -
    type geometry interface {
    +          
    type geometry interface {
         area() float64
         perim() float64
     }
    @@ -74,7 +88,7 @@ signatures.

    -
    type rect struct {
    +          
    type rect struct {
         width, height float64
     }
     type circle struct {
    @@ -94,7 +108,7 @@ implement geometry on rects.

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

    -
    func (c circle) area() float64 {
    +          
    func (c circle) area() float64 {
         return math.Pi * c.radius * c.radius
     }
     func (c circle) perim() float64 {
    @@ -133,7 +147,7 @@ to work on any geometry.

    -
    func measure(g geometry) {
    +          
    func measure(g geometry) {
         fmt.Println(g)
         fmt.Println(g.area())
         fmt.Println(g.perim())
    @@ -149,7 +163,7 @@ to work on any geometry.

    -
    func main() {
    +          
    func main() {
         r := rect{width: 3, height: 4}
         c := circle{radius: 5}
     
    @@ -167,7 +181,7 @@ these structs as arguments to measure.

    -
        measure(r)
    +          
        measure(r)
         measure(c)
     }
     
    @@ -185,7 +199,7 @@ these structs as arguments to measure.

    -
    $ go run interfaces.go
    +          
    $ go run interfaces.go
     {3 4}
     12
     14
    @@ -205,7 +219,7 @@ these structs as arguments to measure.

    - + @@ -220,5 +234,10 @@ these structs as arguments to measure.

    by Mark McGranaghan | source | license

    + + diff --git a/public/json b/public/json index 54979d2..e2327ec 100644 --- a/public/json +++ b/public/json @@ -5,6 +5,20 @@ Go by Example: JSON +

    Go by Example: JSON

    @@ -20,7 +34,7 @@ data types.

    - + @@ -29,10 +43,8 @@ data types.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,9 +56,11 @@ data types.

    -
    import "encoding/json"
    -import "fmt"
    -import "os"
    +          
    import (
    +    "encoding/json"
    +    "fmt"
    +    "os"
    +)
     
    @@ -60,11 +74,24 @@ decoding of custom types below.

    -
    type response1 struct {
    +          
    type response1 struct {
         Page   int
         Fruits []string
     }
    -type response2 struct {
    +
    + + + + + + +

    Only exported fields will be encoded/decoded in JSON. +Fields must start with capital letters to be exported.

    + + + + +
    type response2 struct {
         Page   int      `json:"page"`
         Fruits []string `json:"fruits"`
     }
    @@ -79,7 +106,7 @@ decoding of custom types below.

    -
    func main() {
    +          
    func main() {
     
    @@ -94,7 +121,7 @@ values.

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

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

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

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

    -
        slcD := []string{"apple", "peach", "pear"}
    +          
        slcD := []string{"apple", "peach", "pear"}
         slcB, _ := json.Marshal(slcD)
         fmt.Println(string(slcB))
     
    @@ -162,7 +189,7 @@ to JSON arrays and objects as you’d expect.

    -
        mapD := map[string]int{"apple": 5, "lettuce": 7}
    +          
        mapD := map[string]int{"apple": 5, "lettuce": 7}
         mapB, _ := json.Marshal(mapD)
         fmt.Println(string(mapB))
     
    @@ -180,7 +207,7 @@ use those names as the JSON keys.

    -
        res1D := &response1{
    +          
        res1D := &response1{
             Page:   1,
             Fruits: []string{"apple", "peach", "pear"}}
         res1B, _ := json.Marshal(res1D)
    @@ -200,7 +227,7 @@ of such tags.

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

    -
        byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
    +          
        byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
     
    @@ -235,7 +262,7 @@ to arbitrary data types.

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

    -
        if err := json.Unmarshal(byt, &dat); err != nil {
    +          
        if err := json.Unmarshal(byt, &dat); err != nil {
             panic(err)
         }
         fmt.Println(dat)
    @@ -268,7 +295,7 @@ the expected float64 type.

    -
        num := dat["num"].(float64)
    +          
        num := dat["num"].(float64)
         fmt.Println(num)
     
    @@ -283,7 +310,7 @@ conversions.

    -
        strs := dat["strs"].([]interface{})
    +          
        strs := dat["strs"].([]interface{})
         str1 := strs[0].(string)
         fmt.Println(str1)
     
    @@ -302,7 +329,7 @@ data.

    -
        str := `{"page": 1, "fruits": ["apple", "peach"]}`
    +          
        str := `{"page": 1, "fruits": ["apple", "peach"]}`
         res := response2{}
         json.Unmarshal([]byte(str), &res)
         fmt.Println(res)
    @@ -323,7 +350,7 @@ stream JSON encodings directly to os.Writers like
               
               
                 
    -            
        enc := json.NewEncoder(os.Stdout)
    +          
        enc := json.NewEncoder(os.Stdout)
         d := map[string]int{"apple": 5, "lettuce": 7}
         enc.Encode(d)
     }
    @@ -342,7 +369,7 @@ stream JSON encodings directly to os.Writers like
               
               
                 
    -            
    $ go run json.go
    +          
    $ go run json.go
     true
     1
     2.34
    @@ -372,7 +399,7 @@ for more.

    - + @@ -380,12 +407,17 @@ for more.

    - Next example: Time. + Next example: XML.

    + + diff --git a/public/line-filters b/public/line-filters index d264214..f7796d0 100644 --- a/public/line-filters +++ b/public/line-filters @@ -5,6 +5,20 @@ Go by Example: Line Filters +

    Go by Example: Line Filters

    @@ -21,7 +35,7 @@ line filters.

    - + @@ -33,10 +47,8 @@ pattern to write your own Go line filters.

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

    -
    import (
    +          
    import (
         "bufio"
         "fmt"
         "os"
    @@ -65,7 +77,7 @@ pattern to write your own Go line filters.

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

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

    -
        for scanner.Scan() {
    +          
        for scanner.Scan() {
     
    @@ -107,7 +119,7 @@ from the input.

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

    -
            fmt.Println(ucl)
    +          
            fmt.Println(ucl)
         }
     
    @@ -135,7 +147,7 @@ expected and not reported by Scan as an error.

    -
        if err := scanner.Err(); err != nil {
    +          
        if err := scanner.Err(); err != nil {
             fmt.Fprintln(os.Stderr, "error:", err)
             os.Exit(1)
         }
    @@ -157,7 +169,7 @@ lowercase lines.

    -
    $ echo 'hello'   > /tmp/lines
    +          
    $ echo 'hello'   > /tmp/lines
     $ echo 'filter' >> /tmp/lines
     
    @@ -171,7 +183,7 @@ lowercase lines.

    -
    $ cat /tmp/lines | go run line-filters.go
    +          
    $ cat /tmp/lines | go run line-filters.go
     HELLO
     FILTER
     
    @@ -190,5 +202,10 @@ lowercase lines.

    by Mark McGranaghan | source | license

    + + diff --git a/public/maps b/public/maps index bf31208..443efd7 100644 --- a/public/maps +++ b/public/maps @@ -5,6 +5,20 @@ Go by Example: Maps +

    Go by Example: Maps

    @@ -19,7 +33,7 @@ - + @@ -28,10 +42,8 @@ - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,7 +55,7 @@ -
    import "fmt"
    +          
    import "fmt"
     
    @@ -55,7 +67,7 @@ -
    func main() {
    +          
    func main() {
     
    @@ -69,7 +81,7 @@ -
        m := make(map[string]int)
    +          
        m := make(map[string]int)
     
    @@ -83,7 +95,7 @@ syntax.

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

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

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

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

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

    -
        n := map[string]int{"foo": 1, "bar": 2}
    +          
        n := map[string]int{"foo": 1, "bar": 2}
         fmt.Println("map:", n)
     }
     
    @@ -195,7 +207,7 @@ printed with fmt.Println.

    -
    $ go run maps.go 
    +          
    $ go run maps.go 
     map: map[k1:7 k2:13]
     v1:  7
     len: 2
    @@ -218,5 +230,10 @@ printed with fmt.Println.

    by Mark McGranaghan | source | license

    + + diff --git a/public/methods b/public/methods index c1ae6d0..ca0589a 100644 --- a/public/methods +++ b/public/methods @@ -5,6 +5,20 @@ Go by Example: Methods +

    Go by Example: Methods

    @@ -18,7 +32,7 @@ - + @@ -27,10 +41,8 @@ - - - -
    package main
    +            
    +          
    package main
     
    @@ -42,7 +54,7 @@ -
    import "fmt"
    +          
    import "fmt"
     
    @@ -54,7 +66,7 @@ -
    type rect struct {
    +          
    type rect struct {
         width, height int
     }
     
    @@ -69,7 +81,7 @@ -
    func (r *rect) area() int {
    +          
    func (r *rect) area() int {
         return r.width * r.height
     }
     
    @@ -85,7 +97,7 @@ receiver types. Here’s an example of a value receiver.

    -
    func (r rect) perim() int {
    +          
    func (r rect) perim() int {
         return 2*r.width + 2*r.height
     }
     
    @@ -99,7 +111,7 @@ receiver types. Here’s an example of a value receiver.

    -
    func main() {
    +          
    func main() {
         r := rect{width: 10, height: 5}
     
    @@ -113,7 +125,7 @@ receiver types. Here’s an example of a value receiver.

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

    -
        rp := &r
    +          
        rp := &r
         fmt.Println("area: ", rp.area())
         fmt.Println("perim:", rp.perim())
     }
    @@ -150,7 +162,7 @@ receiving struct.

    -
    $ go run methods.go 
    +          
    $ go run methods.go 
     area:  50
     perim: 30
     area:  50
    @@ -168,7 +180,7 @@ naming related sets of methods: interfaces.

    - + @@ -183,5 +195,10 @@ naming related sets of methods: interfaces.

    by Mark McGranaghan | source | license

    + + diff --git a/public/multiple-return-values b/public/multiple-return-values index 5392875..bd16bd1 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

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

    - + @@ -29,10 +43,8 @@ to return both result and error values from a function.

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

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -58,7 +70,7 @@ the function returns 2 ints.

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

    -
    func main() {
    +          
    func main() {
     
    @@ -86,7 +98,7 @@ call with multiple assignment.

    -
        a, b := vals()
    +          
        a, b := vals()
         fmt.Println(a)
         fmt.Println(b)
     
    @@ -102,7 +114,7 @@ use the blank identifier _.

    -
        _, c := vals()
    +          
        _, c := vals()
         fmt.Println(c)
     }
     
    @@ -120,7 +132,7 @@ use the blank identifier _.

    -
    $ go run multiple-return-values.go
    +          
    $ go run multiple-return-values.go
     3
     7
     7
    @@ -137,7 +149,7 @@ feature of Go functions; we’ll look at this next.

    - + @@ -152,5 +164,10 @@ feature of Go functions; we’ll look at this next.

    by Mark McGranaghan | source | license

    + + diff --git a/public/mutexes b/public/mutexes index efc2253..14d8137 100644 --- a/public/mutexes +++ b/public/mutexes @@ -5,6 +5,20 @@ Go by Example: Mutexes +

    Go by Example: Mutexes

    @@ -21,7 +35,7 @@ to safely access data across multiple goroutines.

    - + @@ -30,10 +44,8 @@ to safely access data across multiple goroutines.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,7 +57,7 @@ to safely access data across multiple goroutines.

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

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

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

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

    -
        var readOps uint64
    +          
        var readOps uint64
         var writeOps uint64
     
    @@ -119,7 +131,7 @@ each goroutine.

    -
        for r := 0; r < 100; r++ {
    +          
        for r := 0; r < 100; r++ {
             go func() {
                 total := 0
                 for {
    @@ -140,7 +152,7 @@ the readOps count.

    -
                    key := rand.Intn(5)
    +          
                    key := rand.Intn(5)
                     mutex.Lock()
                     total += state[key]
                     mutex.Unlock()
    @@ -157,7 +169,7 @@ the readOps count.

    -
                    time.Sleep(time.Millisecond)
    +          
                    time.Sleep(time.Millisecond)
                 }
             }()
         }
    @@ -174,7 +186,7 @@ using the same pattern we did for reads.

    -
        for w := 0; w < 10; w++ {
    +          
        for w := 0; w < 10; w++ {
             go func() {
                 for {
                     key := rand.Intn(5)
    @@ -200,7 +212,7 @@ using the same pattern we did for reads.

    -
        time.Sleep(time.Second)
    +          
        time.Sleep(time.Second)
     
    @@ -213,7 +225,7 @@ using the same pattern we did for reads.

    -
        readOpsFinal := atomic.LoadUint64(&readOps)
    +          
        readOpsFinal := atomic.LoadUint64(&readOps)
         fmt.Println("readOps:", readOpsFinal)
         writeOpsFinal := atomic.LoadUint64(&writeOps)
         fmt.Println("writeOps:", writeOpsFinal)
    @@ -229,7 +241,7 @@ using the same pattern we did for reads.

    -
        mutex.Lock()
    +          
        mutex.Lock()
         fmt.Println("state:", state)
         mutex.Unlock()
     }
    @@ -251,7 +263,7 @@ using the same pattern we did for reads.

    -
    $ go run mutexes.go
    +          
    $ go run mutexes.go
     readOps: 83285
     writeOps: 8320
     state: map[1:97 4:53 0:33 2:15 3:2]
    @@ -268,7 +280,7 @@ management task using only goroutines and channels.

    - + @@ -283,5 +295,10 @@ management task using only goroutines and channels.

    by Mark McGranaghan | source | license

    + + diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index ada60a3..bbe6d55 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

    @@ -21,7 +35,7 @@ non-blocking multi-way selects.

    - + @@ -30,10 +44,8 @@ non-blocking multi-way selects.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,7 +57,7 @@ non-blocking multi-way selects.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -57,7 +69,7 @@ non-blocking multi-way selects.

    -
    func main() {
    +          
    func main() {
         messages := make(chan string)
         signals := make(chan bool)
     
    @@ -75,7 +87,7 @@ it will immediately take the default case.

    -
        select {
    +          
        select {
         case msg := <-messages:
             fmt.Println("received message", msg)
         default:
    @@ -96,7 +108,7 @@ Therefore the default case is selected.

    -
        msg := "hi"
    +          
        msg := "hi"
         select {
         case messages <- msg:
             fmt.Println("sent message", msg)
    @@ -118,7 +130,7 @@ on both messages and signals.

    -
        select {
    +          
        select {
         case msg := <-messages:
             fmt.Println("received message", msg)
         case sig := <-signals:
    @@ -142,7 +154,7 @@ on both messages and signals.

    -
    $ go run non-blocking-channel-operations.go 
    +          
    $ go run non-blocking-channel-operations.go 
     no message received
     no message sent
     no activity
    @@ -162,5 +174,10 @@ on both messages and signals.

    by Mark McGranaghan | source | license

    + + diff --git a/public/number-parsing b/public/number-parsing index 35e768e..269da85 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -5,6 +5,20 @@ Go by Example: Number Parsing +

    Go by Example: Number Parsing

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

    - + @@ -28,10 +42,8 @@ in many programs; here’s how to do it in Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,8 +57,10 @@ parsing.

    -
    import "strconv"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "strconv"
    +)
     
    @@ -58,7 +72,7 @@ parsing.

    -
    func main() {
    +          
    func main() {
     
    @@ -72,7 +86,7 @@ precision to parse.

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

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

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

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

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

    -
        _, e := strconv.Atoi("wat")
    +          
        _, e := strconv.Atoi("wat")
         fmt.Println(e)
     }
     
    @@ -163,7 +177,7 @@ bits.

    -
    $ go run number-parsing.go 
    +          
    $ go run number-parsing.go 
     1.234
     123
     456
    @@ -182,7 +196,7 @@ bits.

    - + @@ -197,5 +211,10 @@ bits.

    by Mark McGranaghan | source | license

    + + diff --git a/public/panic b/public/panic index 59198af..6a9b834 100644 --- a/public/panic +++ b/public/panic @@ -5,6 +5,20 @@ Go by Example: Panic +

    Go by Example: Panic

    @@ -21,7 +35,7 @@ aren’t prepared to handle gracefully.

    - + @@ -30,10 +44,8 @@ aren’t prepared to handle gracefully.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,7 +57,7 @@ aren’t prepared to handle gracefully.

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

    -
    func main() {
    +          
    func main() {
     
    @@ -72,7 +84,7 @@ site designed to panic.

    -
        panic("a problem")
    +          
        panic("a problem")
     
    @@ -88,7 +100,7 @@ returns an error value that we don’t know how to -
        _, err := os.Create("/tmp/file")
    +          
        _, err := os.Create("/tmp/file")
         if err != nil {
             panic(err)
         }
    @@ -111,7 +123,7 @@ a non-zero status.

    -
    $ go run panic.go
    +          
    $ go run panic.go
     panic: a problem
     
    @@ -124,7 +136,7 @@ a non-zero status.

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

    - + @@ -158,5 +170,10 @@ to use error-indicating return values wherever possible.

    by Mark McGranaghan | source | license

    + + diff --git a/public/pointers b/public/pointers index 16687f5..4d10527 100644 --- a/public/pointers +++ b/public/pointers @@ -5,6 +5,20 @@ Go by Example: Pointers +

    Go by Example: Pointers

    @@ -20,7 +34,7 @@ within your program.

    - + @@ -29,10 +43,8 @@ within your program.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ within your program.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -61,7 +73,7 @@ from the one in the calling function.

    -
    func zeroval(ival int) {
    +          
    func zeroval(ival int) {
         ival = 0
     }
     
    @@ -81,7 +93,7 @@ value at the referenced address.

    -
    func zeroptr(iptr *int) {
    +          
    func zeroptr(iptr *int) {
         *iptr = 0
     }
     
    @@ -95,7 +107,7 @@ value at the referenced address.

    -
    func main() {
    +          
    func main() {
         i := 1
         fmt.Println("initial:", i)
     
    @@ -109,7 +121,7 @@ value at the referenced address.

    -
        zeroval(i)
    +          
        zeroval(i)
         fmt.Println("zeroval:", i)
     
    @@ -124,7 +136,7 @@ i.e. a pointer to i.

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

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

    -
    $ go run pointers.go
    +          
    $ go run pointers.go
     initial: 1
     zeroval: 1
     zeroptr: 0
    @@ -179,5 +191,10 @@ the memory address for that variable.

    by Mark McGranaghan | source | license

    + + diff --git a/public/random-numbers b/public/random-numbers index 5de950f..d3685c5 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -5,6 +5,20 @@ Go by Example: Random Numbers +

    Go by Example: Random Numbers

    @@ -20,7 +34,7 @@ generation.

    - + @@ -29,10 +43,8 @@ generation.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,9 +56,11 @@ generation.

    -
    import "time"
    -import "fmt"
    -import "math/rand"
    +          
    import (
    +    "fmt"
    +    "math/rand"
    +    "time"
    +)
     
    @@ -58,7 +72,7 @@ generation.

    -
    func main() {
    +          
    func main() {
     
    @@ -72,7 +86,7 @@ generation.

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

    -
        fmt.Println(rand.Float64())
    +          
        fmt.Println(rand.Float64())
     
    @@ -102,7 +116,7 @@ other ranges, for example 5.0 <= f' < 10.0.

    -
        fmt.Print((rand.Float64()*5)+5, ",")
    +          
        fmt.Print((rand.Float64()*5)+5, ",")
         fmt.Print((rand.Float64() * 5) + 5)
         fmt.Println()
     
    @@ -121,7 +135,7 @@ intend to be secret, use crypto/rand for those.

    -
        s1 := rand.NewSource(time.Now().UnixNano())
    +          
        s1 := rand.NewSource(time.Now().UnixNano())
         r1 := rand.New(s1)
     
    @@ -136,7 +150,7 @@ functions on the rand package.

    -
        fmt.Print(r1.Intn(100), ",")
    +          
        fmt.Print(r1.Intn(100), ",")
         fmt.Print(r1.Intn(100))
         fmt.Println()
     
    @@ -152,7 +166,7 @@ produces the same sequence of random numbers.

    -
        s2 := rand.NewSource(42)
    +          
        s2 := rand.NewSource(42)
         r2 := rand.New(s2)
         fmt.Print(r2.Intn(100), ",")
         fmt.Print(r2.Intn(100))
    @@ -177,7 +191,7 @@ produces the same sequence of random numbers.

    -
    $ go run random-numbers.go
    +          
    $ go run random-numbers.go
     81,87
     0.6645600532184904
     7.123187485356329,8.434115364335547
    @@ -198,7 +212,7 @@ that Go can provide.

    - + @@ -213,5 +227,10 @@ that Go can provide.

    by Mark McGranaghan | source | license

    + + diff --git a/public/range b/public/range index e9aa99e..f09b0c7 100644 --- a/public/range +++ b/public/range @@ -5,6 +5,20 @@ Go by Example: Range +

    Go by Example: Range

    @@ -20,7 +34,7 @@ of the data structures we’ve already learned.

    - + @@ -29,10 +43,8 @@ of the data structures we’ve already learned.

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

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

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

    -
        nums := []int{2, 3, 4}
    +          
        nums := []int{2, 3, 4}
         sum := 0
         for _, num := range nums {
             sum += num
    @@ -92,7 +104,7 @@ the indexes though.

    -
        for i, num := range nums {
    +          
        for i, num := range nums {
             if num == 3 {
                 fmt.Println("index:", i)
             }
    @@ -109,7 +121,7 @@ the indexes though.

    -
        kvs := map[string]string{"a": "apple", "b": "banana"}
    +          
        kvs := map[string]string{"a": "apple", "b": "banana"}
         for k, v := range kvs {
             fmt.Printf("%s -> %s\n", k, v)
         }
    @@ -125,7 +137,7 @@ the indexes though.

    -
        for k := range kvs {
    +          
        for k := range kvs {
             fmt.Println("key:", k)
         }
     
    @@ -142,7 +154,7 @@ of the rune and the second the rune itself.

    -
        for i, c := range "go" {
    +          
        for i, c := range "go" {
             fmt.Println(i, c)
         }
     }
    @@ -161,7 +173,7 @@ of the rune and the second the rune itself.

    -
    $ go run range.go
    +          
    $ go run range.go
     sum: 9
     index: 1
     a -> apple
    @@ -186,5 +198,10 @@ of the rune and the second the rune itself.

    by Mark McGranaghan | source | license

    + + diff --git a/public/range-over-channels b/public/range-over-channels index a3ba422..1b7354c 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

    @@ -21,7 +35,7 @@ values received from a channel.

    - + @@ -30,10 +44,8 @@ values received from a channel.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,7 +57,7 @@ values received from a channel.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -57,7 +69,7 @@ values received from a channel.

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

    -
        queue := make(chan string, 2)
    +          
        queue := make(chan string, 2)
         queue <- "one"
         queue <- "two"
         close(queue)
    @@ -89,7 +101,7 @@ receiving the 2 elements.

    -
        for elem := range queue {
    +          
        for elem := range queue {
             fmt.Println(elem)
         }
     }
    @@ -108,7 +120,7 @@ receiving the 2 elements.

    -
    $ go run range-over-channels.go
    +          
    $ go run range-over-channels.go
     one
     two
     
    @@ -125,7 +137,7 @@ values be received.

    - + @@ -140,5 +152,10 @@ values be received.

    by Mark McGranaghan | source | license

    + + diff --git a/public/rate-limiting b/public/rate-limiting index 07dc185..33dd251 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -5,6 +5,20 @@ Go by Example: Rate Limiting +

    Go by Example: Rate Limiting

    @@ -22,7 +36,7 @@ channels, and tickers.

    - + @@ -31,10 +45,8 @@ channels, and tickers.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -46,8 +58,10 @@ channels, and tickers.

    -
    import "time"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -59,7 +73,7 @@ channels, and tickers.

    -
    func main() {
    +          
    func main() {
     
    @@ -75,7 +89,7 @@ same name.

    -
        requests := make(chan int, 5)
    +          
        requests := make(chan int, 5)
         for i := 1; i <= 5; i++ {
             requests <- i
         }
    @@ -94,7 +108,7 @@ our rate limiting scheme.

    -
        limiter := time.Tick(200 * time.Millisecond)
    +          
        limiter := time.Tick(200 * time.Millisecond)
     
    @@ -109,7 +123,7 @@ before serving each request, we limit ourselves to -
        for req := range requests {
    +          
        for req := range requests {
             <-limiter
             fmt.Println("request", req, time.Now())
         }
    @@ -129,7 +143,7 @@ channel will allow bursts of up to 3 events.

    -
        burstyLimiter := make(chan time.Time, 3)
    +          
        burstyLimiter := make(chan time.Time, 3)
     
    @@ -142,7 +156,7 @@ channel will allow bursts of up to 3 events.

    -
        for i := 0; i < 3; i++ {
    +          
        for i := 0; i < 3; i++ {
             burstyLimiter <- time.Now()
         }
     
    @@ -158,7 +172,7 @@ value to burstyLimiter, up to its limit of 3.

    -
        go func() {
    +          
        go func() {
             for t := range time.Tick(200 * time.Millisecond) {
                 burstyLimiter <- t
             }
    @@ -177,7 +191,7 @@ of burstyLimiter.

    -
        burstyRequests := make(chan int, 5)
    +          
        burstyRequests := make(chan int, 5)
         for i := 1; i <= 5; i++ {
             burstyRequests <- i
         }
    @@ -204,7 +218,7 @@ handled once every ~200 milliseconds as desired.

    -
    $ go run rate-limiting.go
    +          
    $ 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
     request 3 2012-10-19 00:38:19.087238 +0000 UTC
    @@ -224,7 +238,7 @@ then serve the remaining 2 with ~200ms delays each.

    -
    request 1 2012-10-19 00:38:20.487578 +0000 UTC
    +          
    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
     request 4 2012-10-19 00:38:20.687483 +0000 UTC
    @@ -245,5 +259,10 @@ then serve the remaining 2 with ~200ms delays each.

    by Mark McGranaghan | source | license

    + + diff --git a/public/reading-files b/public/reading-files index d51206c..5f87bee 100644 --- a/public/reading-files +++ b/public/reading-files @@ -5,6 +5,20 @@ Go by Example: Reading Files +

    Go by Example: Reading Files

    @@ -20,7 +34,7 @@ reading files.

    - + @@ -29,10 +43,8 @@ reading files.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ reading files.

    -
    import (
    +          
    import (
         "bufio"
         "fmt"
         "io"
    @@ -64,7 +76,7 @@ This helper will streamline our error checks below.

    -
    func check(e error) {
    +          
    func check(e error) {
         if e != nil {
             panic(e)
         }
    @@ -80,7 +92,7 @@ This helper will streamline our error checks below.

    -
    func main() {
    +          
    func main() {
     
    @@ -94,7 +106,7 @@ slurping a file’s entire contents into memory.

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

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

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

    -
        o2, err := f.Seek(6, 0)
    +          
        o2, err := f.Seek(6, 0)
         check(err)
         b2 := make([]byte, 2)
         n2, err := f.Read(b2)
    @@ -166,7 +178,7 @@ implemented with ReadAtLeast.

    -
        o3, err := f.Seek(6, 0)
    +          
        o3, err := f.Seek(6, 0)
         check(err)
         b3 := make([]byte, 2)
         n3, err := io.ReadAtLeast(f, b3, 2)
    @@ -185,7 +197,7 @@ accomplishes this.

    -
        _, err = f.Seek(0, 0)
    +          
        _, err = f.Seek(0, 0)
         check(err)
     
    @@ -202,7 +214,7 @@ reading methods it provides.

    -
        r4 := bufio.NewReader(f)
    +          
        r4 := bufio.NewReader(f)
         b4, err := r4.Peek(5)
         check(err)
         fmt.Printf("5 bytes: %s\n", string(b4))
    @@ -220,7 +232,7 @@ be scheduled immediately after Opening with
               
               
                 
    -            
        f.Close()
    +          
        f.Close()
     }
     
    @@ -237,7 +249,7 @@ be scheduled immediately after Opening with -
    $ echo "hello" > /tmp/dat
    +          
    $ echo "hello" > /tmp/dat
     $ echo "go" >>   /tmp/dat
     $ go run reading-files.go
     hello
    @@ -258,7 +270,7 @@ be scheduled immediately after Opening with
               
               
                 
    -            
    +          
               
             
             
    @@ -273,5 +285,10 @@ be scheduled immediately after Opening with
             by Mark McGranaghan | source | license
           

    + + diff --git a/public/recursion b/public/recursion index bedbf2f..215d30d 100644 --- a/public/recursion +++ b/public/recursion @@ -5,6 +5,20 @@ Go by Example: Recursion +

    Go by Example: Recursion

    @@ -20,7 +34,7 @@ Here’s a classic factorial example.

    - + @@ -29,10 +43,8 @@ Here’s a classic factorial example.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ Here’s a classic factorial example.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -58,7 +70,7 @@ base case of fact(0).

    -
    func fact(n int) int {
    +          
    func fact(n int) int {
         if n == 0 {
             return 1
         }
    @@ -75,7 +87,7 @@ base case of fact(0).

    -
    func main() {
    +          
    func main() {
         fmt.Println(fact(7))
     }
     
    @@ -93,7 +105,7 @@ base case of fact(0).

    -
    $ go run recursion.go 
    +          
    $ go run recursion.go 
     5040
     
    @@ -111,5 +123,10 @@ base case of fact(0).

    by Mark McGranaghan | source | license

    + + diff --git a/public/regular-expressions b/public/regular-expressions index 8db2fbd..76529e3 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -5,6 +5,20 @@ Go by Example: Regular Expressions +

    Go by Example: Regular Expressions

    @@ -20,7 +34,7 @@ in Go.

    - + @@ -29,10 +43,8 @@ in Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,9 +56,11 @@ in Go.

    -
    import "bytes"
    -import "fmt"
    -import "regexp"
    +          
    import (
    +    "bytes"
    +    "fmt"
    +    "regexp"
    +)
     
    @@ -58,7 +72,7 @@ in Go.

    -
    func main() {
    +          
    func main() {
     
    @@ -71,7 +85,7 @@ in Go.

    -
        match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
    +          
        match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
         fmt.Println(match)
     
    @@ -87,7 +101,7 @@ optimized Regexp struct.

    -
        r, _ := regexp.Compile("p([a-z]+)ch")
    +          
        r, _ := regexp.Compile("p([a-z]+)ch")
     
    @@ -101,7 +115,7 @@ a match test like we saw earlier.

    -
        fmt.Println(r.MatchString("peach"))
    +          
        fmt.Println(r.MatchString("peach"))
     
    @@ -114,7 +128,7 @@ a match test like we saw earlier.

    -
        fmt.Println(r.FindString("peach punch"))
    +          
        fmt.Println(r.FindString("peach punch"))
     
    @@ -129,7 +143,7 @@ matching text.

    -
        fmt.Println(r.FindStringIndex("peach punch"))
    +          
        fmt.Println(r.FindStringIndex("peach punch"))
     
    @@ -145,7 +159,7 @@ information for both p([a-z]+)ch and ([a-z]+).

    -
        fmt.Println(r.FindStringSubmatch("peach punch"))
    +          
        fmt.Println(r.FindStringSubmatch("peach punch"))
     
    @@ -159,7 +173,7 @@ indexes of matches and submatches.

    -
        fmt.Println(r.FindStringSubmatchIndex("peach punch"))
    +          
        fmt.Println(r.FindStringSubmatchIndex("peach punch"))
     
    @@ -174,7 +188,7 @@ example to find all matches for a regexp.

    -
        fmt.Println(r.FindAllString("peach punch pinch", -1))
    +          
        fmt.Println(r.FindAllString("peach punch pinch", -1))
     
    @@ -188,7 +202,7 @@ functions we saw above as well.

    -
        fmt.Println(r.FindAllStringSubmatchIndex(
    +          
        fmt.Println(r.FindAllStringSubmatchIndex(
             "peach punch pinch", -1))
     
    @@ -204,7 +218,7 @@ of matches.

    -
        fmt.Println(r.FindAllString("peach punch pinch", 2))
    +          
        fmt.Println(r.FindAllString("peach punch pinch", 2))
     
    @@ -220,7 +234,7 @@ function name.

    -
        fmt.Println(r.Match([]byte("peach")))
    +          
        fmt.Println(r.Match([]byte("peach")))
     
    @@ -236,7 +250,7 @@ constants because it has 2 return values.

    -
        r = regexp.MustCompile("p([a-z]+)ch")
    +          
        r = regexp.MustCompile("p([a-z]+)ch")
         fmt.Println(r)
     
    @@ -251,7 +265,7 @@ subsets of strings with other values.

    -
        fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
    +          
        fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
     
    @@ -265,7 +279,7 @@ text with a given function.

    -
        in := []byte("a peach")
    +          
        in := []byte("a peach")
         out := r.ReplaceAllFunc(in, bytes.ToUpper)
         fmt.Println(string(out))
     }
    @@ -284,7 +298,7 @@ text with a given function.

    -
    $ go run regular-expressions.go 
    +          
    $ go run regular-expressions.go 
     true
     true
     peach
    @@ -311,7 +325,7 @@ the regexp package docs
               
               
                 
    -            
    +          
               
             
             
    @@ -326,5 +340,10 @@ the regexp package docs
             by Mark McGranaghan | source | license
           

    + + diff --git a/public/select b/public/select index d6733a1..116ac3b 100644 --- a/public/select +++ b/public/select @@ -5,6 +5,20 @@ Go by Example: Select +

    Go by Example: Select

    @@ -20,7 +34,7 @@ select is a powerful feature of Go.

    - + @@ -29,10 +43,8 @@ select is a powerful feature of Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,8 +56,10 @@ select is a powerful feature of Go.

    -
    import "time"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -57,7 +71,7 @@ select is a powerful feature of Go.

    -
    func main() {
    +          
    func main() {
     
    @@ -70,7 +84,7 @@ select is a powerful feature of Go.

    -
        c1 := make(chan string)
    +          
        c1 := make(chan string)
         c2 := make(chan string)
     
    @@ -86,7 +100,7 @@ executing in concurrent goroutines.

    -
        go func() {
    +          
        go func() {
             time.Sleep(1 * time.Second)
             c1 <- "one"
         }()
    @@ -107,7 +121,7 @@ simultaneously, printing each one as it arrives.

    -
        for i := 0; i < 2; i++ {
    +          
        for i := 0; i < 2; i++ {
             select {
             case msg1 := <-c1:
                 fmt.Println("received", msg1)
    @@ -133,7 +147,7 @@ expected.

    -
    $ time go run select.go 
    +          
    $ time go run select.go 
     received one
     received two
     
    @@ -150,7 +164,7 @@ concurrently.

    -
    real    0m2.245s
    +          
    real    0m2.245s
     
    @@ -167,5 +181,10 @@ concurrently.

    by Mark McGranaghan | source | license

    + + diff --git a/public/sha1-hashes b/public/sha1-hashes index c28cf1d..4db0375 100644 --- a/public/sha1-hashes +++ b/public/sha1-hashes @@ -5,6 +5,20 @@ Go by Example: SHA1 Hashes +

    Go by Example: SHA1 Hashes

    @@ -23,7 +37,7 @@ compute SHA1 hashes in Go.

    - + @@ -32,10 +46,8 @@ compute SHA1 hashes in Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -49,8 +61,10 @@ compute SHA1 hashes in Go.

    -
    import "crypto/sha1"
    -import "fmt"
    +          
    import (
    +    "crypto/sha1"
    +    "fmt"
    +)
     
    @@ -62,7 +76,7 @@ compute SHA1 hashes in Go.

    -
    func main() {
    +          
    func main() {
         s := "sha1 this string"
     
    @@ -78,7 +92,7 @@ Here we start with a new hash.

    -
        h := sha1.New()
    +          
        h := sha1.New()
     
    @@ -92,7 +106,7 @@ use []byte(s) to coerce it to bytes.

    -
        h.Write([]byte(s))
    +          
        h.Write([]byte(s))
     
    @@ -107,7 +121,7 @@ to an existing byte slice: it usually isn’t needed.

    -
        bs := h.Sum(nil)
    +          
        bs := h.Sum(nil)
     
    @@ -122,7 +136,7 @@ a hash results to a hex string.

    -
        fmt.Println(s)
    +          
        fmt.Println(s)
         fmt.Printf("%x\n", bs)
     }
     
    @@ -142,7 +156,7 @@ a human-readable hex format.

    -
    $ go run sha1-hashes.go
    +          
    $ go run sha1-hashes.go
     sha1 this string
     cf23df2207d99a74fbe169e3eba035e633b65d94
     
    @@ -159,7 +173,7 @@ import crypto/md5 and use md5.New().

    - + @@ -172,7 +186,7 @@ you should carefully research - + @@ -187,5 +201,10 @@ you should carefully research by Mark McGranaghan | source | license

    + + diff --git a/public/signals b/public/signals index 50f0ec1..b0109b5 100644 --- a/public/signals +++ b/public/signals @@ -5,6 +5,20 @@ Go by Example: Signals +

    Go by Example: Signals

    @@ -23,7 +37,7 @@ Here’s how to handle signals in Go with channels.

    - + @@ -32,10 +46,8 @@ Here’s how to handle signals in Go with channels.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -47,10 +59,12 @@ Here’s how to handle signals in Go with channels.

    -
    import "fmt"
    -import "os"
    -import "os/signal"
    -import "syscall"
    +          
    import (
    +    "fmt"
    +    "os"
    +    "os/signal"
    +    "syscall"
    +)
     
    @@ -62,7 +76,7 @@ Here’s how to handle signals in Go with channels.

    -
    func main() {
    +          
    func main() {
     
    @@ -78,7 +92,7 @@ notify us when the program can exit).

    -
        sigs := make(chan os.Signal, 1)
    +          
        sigs := make(chan os.Signal, 1)
         done := make(chan bool, 1)
     
    @@ -93,7 +107,7 @@ receive notifications of the specified signals.

    -
        signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    +          
        signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
     
    @@ -108,7 +122,7 @@ and then notify the program that it can finish.

    -
        go func() {
    +          
        go func() {
             sig := <-sigs
             fmt.Println()
             fmt.Println(sig)
    @@ -128,7 +142,7 @@ above sending a value on done) and then exit.

    -
        fmt.Println("awaiting signal")
    +          
        fmt.Println("awaiting signal")
         <-done
         fmt.Println("exiting")
     }
    @@ -151,7 +165,7 @@ causing the program to print interrupt and then exit.

    -
    $ go run signals.go
    +          
    $ go run signals.go
     awaiting signal
     ^C
     interrupt
    @@ -172,5 +186,10 @@ causing the program to print interrupt and then exit.

    by Mark McGranaghan | source | license

    + + diff --git a/public/site.css b/public/site.css index 4808e32..7e93afb 100644 --- a/public/site.css +++ b/public/site.css @@ -136,11 +136,17 @@ pre, code { font-size: 14px; line-height: 18px; font-family: 'Menlo', 'Monaco', 'Consolas', 'Lucida Console', monospace; } -img.run { +img.copy, img.run { height: 16px; width: 16px; float: right } +img.copy, img.run { + cursor: pointer; +} +img.copy { + margin-right: 4px; +} /* Syntax highlighting */ body .hll { background-color: #ffffcc } diff --git a/public/site.js b/public/site.js new file mode 100644 index 0000000..752e656 --- /dev/null +++ b/public/site.js @@ -0,0 +1,17 @@ +/*! + * clipboard.js v1.5.13 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function r(c,a){if(!n[c]){if(!e[c]){var l="function"==typeof require&&require;if(!a&&l)return l(c,!0);if(i)return i(c,!0);var s=new Error("Cannot find module '"+c+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[c]={exports:{}};e[c][0].call(u.exports,function(t){var n=e[c][1][t];return r(n?n:t)},u,u.exports,t,e,n,o)}return n[c].exports}for(var i="function"==typeof require&&require,c=0;cGo by Example: Slices +

    Go by Example: Slices

    @@ -19,7 +33,7 @@ powerful interface to sequences than arrays.

    - + @@ -28,10 +42,8 @@ powerful interface to sequences than arrays.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,7 +55,7 @@ powerful interface to sequences than arrays.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -55,7 +67,7 @@ powerful interface to sequences than arrays.

    -
    func main() {
    +          
    func main() {
     
    @@ -72,7 +84,7 @@ the builtin make. Here we make a slice of -
        s := make([]string, 3)
    +          
        s := make([]string, 3)
         fmt.Println("emp:", s)
     
    @@ -86,7 +98,7 @@ the builtin make. Here we make a slice of -
        s[0] = "a"
    +          
        s[0] = "a"
         s[1] = "b"
         s[2] = "c"
         fmt.Println("set:", s)
    @@ -103,7 +115,7 @@ the builtin make. Here we make a slice of
               
               
                 
    -            
        fmt.Println("len:", len(s))
    +          
        fmt.Println("len:", len(s))
     
    @@ -121,7 +133,7 @@ Note that we need to accept a return value from -
        s = append(s, "d")
    +          
        s = append(s, "d")
         s = append(s, "e", "f")
         fmt.Println("apd:", s)
     
    @@ -138,7 +150,7 @@ into c from s.

    -
        c := make([]string, len(s))
    +          
        c := make([]string, len(s))
         copy(c, s)
         fmt.Println("cpy:", c)
     
    @@ -155,7 +167,7 @@ of the elements s[2], s[3], and s[4].

    -
        l := s[2:5]
    +          
        l := s[2:5]
         fmt.Println("sl1:", l)
     
    @@ -169,7 +181,7 @@ of the elements s[2], s[3], and s[4].

    -
        l = s[:5]
    +          
        l = s[:5]
         fmt.Println("sl2:", l)
     
    @@ -183,7 +195,7 @@ of the elements s[2], s[3], and s[4].

    -
        l = s[2:]
    +          
        l = s[2:]
         fmt.Println("sl3:", l)
     
    @@ -198,7 +210,7 @@ in a single line as well.

    -
        t := []string{"g", "h", "i"}
    +          
        t := []string{"g", "h", "i"}
         fmt.Println("dcl:", t)
     
    @@ -214,7 +226,7 @@ vary, unlike with multi-dimensional arrays.

    -
        twoD := make([][]int, 3)
    +          
        twoD := make([][]int, 3)
         for i := 0; i < 3; i++ {
             innerLen := i + 1
             twoD[i] = make([]int, innerLen)
    @@ -241,7 +253,7 @@ they are rendered similarly by fmt.Println.

    -
    $ go run slices.go
    +          
    $ go run slices.go
     emp: [  ]
     set: [a b c]
     get: c
    @@ -267,7 +279,7 @@ implementation of slices in Go.

    - + @@ -279,7 +291,7 @@ Go’s other key builtin data structure: maps.

    - + @@ -294,5 +306,10 @@ Go’s other key builtin data structure: maps.

    by Mark McGranaghan | source | license

    + + diff --git a/public/sorting b/public/sorting index 73f22b1..ded8f48 100644 --- a/public/sorting +++ b/public/sorting @@ -5,6 +5,20 @@ Go by Example: Sorting +

    Go by Example: Sorting

    @@ -20,7 +34,7 @@ builtins first.

    - + @@ -29,10 +43,8 @@ builtins first.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,8 +56,10 @@ builtins first.

    -
    import "fmt"
    -import "sort"
    +          
    import (
    +    "fmt"
    +    "sort"
    +)
     
    @@ -57,7 +71,7 @@ builtins first.

    -
    func main() {
    +          
    func main() {
     
    @@ -73,7 +87,7 @@ return a new one.

    -
        strs := []string{"c", "a", "b"}
    +          
        strs := []string{"c", "a", "b"}
         sort.Strings(strs)
         fmt.Println("Strings:", strs)
     
    @@ -88,7 +102,7 @@ return a new one.

    -
        ints := []int{7, 2, 4}
    +          
        ints := []int{7, 2, 4}
         sort.Ints(ints)
         fmt.Println("Ints:   ", ints)
     
    @@ -104,7 +118,7 @@ already in sorted order.

    -
        s := sort.IntsAreSorted(ints)
    +          
        s := sort.IntsAreSorted(ints)
         fmt.Println("Sorted: ", s)
     }
     
    @@ -124,7 +138,7 @@ slices and true as the result of our AreSorted test. -
    $ go run sorting.go
    +          
    $ go run sorting.go
     Strings: [a b c]
     Ints:    [2 4 7]
     Sorted:  true
    @@ -144,5 +158,10 @@ slices and true as the result of our AreSorted test.Mark McGranaghan | source | license
           

    + + diff --git a/public/sorting-by-functions b/public/sorting-by-functions index 92c0f41..f86a188 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

    @@ -22,7 +36,7 @@ in Go.

    - + @@ -31,10 +45,8 @@ in Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -46,8 +58,10 @@ in Go.

    -
    import "sort"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "sort"
    +)
     
    @@ -63,7 +77,7 @@ type.

    -
    type byLength []string
    +          
    type byLength []string
     
    @@ -82,7 +96,7 @@ 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) {
    @@ -106,7 +120,7 @@ slice.

    -
    func main() {
    +          
    func main() {
         fruits := []string{"peach", "banana", "kiwi"}
         sort.Sort(byLength(fruits))
         fmt.Println(fruits)
    @@ -128,7 +142,7 @@ length, as desired.

    -
    $ go run sorting-by-functions.go 
    +          
    $ go run sorting-by-functions.go 
     [kiwi peach banana]
     
    @@ -146,7 +160,7 @@ functions.

    - + @@ -161,5 +175,10 @@ functions.

    by Mark McGranaghan | source | license

    + + diff --git a/public/spawning-processes b/public/spawning-processes index c6ba21e..da8dfc5 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -5,6 +5,20 @@ Go by Example: Spawning Processes +

    Go by Example: Spawning Processes

    @@ -23,7 +37,7 @@ of spawning processes from Go.

    - + @@ -32,10 +46,8 @@ of spawning processes from Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -47,9 +59,11 @@ of spawning processes from Go.

    -
    import "fmt"
    -import "io/ioutil"
    -import "os/exec"
    +          
    import (
    +    "fmt"
    +    "io/ioutil"
    +    "os/exec"
    +)
     
    @@ -61,7 +75,7 @@ of spawning processes from Go.

    -
    func main() {
    +          
    func main() {
     
    @@ -77,7 +91,7 @@ to represent this external process.

    -
        dateCmd := exec.Command("date")
    +          
        dateCmd := exec.Command("date")
     
    @@ -93,7 +107,7 @@ and collecting its output. If there were no errors, -
        dateOut, err := dateCmd.Output()
    +          
        dateOut, err := dateCmd.Output()
         if err != nil {
             panic(err)
         }
    @@ -113,7 +127,7 @@ where we pipe data to the external process on its
               
               
                 
    -            
        grepCmd := exec.Command("grep", "hello")
    +          
        grepCmd := exec.Command("grep", "hello")
     
    @@ -129,7 +143,7 @@ to exit.

    -
        grepIn, _ := grepCmd.StdinPipe()
    +          
        grepIn, _ := grepCmd.StdinPipe()
         grepOut, _ := grepCmd.StdoutPipe()
         grepCmd.Start()
         grepIn.Write([]byte("hello grep\ngoodbye grep"))
    @@ -152,7 +166,7 @@ exactly the same way.

    -
        fmt.Println("> grep hello")
    +          
        fmt.Println("> grep hello")
         fmt.Println(string(grepBytes))
     
    @@ -171,7 +185,7 @@ option:

    -
        lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
    +          
        lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
         lsOut, err := lsCmd.Output()
         if err != nil {
             panic(err)
    @@ -196,7 +210,7 @@ as if we had run them directly from the command-line.

    -
    $ go run spawning-processes.go 
    +          
    $ go run spawning-processes.go 
     > date
     Wed Oct 10 09:53:11 PDT 2012
     
    @@ -210,7 +224,7 @@ as if we had run them directly from the command-line.

    -
    > grep hello
    +          
    > grep hello
     hello grep
     
    @@ -223,7 +237,7 @@ as if we had run them directly from the command-line.

    -
    > ls -a -l -h
    +          
    > 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 ..
     -rw-r--r--  1 mark 1.3K Oct 3 16:28 spawning-processes.go
    @@ -243,5 +257,10 @@ as if we had run them directly from the command-line.

    by Mark McGranaghan | source | license

    + + diff --git a/public/stateful-goroutines b/public/stateful-goroutines index a14245a..80ad0ba 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -5,6 +5,20 @@ Go by Example: Stateful Goroutines +

    Go by Example: Stateful Goroutines

    @@ -25,7 +39,7 @@ by exactly 1 goroutine.

    - + @@ -34,10 +48,8 @@ by exactly 1 goroutine.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -49,7 +61,7 @@ by exactly 1 goroutine.

    -
    import (
    +          
    import (
         "fmt"
         "math/rand"
         "sync/atomic"
    @@ -74,7 +86,7 @@ goroutine to respond.

    -
    type readOp struct {
    +          
    type readOp struct {
         key  int
         resp chan int
     }
    @@ -94,7 +106,7 @@ goroutine to respond.

    -
    func main() {
    +          
    func main() {
     
    @@ -107,7 +119,7 @@ goroutine to respond.

    -
        var readOps uint64
    +          
        var readOps uint64
         var writeOps uint64
     
    @@ -123,7 +135,7 @@ respectively.

    -
        reads := make(chan readOp)
    +          
        reads := make(chan readOp)
         writes := make(chan writeOp)
     
    @@ -145,7 +157,7 @@ value in the case of reads).

    -
        go func() {
    +          
        go func() {
             var state = make(map[int]int)
             for {
                 select {
    @@ -173,7 +185,7 @@ result over the provided resp channel.

    -
        for r := 0; r < 100; r++ {
    +          
        for r := 0; r < 100; r++ {
             go func() {
                 for {
                     read := readOp{
    @@ -199,7 +211,7 @@ approach.

    -
        for w := 0; w < 10; w++ {
    +          
        for w := 0; w < 10; w++ {
             go func() {
                 for {
                     write := writeOp{
    @@ -225,7 +237,7 @@ approach.

    -
        time.Sleep(time.Second)
    +          
        time.Sleep(time.Second)
     
    @@ -238,7 +250,7 @@ approach.

    -
        readOpsFinal := atomic.LoadUint64(&readOps)
    +          
        readOpsFinal := atomic.LoadUint64(&readOps)
         fmt.Println("readOps:", readOpsFinal)
         writeOpsFinal := atomic.LoadUint64(&writeOps)
         fmt.Println("writeOps:", writeOpsFinal)
    @@ -261,7 +273,7 @@ total operations.

    -
    $ go run stateful-goroutines.go
    +          
    $ go run stateful-goroutines.go
     readOps: 71708
     writeOps: 7177
     
    @@ -283,7 +295,7 @@ program.

    - + @@ -298,5 +310,10 @@ program.

    by Mark McGranaghan | source | license

    + + diff --git a/public/string-formatting b/public/string-formatting index c3118b0..6616ed0 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -5,6 +5,20 @@ Go by Example: String Formatting +

    Go by Example: String Formatting

    @@ -20,7 +34,7 @@ common string formatting tasks.

    - + @@ -29,10 +43,8 @@ common string formatting tasks.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,8 +56,10 @@ common string formatting tasks.

    -
    import "fmt"
    -import "os"
    +          
    import (
    +    "fmt"
    +    "os"
    +)
     
    @@ -57,7 +71,7 @@ common string formatting tasks.

    -
    type point struct {
    +          
    type point struct {
         x, y int
     }
     
    @@ -71,7 +85,7 @@ common string formatting tasks.

    -
    func main() {
    +          
    func main() {
     
    @@ -86,7 +100,7 @@ an instance of our point struct.

    -
        p := point{1, 2}
    +          
        p := point{1, 2}
         fmt.Printf("%v\n", p)
     
    @@ -101,7 +115,7 @@ include the struct’s field names.

    -
        fmt.Printf("%+v\n", p)
    +          
        fmt.Printf("%+v\n", p)
     
    @@ -116,7 +130,7 @@ would produce that value.

    -
        fmt.Printf("%#v\n", p)
    +          
        fmt.Printf("%#v\n", p)
     
    @@ -129,7 +143,7 @@ would produce that value.

    -
        fmt.Printf("%T\n", p)
    +          
        fmt.Printf("%T\n", p)
     
    @@ -142,7 +156,7 @@ would produce that value.

    -
        fmt.Printf("%t\n", true)
    +          
        fmt.Printf("%t\n", true)
     
    @@ -156,7 +170,7 @@ Use %d for standard, base-10 formatting.

    -
        fmt.Printf("%d\n", 123)
    +          
        fmt.Printf("%d\n", 123)
     
    @@ -169,7 +183,7 @@ Use %d for standard, base-10 formatting.

    -
        fmt.Printf("%b\n", 14)
    +          
        fmt.Printf("%b\n", 14)
     
    @@ -183,7 +197,7 @@ given integer.

    -
        fmt.Printf("%c\n", 33)
    +          
        fmt.Printf("%c\n", 33)
     
    @@ -196,7 +210,7 @@ given integer.

    -
        fmt.Printf("%x\n", 456)
    +          
        fmt.Printf("%x\n", 456)
     
    @@ -210,7 +224,7 @@ floats. For basic decimal formatting use %f.

    -
        fmt.Printf("%f\n", 78.9)
    +          
        fmt.Printf("%f\n", 78.9)
     
    @@ -224,7 +238,7 @@ different versions of) scientific notation.

    -
        fmt.Printf("%e\n", 123400000.0)
    +          
        fmt.Printf("%e\n", 123400000.0)
         fmt.Printf("%E\n", 123400000.0)
     
    @@ -238,7 +252,7 @@ different versions of) scientific notation.

    -
        fmt.Printf("%s\n", "\"string\"")
    +          
        fmt.Printf("%s\n", "\"string\"")
     
    @@ -251,7 +265,7 @@ different versions of) scientific notation.

    -
        fmt.Printf("%q\n", "\"string\"")
    +          
        fmt.Printf("%q\n", "\"string\"")
     
    @@ -266,7 +280,7 @@ per byte of input.

    -
        fmt.Printf("%x\n", "hex this")
    +          
        fmt.Printf("%x\n", "hex this")
     
    @@ -279,7 +293,7 @@ per byte of input.

    -
        fmt.Printf("%p\n", &p)
    +          
        fmt.Printf("%p\n", &p)
     
    @@ -297,7 +311,7 @@ spaces.

    -
        fmt.Printf("|%6d|%6d|\n", 12, 345)
    +          
        fmt.Printf("|%6d|%6d|\n", 12, 345)
     
    @@ -313,7 +327,7 @@ width.precision syntax.

    -
        fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
    +          
        fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
     
    @@ -326,7 +340,7 @@ width.precision syntax.

    -
        fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
    +          
        fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
     
    @@ -341,7 +355,7 @@ table-like output. For basic right-justified width.

    -
        fmt.Printf("|%6s|%6s|\n", "foo", "b")
    +          
        fmt.Printf("|%6s|%6s|\n", "foo", "b")
     
    @@ -354,7 +368,7 @@ table-like output. For basic right-justified width.

    -
        fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
    +          
        fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
     
    @@ -369,7 +383,7 @@ and returns a string without printing it anywhere.

    -
        s := fmt.Sprintf("a %s", "string")
    +          
        s := fmt.Sprintf("a %s", "string")
         fmt.Println(s)
     
    @@ -384,7 +398,7 @@ and returns a string without printing it anywhere.

    -
        fmt.Fprintf(os.Stderr, "an %s\n", "error")
    +          
        fmt.Fprintf(os.Stderr, "an %s\n", "error")
     }
     
    @@ -401,7 +415,7 @@ and returns a string without printing it anywhere.

    -
    $ go run string-formatting.go
    +          
    $ go run string-formatting.go
     {1 2}
     {x:1 y:2}
     main.point{x:1, y:2}
    @@ -441,5 +455,10 @@ and returns a string without printing it anywhere.

    by Mark McGranaghan | source | license

    + + diff --git a/public/string-functions b/public/string-functions index 73b6019..093c467 100644 --- a/public/string-functions +++ b/public/string-functions @@ -5,6 +5,20 @@ Go by Example: String Functions +

    Go by Example: String Functions

    @@ -20,7 +34,7 @@ to give you a sense of the package.

    - + @@ -29,10 +43,8 @@ to give you a sense of the package.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,8 +56,10 @@ to give you a sense of the package.

    -
    import s "strings"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    s "strings"
    +)
     
    @@ -59,7 +73,7 @@ it a lot below.

    -
    var p = fmt.Println
    +          
    var p = fmt.Println
     
    @@ -71,7 +85,7 @@ it a lot below.

    -
    func main() {
    +          
    func main() {
     
    @@ -90,7 +104,7 @@ package docs.

    -
        p("Contains:  ", s.Contains("test", "es"))
    +          
        p("Contains:  ", s.Contains("test", "es"))
         p("Count:     ", s.Count("test", "t"))
         p("HasPrefix: ", s.HasPrefix("test", "te"))
         p("HasSuffix: ", s.HasSuffix("test", "st"))
    @@ -117,7 +131,7 @@ bytes and getting a byte by index.

    -
        p("Len: ", len("hello"))
    +          
        p("Len: ", len("hello"))
         p("Char:", "hello"[1])
     }
     
    @@ -137,7 +151,7 @@ for more information.

    - + @@ -151,7 +165,7 @@ for more information.

    -
    $ go run string-functions.go
    +          
    $ go run string-functions.go
     Contains:   true
     Count:      2
     HasPrefix:  true
    @@ -175,7 +189,7 @@ for more information.

    -
    Len:  5
    +          
    Len:  5
     Char: 101
     
    @@ -193,5 +207,10 @@ for more information.

    by Mark McGranaghan | source | license

    + + diff --git a/public/structs b/public/structs index 31c03d0..672b214 100644 --- a/public/structs +++ b/public/structs @@ -5,6 +5,20 @@ Go by Example: Structs +

    Go by Example: Structs

    @@ -20,7 +34,7 @@ records.

    - + @@ -29,10 +43,8 @@ records.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ records.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -57,7 +69,7 @@ records.

    -
    type person struct {
    +          
    type person struct {
         name string
         age  int
     }
    @@ -66,13 +78,43 @@ records.

    + + +

    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}
    +    p.age = 42
    +    return &p
    +}
    +
    + + + + -
    func main() {
    +          
    func main() {
     
    @@ -85,7 +127,7 @@ records.

    -
        fmt.Println(person{"Bob", 20})
    +          
        fmt.Println(person{"Bob", 20})
     
    @@ -98,7 +140,7 @@ records.

    -
        fmt.Println(person{name: "Alice", age: 30})
    +          
        fmt.Println(person{name: "Alice", age: 30})
     
    @@ -111,7 +153,7 @@ records.

    -
        fmt.Println(person{name: "Fred"})
    +          
        fmt.Println(person{name: "Fred"})
     
    @@ -124,7 +166,20 @@ records.

    -
        fmt.Println(&person{name: "Ann", age: 40})
    +          
        fmt.Println(&person{name: "Ann", age: 40})
    +
    + + + + + + +

    It’s idiomatic to encapsulate new struct creation in constructor functions

    + + + + +
        fmt.Println(NewPerson("Jon"))
     
    @@ -137,7 +192,7 @@ records.

    -
        s := person{name: "Sean", age: 50}
    +          
        s := person{name: "Sean", age: 50}
         fmt.Println(s.name)
     
    @@ -152,7 +207,7 @@ pointers are automatically dereferenced.

    -
        sp := &s
    +          
        sp := &s
         fmt.Println(sp.age)
     
    @@ -166,7 +221,7 @@ pointers are automatically dereferenced.

    -
        sp.age = 51
    +          
        sp.age = 51
         fmt.Println(sp.age)
     }
     
    @@ -184,7 +239,7 @@ pointers are automatically dereferenced.

    -
    $ go run structs.go
    +          
    $ go run structs.go
     {Bob 20}
     {Alice 30}
     {Fred 0}
    @@ -192,6 +247,7 @@ pointers are automatically dereferenced.

    Sean 50 51 +&{Jon 42}
    @@ -208,5 +264,10 @@ pointers are automatically dereferenced.

    by Mark McGranaghan | source | license

    + + diff --git a/public/switch b/public/switch index c739ea3..f0eff96 100644 --- a/public/switch +++ b/public/switch @@ -5,6 +5,20 @@ Go by Example: Switch +

    Go by Example: Switch

    @@ -19,7 +33,7 @@ branches.

    - + @@ -28,10 +42,8 @@ branches.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,8 +55,10 @@ branches.

    -
    import "fmt"
    -import "time"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -56,7 +70,7 @@ branches.

    -
    func main() {
    +          
    func main() {
     
    @@ -69,7 +83,7 @@ branches.

    -
        i := 2
    +          
        i := 2
         fmt.Print("Write ", i, " as ")
         switch i {
         case 1:
    @@ -93,7 +107,7 @@ in the same case statement. We use the optional
               
               
                 
    -            
        switch time.Now().Weekday() {
    +          
        switch time.Now().Weekday() {
         case time.Saturday, time.Sunday:
             fmt.Println("It's the weekend")
         default:
    @@ -113,7 +127,7 @@ to express if/else logic. Here we also show how the
               
               
                 
    -            
        t := time.Now()
    +          
        t := time.Now()
         switch {
         case t.Hour() < 12:
             fmt.Println("It's before noon")
    @@ -135,7 +149,7 @@ type corresponding to its clause.

    -
        whatAmI := func(i interface{}) {
    +          
        whatAmI := func(i interface{}) {
             switch t := i.(type) {
             case bool:
                 fmt.Println("I'm a bool")
    @@ -164,7 +178,7 @@ type corresponding to its clause.

    -
    $ go run switch.go 
    +          
    $ go run switch.go 
     Write 2 as two
     It's a weekday
     It's after noon
    @@ -187,5 +201,10 @@ type corresponding to its clause.

    by Mark McGranaghan | source | license

    + + diff --git a/public/temporary-files-and-directories b/public/temporary-files-and-directories new file mode 100644 index 0000000..37d7831 --- /dev/null +++ b/public/temporary-files-and-directories @@ -0,0 +1,248 @@ + + + + + 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)
    +}
    +
    + +
    + + + + + + + + +
    + + + +
    $ go run temporary-files-and-directories.go
    +Temp file name: /tmp/sample610887201
    +Temp dir name: /tmp/sampledir898854668
    +
    + +
    + + +

    + Next example: Command-Line Arguments. +

    + + +
    + + + + diff --git a/public/tickers b/public/tickers index 64f1044..dd2bb28 100644 --- a/public/tickers +++ b/public/tickers @@ -5,6 +5,20 @@ Go by Example: Tickers +

    Go by Example: Tickers

    @@ -22,7 +36,7 @@ periodically until we stop it.

    - + @@ -31,10 +45,8 @@ periodically until we stop it.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -46,8 +58,10 @@ periodically until we stop it.

    -
    import "time"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -59,7 +73,7 @@ periodically until we stop it.

    -
    func main() {
    +          
    func main() {
     
    @@ -75,10 +89,27 @@ 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)
    +          
        ticker := time.NewTicker(500 * time.Millisecond)
    +    done := make(chan bool)
    +
    + + + + + + + + + + +
        go func() {
    +        for {
    +            select {
    +            case <-done:
    +                return
    +            case t := <-ticker.C:
    +                fmt.Println("Tick at", t)
    +            }
             }
         }()
     
    @@ -95,8 +126,9 @@ channel. We’ll stop ours after 1600ms.

    -
        time.Sleep(1600 * time.Millisecond)
    +          
        time.Sleep(1600 * time.Millisecond)
         ticker.Stop()
    +    done <- true
         fmt.Println("Ticker stopped")
     }
     
    @@ -116,7 +148,7 @@ before we stop it.

    -
    $ go run tickers.go
    +          
    $ 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
     Tick at 2012-09-23 11:29:57.488076 -0700 PDT
    @@ -137,5 +169,10 @@ before we stop it.

    by Mark McGranaghan | source | license

    + + diff --git a/public/time b/public/time index 443f568..12137d8 100644 --- a/public/time +++ b/public/time @@ -5,6 +5,20 @@ Go by Example: Time +

    Go by Example: Time

    @@ -19,7 +33,7 @@ here are some examples.

    - + @@ -28,10 +42,8 @@ here are some examples.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,8 +55,10 @@ here are some examples.

    -
    import "fmt"
    -import "time"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -56,7 +70,7 @@ here are some examples.

    -
    func main() {
    +          
    func main() {
         p := fmt.Println
     
    @@ -70,7 +84,7 @@ here are some examples.

    -
        now := time.Now()
    +          
        now := time.Now()
         p(now)
     
    @@ -86,7 +100,7 @@ with a Location, i.e. time zone.

    -
        then := time.Date(
    +          
        then := time.Date(
             2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
         p(then)
     
    @@ -102,7 +116,7 @@ value as expected.

    -
        p(then.Year())
    +          
        p(then.Year())
         p(then.Month())
         p(then.Day())
         p(then.Hour())
    @@ -122,7 +136,7 @@ value as expected.

    -
        p(then.Weekday())
    +          
        p(then.Weekday())
     
    @@ -137,7 +151,7 @@ as the second, respectively.

    -
        p(then.Before(now))
    +          
        p(then.Before(now))
         p(then.After(now))
         p(then.Equal(now))
     
    @@ -153,7 +167,7 @@ the interval between two times.

    -
        diff := now.Sub(then)
    +          
        diff := now.Sub(then)
         p(diff)
     
    @@ -168,7 +182,7 @@ various units.

    -
        p(diff.Hours())
    +          
        p(diff.Hours())
         p(diff.Minutes())
         p(diff.Seconds())
         p(diff.Nanoseconds())
    @@ -186,7 +200,7 @@ duration.

    -
        p(then.Add(diff))
    +          
        p(then.Add(diff))
         p(then.Add(-diff))
     }
     
    @@ -204,7 +218,7 @@ duration.

    -
    $ go run time.go
    +          
    $ go run time.go
     2012-10-31 15:50:13.793654 +0000 UTC
     2009-11-17 20:34:58.651387237 +0000 UTC
     2009
    @@ -239,7 +253,7 @@ the Unix epoch.

    - + @@ -254,5 +268,10 @@ the Unix epoch.

    by Mark McGranaghan | source | license

    + + diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index f16fbc9..5c8f266 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

    @@ -19,7 +33,7 @@ pattern-based layouts.

    - + @@ -28,10 +42,8 @@ pattern-based layouts.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,8 +55,10 @@ pattern-based layouts.

    -
    import "fmt"
    -import "time"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -56,7 +70,7 @@ pattern-based layouts.

    -
    func main() {
    +          
    func main() {
         p := fmt.Println
     
    @@ -72,7 +86,7 @@ constant.

    -
        t := time.Now()
    +          
        t := time.Now()
         p(t.Format(time.RFC3339))
     
    @@ -86,7 +100,7 @@ constant.

    -
        t1, e := time.Parse(
    +          
        t1, e := time.Parse(
             time.RFC3339,
             "2012-11-01T22:08:41+00:00")
         p(t1)
    @@ -108,7 +122,7 @@ The example time must be exactly as shown: the year 2006,
               
               
                 
    -            
        p(t.Format("3:04PM"))
    +          
        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"
    @@ -128,7 +142,7 @@ components of the time value.

    -
        fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
    +          
        fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
             t.Year(), t.Month(), t.Day(),
             t.Hour(), t.Minute(), t.Second())
     
    @@ -144,7 +158,7 @@ explaining the parsing problem.

    -
        ansic := "Mon Jan _2 15:04:05 2006"
    +          
        ansic := "Mon Jan _2 15:04:05 2006"
         _, e = time.Parse(ansic, "8:41PM")
         p(e)
     }
    @@ -163,7 +177,7 @@ explaining the parsing problem.

    -
    $ go run time-formatting-parsing.go 
    +          
    $ go run time-formatting-parsing.go 
     2014-04-15T18:00:15-07:00
     2012-11-01 22:08:41 +0000 +0000
     6:00PM
    @@ -188,5 +202,10 @@ explaining the parsing problem.

    by Mark McGranaghan | source | license

    + + diff --git a/public/timeouts b/public/timeouts index 449446a..39238ed 100644 --- a/public/timeouts +++ b/public/timeouts @@ -5,6 +5,20 @@ Go by Example: Timeouts +

    Go by Example: Timeouts

    @@ -21,7 +35,7 @@ elegant thanks to channels and select.

    - + @@ -30,10 +44,8 @@ elegant thanks to channels and select.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,8 +57,10 @@ elegant thanks to channels and select.

    -
    import "time"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -58,7 +72,7 @@ elegant thanks to channels and select.

    -
    func main() {
    +          
    func main() {
     
    @@ -68,12 +82,15 @@ elegant thanks to channels and select.

    For our example, suppose we’re executing an external call that returns its result on a channel c1 -after 2s.

    +after 2s. Note that the channel is buffered, so the +send in the goroutine is nonblocking. This is a +common pattern to prevent goroutine leaks in case the +channel is never read.

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

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

    -
        c2 := make(chan string, 1)
    +          
        c2 := make(chan string, 1)
         go func() {
             time.Sleep(2 * time.Second)
             c2 <- "result 2"
    @@ -141,9 +158,9 @@ from c2 will succeed and we’ll print the result.

    out and the second succeeding.

    - + -
    $ go run timeouts.go 
    +          
    $ go run timeouts.go 
     timeout 1
     result 2
     
    @@ -151,21 +168,6 @@ out and the second succeeding.

    - - -

    Using this select timeout pattern requires -communicating results over channels. This is a good -idea in general because other important Go features are -based on channels and select. We’ll look at two -examples of this next: timers and tickers.

    - - - - - - - - @@ -177,5 +179,10 @@ examples of this next: timers and tickers.

    by Mark McGranaghan | source | license

    + + diff --git a/public/timers b/public/timers index 7004b5f..977afef 100644 --- a/public/timers +++ b/public/timers @@ -5,6 +5,20 @@ Go by Example: Timers +

    Go by Example: Timers

    @@ -22,7 +36,7 @@ at tickers.

    - + @@ -31,10 +45,8 @@ at tickers.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -46,8 +58,10 @@ at tickers.

    -
    import "time"
    -import "fmt"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -59,7 +73,7 @@ at tickers.

    -
    func main() {
    +          
    func main() {
     
    @@ -75,7 +89,7 @@ time. This timer will wait 2 seconds.

    -
        timer1 := time.NewTimer(2 * time.Second)
    +          
        timer1 := time.NewTimer(2 * time.Second)
     
    @@ -90,7 +104,7 @@ expired.

    -
        <-timer1.C
    +          
        <-timer1.C
         fmt.Println("Timer 1 expired")
     
    @@ -107,7 +121,7 @@ Here’s an example of that.

    -
        timer2 := time.NewTimer(time.Second)
    +          
        timer2 := time.NewTimer(time.Second)
         go func() {
             <-timer2.C
             fmt.Println("Timer 2 expired")
    @@ -135,7 +149,7 @@ a chance to expire.

    -
    $ go run timers.go
    +          
    $ go run timers.go
     Timer 1 expired
     Timer 2 stopped
     
    @@ -154,5 +168,10 @@ a chance to expire.

    by Mark McGranaghan | source | license

    + + diff --git a/public/url-parsing b/public/url-parsing index 8b17377..0cd07f4 100644 --- a/public/url-parsing +++ b/public/url-parsing @@ -5,6 +5,20 @@ Go by Example: URL Parsing +

    Go by Example: URL Parsing

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

    - + @@ -28,10 +42,8 @@ Here’s how to parse URLs in Go.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,9 +55,11 @@ Here’s how to parse URLs in Go.

    -
    import "fmt"
    -import "net"
    -import "net/url"
    +          
    import (
    +    "fmt"
    +    "net"
    +    "net/url"
    +)
     
    @@ -57,7 +71,7 @@ Here’s how to parse URLs in Go.

    -
    func main() {
    +          
    func main() {
     
    @@ -72,7 +86,7 @@ query params, and query fragment.

    -
        s := "postgres://user:pass@host.com:5432/path?k=v#f"
    +          
        s := "postgres://user:pass@host.com:5432/path?k=v#f"
     
    @@ -85,7 +99,7 @@ query params, and query fragment.

    -
        u, err := url.Parse(s)
    +          
        u, err := url.Parse(s)
         if err != nil {
             panic(err)
         }
    @@ -101,7 +115,7 @@ query params, and query fragment.

    -
        fmt.Println(u.Scheme)
    +          
        fmt.Println(u.Scheme)
     
    @@ -116,7 +130,7 @@ values.

    -
        fmt.Println(u.User)
    +          
        fmt.Println(u.User)
         fmt.Println(u.User.Username())
         p, _ := u.User.Password()
         fmt.Println(p)
    @@ -133,7 +147,7 @@ if present. Use SplitHostPort to extract them.

    -
        fmt.Println(u.Host)
    +          
        fmt.Println(u.Host)
         host, port, _ := net.SplitHostPort(u.Host)
         fmt.Println(host)
         fmt.Println(port)
    @@ -150,7 +164,7 @@ the #.

    -
        fmt.Println(u.Path)
    +          
        fmt.Println(u.Path)
         fmt.Println(u.Fragment)
     
    @@ -168,7 +182,7 @@ if you only want the first value.

    -
        fmt.Println(u.RawQuery)
    +          
        fmt.Println(u.RawQuery)
         m, _ := url.ParseQuery(u.RawQuery)
         fmt.Println(m)
         fmt.Println(m["k"][0])
    @@ -190,7 +204,7 @@ pieces that we extracted.

    -
    $ go run url-parsing.go 
    +          
    $ go run url-parsing.go 
     postgres
     user:pass
     user
    @@ -219,5 +233,10 @@ pieces that we extracted.

    by Mark McGranaghan | source | license

    + + diff --git a/public/values b/public/values index 38966a3..eef6bfb 100644 --- a/public/values +++ b/public/values @@ -5,6 +5,20 @@ Go by Example: Values +

    Go by Example: Values

    @@ -20,7 +34,7 @@ basic examples.

    - + @@ -29,10 +43,8 @@ basic examples.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ basic examples.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -56,7 +68,7 @@ basic examples.

    -
    func main() {
    +          
    func main() {
     
    @@ -69,7 +81,7 @@ basic examples.

    -
        fmt.Println("go" + "lang")
    +          
        fmt.Println("go" + "lang")
     
    @@ -82,7 +94,7 @@ basic examples.

    -
        fmt.Println("1+1 =", 1+1)
    +          
        fmt.Println("1+1 =", 1+1)
         fmt.Println("7.0/3.0 =", 7.0/3.0)
     
    @@ -96,7 +108,7 @@ basic examples.

    -
        fmt.Println(true && false)
    +          
        fmt.Println(true && false)
         fmt.Println(true || false)
         fmt.Println(!true)
     }
    @@ -115,7 +127,7 @@ basic examples.

    -
    $ go run values.go
    +          
    $ go run values.go
     golang
     1+1 = 2
     7.0/3.0 = 2.3333333333333335
    @@ -138,5 +150,10 @@ basic examples.

    by Mark McGranaghan | source | license

    + + diff --git a/public/variables b/public/variables index 9c1156a..8ce28a3 100644 --- a/public/variables +++ b/public/variables @@ -5,6 +5,20 @@ Go by Example: Variables +

    Go by Example: Variables

    @@ -20,7 +34,7 @@ calls.

    - + @@ -29,10 +43,8 @@ calls.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -44,7 +56,7 @@ calls.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -56,7 +68,7 @@ calls.

    -
    func main() {
    +          
    func main() {
     
    @@ -69,7 +81,7 @@ calls.

    -
        var a = "initial"
    +          
        var a = "initial"
         fmt.Println(a)
     
    @@ -83,7 +95,7 @@ calls.

    -
        var b, c int = 1, 2
    +          
        var b, c int = 1, 2
         fmt.Println(b, c)
     
    @@ -97,7 +109,7 @@ calls.

    -
        var d = true
    +          
        var d = true
         fmt.Println(d)
     
    @@ -113,7 +125,7 @@ zero value for an int is 0.

    -
        var e int
    +          
        var e int
         fmt.Println(e)
     
    @@ -129,7 +141,7 @@ initializing a variable, e.g. for -
        f := "apple"
    +          
        f := "apple"
         fmt.Println(f)
     }
     
    @@ -147,7 +159,7 @@ initializing a variable, e.g. for -
    $ go run variables.go
    +          
    $ go run variables.go
     initial
     1 2
     true
    @@ -169,5 +181,10 @@ initializing a variable, e.g. for
             by Mark McGranaghan | source | license
           

    + + diff --git a/public/variadic-functions b/public/variadic-functions index 75ce887..536970b 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -5,6 +5,20 @@ Go by Example: Variadic Functions +

    Go by Example: Variadic Functions

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

    - + @@ -30,10 +44,8 @@ function.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -45,7 +57,7 @@ function.

    -
    import "fmt"
    +          
    import "fmt"
     
    @@ -59,7 +71,7 @@ of ints as arguments.

    -
    func sum(nums ...int) {
    +          
    func sum(nums ...int) {
         fmt.Print(nums, " ")
         total := 0
         for _, num := range nums {
    @@ -78,7 +90,7 @@ of ints as arguments.

    -
    func main() {
    +          
    func main() {
     
    @@ -92,7 +104,7 @@ with individual arguments.

    -
        sum(1, 2)
    +          
        sum(1, 2)
         sum(1, 2, 3)
     
    @@ -108,7 +120,7 @@ apply them to a variadic function using -
        nums := []int{1, 2, 3, 4}
    +          
        nums := []int{1, 2, 3, 4}
         sum(nums...)
     }
     
    @@ -126,7 +138,7 @@ apply them to a variadic function using -
    $ go run variadic-functions.go 
    +          
    $ go run variadic-functions.go 
     [1 2] 3
     [1 2 3] 6
     [1 2 3 4] 10
    @@ -143,7 +155,7 @@ to form closures, which we’ll look at next.

    - + @@ -158,5 +170,10 @@ to form closures, which we’ll look at next.

    by Mark McGranaghan | source | license

    + + diff --git a/public/waitgroups b/public/waitgroups index 45792a8..d8c3f13 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -5,6 +5,20 @@ Go by Example: WaitGroups +

    Go by Example: WaitGroups

    @@ -19,7 +33,7 @@ use a wait group.

    - + @@ -28,10 +42,8 @@ use a wait group.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,7 +55,7 @@ use a wait group.

    -
    import (
    +          
    import (
         "fmt"
         "sync"
         "time"
    @@ -62,7 +74,7 @@ pointer.

    -
    func worker(id int, wg *sync.WaitGroup) {
    +          
    func worker(id int, wg *sync.WaitGroup) {
         fmt.Printf("Worker %d starting\n", id)
     
    @@ -76,7 +88,7 @@ pointer.

    -
        time.Sleep(time.Second)
    +          
        time.Sleep(time.Second)
         fmt.Printf("Worker %d done\n", id)
     
    @@ -90,7 +102,7 @@ pointer.

    -
        wg.Done()
    +          
        wg.Done()
     }
     
    @@ -103,7 +115,7 @@ pointer.

    -
    func main() {
    +          
    func main() {
     
    @@ -117,7 +129,7 @@ goroutines launched here to finish.

    -
        var wg sync.WaitGroup
    +          
        var wg sync.WaitGroup
     
    @@ -131,7 +143,7 @@ counter for each.

    -
        for i := 1; i <= 5; i++ {
    +          
        for i := 1; i <= 5; i++ {
             wg.Add(1)
             go worker(i, &wg)
         }
    @@ -148,7 +160,7 @@ all the workers notified they’re done.

    -
        wg.Wait()
    +          
        wg.Wait()
     }
     
    @@ -165,7 +177,7 @@ all the workers notified they’re done.

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

    - + @@ -204,5 +216,10 @@ is likely to be different for each invocation.

    by Mark McGranaghan | source | license

    + + diff --git a/public/worker-pools b/public/worker-pools index e1170bf..70a6a0b 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -5,6 +5,20 @@ Go by Example: Worker Pools +

    Go by Example: Worker Pools

    @@ -19,7 +33,7 @@ a worker pool using goroutines and channels.

    - + @@ -28,10 +42,8 @@ a worker pool using goroutines and channels.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,8 +55,10 @@ a worker pool using goroutines and channels.

    -
    import "fmt"
    -import "time"
    +          
    import (
    +    "fmt"
    +    "time"
    +)
     
    @@ -61,7 +75,7 @@ simulate an expensive task.

    -
    func worker(id int, jobs <-chan int, results chan<- int) {
    +          
    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)
    @@ -80,7 +94,7 @@ simulate an expensive task.

    -
    func main() {
    +          
    func main() {
     
    @@ -95,7 +109,7 @@ channels for this.

    -
        jobs := make(chan int, 100)
    +          
        jobs := make(chan int, 100)
         results := make(chan int, 100)
     
    @@ -110,7 +124,7 @@ because there are no jobs yet.

    -
        for w := 1; w <= 3; w++ {
    +          
        for w := 1; w <= 3; w++ {
             go worker(w, jobs, results)
         }
     
    @@ -126,7 +140,7 @@ channel to indicate that’s all the work we have.

    -
        for j := 1; j <= 5; j++ {
    +          
        for j := 1; j <= 5; j++ {
             jobs <- j
         }
         close(jobs)
    @@ -145,7 +159,7 @@ goroutines is to use a WaitGroup.

    -
        for a := 1; a <= 5; a++ {
    +          
        for a := 1; a <= 5; a++ {
             <-results
         }
     }
    @@ -168,7 +182,7 @@ there are 3 workers operating concurrently.

    -
    $ time go run worker-pools.go 
    +          
    $ time go run worker-pools.go 
     worker 1 started  job 1
     worker 2 started  job 2
     worker 3 started  job 3
    @@ -190,7 +204,7 @@ there are 3 workers operating concurrently.

    -
    real    0m2.358s
    +          
    real    0m2.358s
     
    @@ -207,5 +221,10 @@ there are 3 workers operating concurrently.

    by Mark McGranaghan | source | license

    + + diff --git a/public/writing-files b/public/writing-files index ca974bd..2969c77 100644 --- a/public/writing-files +++ b/public/writing-files @@ -5,6 +5,20 @@ Go by Example: Writing Files +

    Go by Example: Writing Files

    @@ -19,7 +33,7 @@ ones we saw earlier for reading.

    - + @@ -28,10 +42,8 @@ ones we saw earlier for reading.

    - - - -
    package main
    +            
    +          
    package main
     
    @@ -43,7 +55,7 @@ ones we saw earlier for reading.

    -
    import (
    +          
    import (
         "bufio"
         "fmt"
         "io/ioutil"
    @@ -60,7 +72,7 @@ ones we saw earlier for reading.

    -
    func check(e error) {
    +          
    func check(e error) {
         if e != nil {
             panic(e)
         }
    @@ -76,7 +88,7 @@ ones we saw earlier for reading.

    -
    func main() {
    +          
    func main() {
     
    @@ -90,7 +102,7 @@ bytes) into a file.

    -
        d1 := []byte("hello\ngo\n")
    +          
        d1 := []byte("hello\ngo\n")
         err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
         check(err)
     
    @@ -105,7 +117,7 @@ bytes) into a file.

    -
        f, err := os.Create("/tmp/dat2")
    +          
        f, err := os.Create("/tmp/dat2")
         check(err)
     
    @@ -120,7 +132,7 @@ after opening a file.

    -
        defer f.Close()
    +          
        defer f.Close()
     
    @@ -133,7 +145,7 @@ after opening a file.

    -
        d2 := []byte{115, 111, 109, 101, 10}
    +          
        d2 := []byte{115, 111, 109, 101, 10}
         n2, err := f.Write(d2)
         check(err)
         fmt.Printf("wrote %d bytes\n", n2)
    @@ -149,7 +161,7 @@ after opening a file.

    -
        n3, err := f.WriteString("writes\n")
    +          
        n3, err := f.WriteString("writes\n")
         fmt.Printf("wrote %d bytes\n", n3)
     
    @@ -163,7 +175,7 @@ after opening a file.

    -
        f.Sync()
    +          
        f.Sync()
     
    @@ -177,7 +189,7 @@ to the buffered readers we saw earlier.

    -
        w := bufio.NewWriter(f)
    +          
        w := bufio.NewWriter(f)
         n4, err := w.WriteString("buffered\n")
         fmt.Printf("wrote %d bytes\n", n4)
     
    @@ -193,7 +205,7 @@ been applied to the underlying writer.

    -
        w.Flush()
    +          
        w.Flush()
     
    @@ -205,7 +217,7 @@ been applied to the underlying writer.

    -
    }
    +          
    }
     
    @@ -222,7 +234,7 @@ been applied to the underlying writer.

    -
    $ go run writing-files.go 
    +          
    $ go run writing-files.go 
     wrote 5 bytes
     wrote 7 bytes
     wrote 9 bytes
    @@ -238,7 +250,7 @@ been applied to the underlying writer.

    -
    $ cat /tmp/dat1
    +          
    $ cat /tmp/dat1
     hello
     go
     $ cat /tmp/dat2
    @@ -258,7 +270,7 @@ we’ve just seen to the stdin and stdout streams.
               
               
                 
    -            
    +          
               
             
             
    @@ -273,5 +285,10 @@ we’ve just seen to the stdin and stdout streams.
             by Mark McGranaghan | source | license
           

    + + diff --git a/public/xml b/public/xml new file mode 100644 index 0000000..e463b37 --- /dev/null +++ b/public/xml @@ -0,0 +1,288 @@ + + + + + Go by Example: XML + + + + +
    +

    Go by Example: XML

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

    Go offers built-in support for XML and XML-like +formats with the encoding.xml package.

    + +
    + + +
    + + + +
    package main
    +
    + +
    + + + +
    import (
    +    "encoding/xml"
    +    "fmt"
    +)
    +
    + +
    +

    This type will be mapped to XML. Similarly to the +JSON examples, field tags contain directives for the +encoder and decoder. Here we use some special features +of the XML package: the XMLName field name dictates +the name of the XML element representing this struct; +id,attr means that the Id field is an XML +attribute rather than a nested element.

    + +
    + +
    type Plant struct {
    +    XMLName xml.Name `xml:"plant"`
    +    Id      int      `xml:"id,attr"`
    +    Name    string   `xml:"name"`
    +    Origin  []string `xml:"origin"`
    +}
    +
    + +
    + + + +
    func (p Plant) String() string {
    +    return fmt.Sprintf("Plant id=%v, name=%v, origin=%v",
    +        p.Id, p.Name, p.Origin)
    +}
    +
    + +
    + + + +
    func main() {
    +    coffee := &Plant{Id: 27, Name: "Coffee"}
    +    coffee.Origin = []string{"Ethiopia", "Brazil"}
    +
    + +
    +

    Emit XML representing our plant; using +MarshalIndent to produce a more +human-readable output.

    + +
    + +
        out, _ := xml.MarshalIndent(coffee, " ", "  ")
    +    fmt.Println(string(out))
    +
    + +
    +

    To add a generic XML header to the output, append +it explicitly.

    + +
    + +
        fmt.Println(xml.Header + string(out))
    +
    + +
    +

    Use Unmarhshal to parse a stream of bytes with XML +into a data structure. If the XML is malformed or +cannot be mapped onto Plant, a descriptive error +will be returned.

    + +
    + +
        var p Plant
    +    if err := xml.Unmarshal(out, &p); err != nil {
    +        panic(err)
    +    }
    +    fmt.Println(p)
    +
    + +
    + + + +
        tomato := &Plant{Id: 81, Name: "Tomato"}
    +    tomato.Origin = []string{"Mexico", "California"}
    +
    + +
    +

    The parent>child>plant field tag tells the encoder +to nest all plants under <parent><child>...

    + +
    + +
        type Nesting struct {
    +        XMLName xml.Name `xml:"nesting"`
    +        Plants  []*Plant `xml:"parent>child>plant"`
    +    }
    +
    + +
    + + + +
        nesting := &Nesting{}
    +    nesting.Plants = []*Plant{coffee, tomato}
    +
    + +
    + + + +
        out, _ = xml.MarshalIndent(nesting, " ", "  ")
    +    fmt.Println(string(out))
    +}
    +
    + +
    + + + + + + + + +
    + + + +
    $ go run xml.go
    + <plant id="27">
    +   <name>Coffee</name>
    +   <origin>Ethiopia</origin>
    +   <origin>Brazil</origin>
    + </plant>
    +<?xml version="1.0" encoding="UTF-8"?>
    + <plant id="27">
    +   <name>Coffee</name>
    +   <origin>Ethiopia</origin>
    +   <origin>Brazil</origin>
    + </plant>
    +Plant id=27, name=Coffee, origin=[Ethiopia Brazil]
    + <nesting>
    +   <parent>
    +     <child>
    +       <plant id="27">
    +         <name>Coffee</name>
    +         <origin>Ethiopia</origin>
    +         <origin>Brazil</origin>
    +       </plant>
    +       <plant id="81">
    +         <name>Tomato</name>
    +         <origin>Mexico</origin>
    +         <origin>California</origin>
    +       </plant>
    +     </child>
    +   </parent>
    + </nesting>
    +
    + +
    + + +

    + Next example: Time. +

    + + +
    + + + + diff --git a/templates/clipboard.png b/templates/clipboard.png new file mode 100644 index 0000000..0e262fe Binary files /dev/null and b/templates/clipboard.png differ diff --git a/templates/example.tmpl b/templates/example.tmpl index c9cfb7d..74bdc12 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -5,6 +5,20 @@ Go by Example: {{.Name}} +

    Go by Example: {{.Name}}

    @@ -16,10 +30,8 @@ {{.DocsRendered}} - {{if .CodeRun}} - - {{end}} - {{.CodeRendered}} + {{if .CodeRun}}{{end}} + {{.CodeRendered}} {{end}} @@ -34,5 +46,10 @@ by Mark McGranaghan | source | license

    + + diff --git a/templates/site.css b/templates/site.css index 4808e32..7e93afb 100644 --- a/templates/site.css +++ b/templates/site.css @@ -136,11 +136,17 @@ pre, code { font-size: 14px; line-height: 18px; font-family: 'Menlo', 'Monaco', 'Consolas', 'Lucida Console', monospace; } -img.run { +img.copy, img.run { height: 16px; width: 16px; float: right } +img.copy, img.run { + cursor: pointer; +} +img.copy { + margin-right: 4px; +} /* Syntax highlighting */ body .hll { background-color: #ffffcc } diff --git a/templates/site.js b/templates/site.js new file mode 100644 index 0000000..752e656 --- /dev/null +++ b/templates/site.js @@ -0,0 +1,17 @@ +/*! + * clipboard.js v1.5.13 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function r(c,a){if(!n[c]){if(!e[c]){var l="function"==typeof require&&require;if(!a&&l)return l(c,!0);if(i)return i(c,!0);var s=new Error("Cannot find module '"+c+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[c]={exports:{}};e[c][0].call(u.exports,function(t){var n=e[c][1][t];return r(n?n:t)},u,u.exports,t,e,n,o)}return n[c].exports}for(var i="function"==typeof require&&require,c=0;c 0 { + example.PrevExample = examples[i-1] + } if i < (len(examples) - 1) { example.NextExample = examples[i+1] } @@ -301,10 +313,17 @@ 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/site.js", siteDir+"/site.js") copyFile("templates/favicon.ico", siteDir+"/favicon.ico") copyFile("templates/404.html", siteDir+"/404.html") copyFile("templates/play.png", siteDir+"/play.png") + copyFile("templates/clipboard.png", siteDir+"/clipboard.png") examples := parseExamples() renderIndex(examples) renderExamples(examples)