Resolve conflicts
This commit is contained in:
commit
a10f0a358a
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
public/* linguist-generated=true
|
||||
vendor/* linguist-vendored=true
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
*.pyc
|
||||
.idea
|
||||
.vscode
|
||||
|
@ -15,4 +15,4 @@ script:
|
||||
- tools/build
|
||||
|
||||
env:
|
||||
- VERBOSE=1
|
||||
- VERBOSE=1 TESTING=1
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
a4190094ea0405b5f2733101beb97939a1d43aee
|
||||
KDr9EMMPMgi
|
||||
8ebec0be3b167021c96b8b497d0e8c0a2ea99385
|
||||
F2pJfduyQiA
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
c20da14820b656c867790f2e99bc37140babca8c
|
||||
y_QTcqdkvZh
|
||||
e0148b9b4acb01e849b8f678cba03f549d250c44
|
||||
V3oV1bvh94k
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
eb022977181884c2ab0f2b69e50311769e67a509
|
||||
8lmP8beav0p
|
||||
0d5a9de912e2a4a18943e082e2f8107cb75d0ce4
|
||||
fe9If6OhYMk
|
||||
|
@ -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.
|
||||
|
@ -1,2 +1,2 @@
|
||||
d961fc0e0074aed46cfd1516efdadea78781af56
|
||||
BJB_npWH516
|
||||
28456737ea996664bdaeb8e1e821d95697d00646
|
||||
8hI6oPNEfyh
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "os"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
41c970a1ef29ad2a05307e6c783ff52ab80eaccd
|
||||
6pFdjf800jj
|
||||
9c80d495201148bbeb0fd0a5a2ce1735aeb34b60
|
||||
myJy_-H8Fo_Q
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
e2ba0461c090789168c712cc7ed0f66aab09a8c8
|
||||
klFR5DitrCy
|
||||
ab08bf890dcd87b807956b5bee441d59efe458e3
|
||||
lPaZodnG9TF
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "math"
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// `const` declares a constant value.
|
||||
const s string = "constant"
|
||||
|
@ -1,2 +1,2 @@
|
||||
2f2ec3a5ff4eef280199da1908eed261346fb40e
|
||||
VhP0f8moZd3
|
||||
7cc09460e8dc6fffd0ba811679f92a85eb51e927
|
||||
gmjHSglwLic
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
570699fc50a1d39e9d0ad6a4461aef3248b080e1
|
||||
xPbQ5SGkH2O
|
||||
4fc23579a9bd5d8512884902394f4dce51eb7d60
|
||||
QJJ2R6kv6K5
|
||||
|
95
examples/directories/directories.go
Normal file
95
examples/directories/directories.go
Normal file
@ -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
|
||||
}
|
2
examples/directories/directories.hash
Normal file
2
examples/directories/directories.hash
Normal file
@ -0,0 +1,2 @@
|
||||
83f67db91816b4544072d0a4d099111a21c60723
|
||||
-7kWq0PmATF
|
15
examples/directories/directories.sh
Normal file
15
examples/directories/directories.sh
Normal file
@ -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
|
@ -5,9 +5,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "os"
|
||||
import "strings"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
4d0832c5a1ddd4e95474791e8802c15452358214
|
||||
CZJ4R_uu6Uu
|
||||
db2e203da519a22943753295e9cc27d89e4347b0
|
||||
bKuCOOD16KH
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
61a498229c8878a97d729cfdd215e5f3960f87ac
|
||||
eN1Qv2ATB-C
|
||||
184c8f3e94dd28176be81956115ac417e33513a6
|
||||
3uYNHHRplmQ
|
||||
|
@ -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.
|
||||
|
@ -1,2 +1,2 @@
|
||||
210ba0f8196006c0380acaec01655816848ef168
|
||||
mP_ZR1qjUvA
|
||||
ed58ad3162d93c723d3efe72529a61ce7041fe13
|
||||
vrwN32gxaYx
|
||||
|
@ -10,9 +10,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "syscall"
|
||||
import "os"
|
||||
import "os/exec"
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
b527bbb76a42dd4bae541b73a7377b7e83e79905
|
||||
bf11ADw-2Ho
|
||||
e6b4830d4264f307506b54726ec79b25a0363874
|
||||
ahZjpJaZz44
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
dc0bb3eaafa045d6aa05e88aff39322a1ccf822e
|
||||
vDaM0-MGJ_k
|
||||
2316e6c8e364e2066c6bd350dc9b0b2af85b63fe
|
||||
OX997ykuOGx
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
ac2909e69be30862bd9f18db954d9ee10f57ec6a
|
||||
8GBAW6yNcbn
|
||||
a4e8d30b7a6f3a6abd96b916d81ce5930bad94f9
|
||||
lNuS9ysZmxH
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "math"
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Here's a basic interface for geometric shapes.
|
||||
type geometry interface {
|
||||
|
@ -1,2 +1,2 @@
|
||||
3547b935d1e0322c0fb696726c27cae53a275e0a
|
||||
0EwsqIn3TTi
|
||||
aac1328f5a04568272b82753ff0762b9eacff4fc
|
||||
hXTlbUAGcvn
|
||||
|
@ -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"`
|
||||
|
@ -1,2 +1,2 @@
|
||||
d4dc2281f64061f077d8f1e9687538f41a339b25
|
||||
xC6SHbzGBZC
|
||||
c751bc7223b8bc615f82fe7643ab98ce2b80240f
|
||||
ROikmz5tRhZ
|
||||
|
@ -5,8 +5,10 @@ package main
|
||||
|
||||
// The built-in package `strconv` provides the number
|
||||
// parsing.
|
||||
import "strconv"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
0d2155e9863a73c098d44637e92403d7f5e8e965
|
||||
NZh4LjhguvN
|
||||
0191c7e43706640207c403ba92dd2272d66fc868
|
||||
t2q4KnWWTAw
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import "math/rand"
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
8e97de760147b061dd09939db294c892211b6b80
|
||||
jiJaIjxL2sP
|
||||
9374869a809d28ea784a9e1181b4aa1988018776
|
||||
DVHO7SjJZnp
|
||||
|
@ -6,8 +6,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
edad78bf3b36ddc9bec30b344b8a72be4de90f3b
|
||||
l4uDE-RCDpa
|
||||
357d83df3e48675eb1e135188cb9f07448c1f146
|
||||
AJ-MJephNib
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "bytes"
|
||||
import "fmt"
|
||||
import "regexp"
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
7cde6b9af5cf6c47606001dd54eee468a6c61dbb
|
||||
qR5gn2l0AGa
|
||||
de24265897edf1d3913e3b87f70757284a66ecea
|
||||
urHlUNDVenk
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
8d743edffd7de6bf7bccdf4437f45672b6adc75e
|
||||
ZdSOPe1Gj13
|
||||
6e1125087bc036ebd905452300575f160d683918
|
||||
yF-xgN7Xf9P
|
||||
|
@ -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"
|
||||
|
@ -1,2 +1,2 @@
|
||||
6a896270e34f2696b881a8fa7e68bfff57dee51f
|
||||
1oT-5GBUkLr
|
||||
4cda643ba233014fe6b30966c37d4d0fcd4edbe8
|
||||
oqcrTfY4Ykd
|
||||
|
@ -7,10 +7,12 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "os"
|
||||
import "os/signal"
|
||||
import "syscall"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
9720d747e3ab2893df508a70cbb341c90fdd7ca1
|
||||
9koJAW1raI5
|
||||
1e43c6f63f1d57e1a52c89f52d35b68757e9676b
|
||||
_6oj-T3Gko2
|
||||
|
@ -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`
|
||||
|
@ -1,2 +1,2 @@
|
||||
6a04058b564d5741815e523f97f240ee6563cb15
|
||||
y3kuCwIFRYK
|
||||
f7d0b7840dd12601fb86946f9dc4c38fb1c0501f
|
||||
Jtxf94x94Hx
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "sort"
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
4e576421f2bdbd11847c367d223bd30d0e301990
|
||||
e6hp3Rn-oH6
|
||||
e11e944d34b21e75ce4f7c91026d4200ce592dc5
|
||||
tAWAkRlBJNX
|
||||
|
@ -7,9 +7,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "io/ioutil"
|
||||
import "os/exec"
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
0b676b93e41ac5434003c194bc038d5f3ce76bc8
|
||||
6HRWVK5gPYU
|
||||
cc68e4290f10209ad2fa8db74fdfaea7fdb44d5c
|
||||
QS_Nkoe8VLG
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type point struct {
|
||||
x, y int
|
||||
|
@ -1,2 +1,2 @@
|
||||
5f39ae6d8f26d59a688a9a9d7d13a5c1d0f7a08b
|
||||
CkBQ3CFpHQ9
|
||||
12b245c576b43537c092a5b84995ebca8ce78a57
|
||||
vmYSdxfUcRh
|
||||
|
@ -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.
|
||||
|
@ -1,2 +1,2 @@
|
||||
17aa523bbd606fa0b624fae44b89812d46330755
|
||||
Vn4D3y4_711
|
||||
bf39c7540bd78eba38eb5a9047a9d0ffc7235f85
|
||||
xoRUhG86wsF
|
||||
|
@ -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)
|
||||
|
@ -1,2 +1,2 @@
|
||||
49cad39331ee5e9fb8d8dad99d3aff7f18a4e6d0
|
||||
XMZpGsF4sWM
|
||||
c5caaf1eefaf084d688afb70d2ee5884a4983182
|
||||
00Yiw6xuICq
|
||||
|
@ -6,3 +6,4 @@ $ go run structs.go
|
||||
Sean
|
||||
50
|
||||
51
|
||||
&{Jon 42}
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
b47004b3e3b6d787ea98642dc5b955df57cd2bcd
|
||||
TJ4Az0KuLfL
|
||||
2486fc553301cdeac9a26f3d0b3aed4143d9f4f0
|
||||
ZcDzdx3nYQn
|
||||
|
@ -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)
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
5f7d0c43988d7dce235adb06ec02f4d2026b7f83
|
||||
pxE20wGTFjv
|
@ -0,0 +1,3 @@
|
||||
$ go run temporary-files-and-directories.go
|
||||
Temp file name: /tmp/sample610887201
|
||||
Temp dir name: /tmp/sampledir898854668
|
@ -6,8 +6,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@ -16,10 +18,17 @@ 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 {
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
case t := <-ticker.C:
|
||||
fmt.Println("Tick at", t)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Tickers can be stopped like timers. Once a ticker
|
||||
@ -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")
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
7dc6447323f493f72aa70952bf3e3f2c6156f82f
|
||||
Rgc_UDvHv6a
|
||||
4a42333d14f902e890902343c7bd9b9c735fd8ad
|
||||
n1q1sSGEvmv
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := fmt.Println
|
||||
|
@ -1,2 +1,2 @@
|
||||
1f9962260f5c92efe57db0b96099b3dd06c90333
|
||||
nHAisH6amZG
|
||||
9e3f17061fef280191e3e8518365e231e17a5d5a
|
||||
1410R7Fcyx0
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := fmt.Println
|
||||
|
@ -1,2 +1,2 @@
|
||||
b6308f1fea7665e89a28f54aac6cb49b95685eb5
|
||||
PZMCzzaJURJ
|
||||
c47d853fa7527a652ce78b0285e452c6cd740050
|
||||
u-7i_p8BHVt
|
||||
|
@ -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)
|
||||
|
@ -1,2 +1,2 @@
|
||||
93343e1aacb14f818c87732914c29ba57afab245
|
||||
MgcfA-xpJO9
|
||||
b8d3e745539b24d3530ca21efcdc924f08769edb
|
||||
TYJgoFjlTd6
|
||||
|
@ -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.
|
||||
|
@ -6,8 +6,10 @@
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
e10c601ab3b702dfcea728c1edb31673561484b5
|
||||
pybl9hRvJq2
|
||||
e8e501d6083bea786629ca5e485e8b18caab4815
|
||||
pLnKEIesooU
|
||||
|
@ -3,9 +3,11 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "net"
|
||||
import "net/url"
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
b7a0813e9413bfcc956cc58b850f655dd129ebb7
|
||||
AL79Lv-9CWo
|
||||
babc12f5066652f4cb0151231c06f1037298ff28
|
||||
M218D9Tldlr
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
bc69c6602d438413dcb9ceac112299ee253e4575
|
||||
yuHsGf712D1
|
||||
9b30cdfc3f46d634c3b8671a7ae1551c133fb6e2
|
||||
IiKZ-nj-nKY
|
||||
|
69
examples/xml/xml.go
Normal file
69
examples/xml/xml.go
Normal file
@ -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 `<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))
|
||||
}
|
2
examples/xml/xml.hash
Normal file
2
examples/xml/xml.hash
Normal file
@ -0,0 +1,2 @@
|
||||
18ada773098bca38778a58b438d6af70529f18b0
|
||||
qd9Ii_3AW0s
|
29
examples/xml/xml.sh
Normal file
29
examples/xml/xml.sh
Normal file
@ -0,0 +1,29 @@
|
||||
$ 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>
|
23
public/arrays
generated
23
public/arrays
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Arrays</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'switch';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'slices';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="arrays">
|
||||
<h2><a href="./">Go by Example</a>: Arrays</h2>
|
||||
@ -28,9 +42,7 @@ specific length.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/W7NwfDq8Vdw">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/W7NwfDq8Vdw"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -192,5 +204,10 @@ typical Go. We’ll look at slices next.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/arrays">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func main() {\u000A');codeLines.push(' var a [5]int\u000A fmt.Println(\"emp:\", a)\u000A');codeLines.push(' a[4] = 100\u000A fmt.Println(\"set:\", a)\u000A fmt.Println(\"get:\", a[4])\u000A');codeLines.push(' fmt.Println(\"len:\", len(a))\u000A');codeLines.push(' b := [5]int{1, 2, 3, 4, 5}\u000A fmt.Println(\"dcl:\", b)\u000A');codeLines.push(' var twoD [2][3]int\u000A for i := 0; i \x3C 2; i++ {\u000A for j := 0; j \x3C 3; j++ {\u000A twoD[i][j] = i + j\u000A }\u000A }\u000A fmt.Println(\"2d: \", twoD)\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
88
public/atomic-counters
generated
88
public/atomic-counters
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Atomic Counters</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'rate-limiting';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'mutexes';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="atomic-counters">
|
||||
<h2><a href="./">Go by Example</a>: Atomic Counters</h2>
|
||||
@ -32,9 +46,7 @@ counters</em> accessed by multiple goroutines.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/KDr9EMMPMgi">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/F2pJfduyQiA"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -47,9 +59,11 @@ counters</em> accessed by multiple goroutines.</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="s">"fmt"</span>
|
||||
<span class="kn">import</span> <span class="s">"time"</span>
|
||||
<span class="kn">import</span> <span class="s">"sync/atomic"</span>
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="s">"fmt"</span>
|
||||
<span class="s">"sync"</span>
|
||||
<span class="s">"sync/atomic"</span>
|
||||
<span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -83,16 +97,28 @@ counters</em> accessed by multiple goroutines.</p>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>To simulate concurrent updates, we’ll start 50
|
||||
goroutines that each increment the counter about
|
||||
once a millisecond.</p>
|
||||
<p>A WaitGroup will help us wait for all goroutines
|
||||
to finish their work.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre> <span class="kd">var</span> <span class="nx">wg</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">WaitGroup</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>We’ll start 50 goroutines that each increment the
|
||||
counter exactly 1000 times.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p"><</span> <span class="mi">50</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
|
||||
<span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">for</span> <span class="p">{</span>
|
||||
<span class="nx">wg</span><span class="p">.</span><span class="nx">Add</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -108,7 +134,8 @@ address of our <code>ops</code> counter with the
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre> <span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<div class="highlight"><pre> <span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">for</span> <span class="nx">c</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">c</span> <span class="p"><</span> <span class="mi">1000</span><span class="p">;</span> <span class="nx">c</span><span class="o">++</span> <span class="p">{</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -116,13 +143,13 @@ address of our <code>ops</code> counter with the
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Wait a bit between increments.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre> <span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Millisecond</span><span class="p">)</span>
|
||||
<div class="highlight"><pre> <span class="nx">atomic</span><span class="p">.</span><span class="nx">AddUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">wg</span><span class="p">.</span><span class="nx">Done</span><span class="p">()</span>
|
||||
<span class="p">}()</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
@ -132,12 +159,12 @@ address of our <code>ops</code> counter with the
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Wait a second to allow some ops to accumulate.</p>
|
||||
<p>Wait until all the goroutines are done.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre> <span class="nx">time</span><span class="p">.</span><span class="nx">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span>
|
||||
<div class="highlight"><pre> <span class="nx">wg</span><span class="p">.</span><span class="nx">Wait</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -145,18 +172,16 @@ address of our <code>ops</code> counter with the
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>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 <code>opsFinal</code> via
|
||||
<code>LoadUint64</code>. As above we need to give this
|
||||
function the memory address <code>&ops</code> from which to
|
||||
fetch the value.</p>
|
||||
<p>It’s safe to access <code>ops</code> 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
|
||||
<code>atomic.LoadUint64</code>.</p>
|
||||
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<div class="highlight"><pre> <span class="nx">opsFinal</span> <span class="o">:=</span> <span class="nx">atomic</span><span class="p">.</span><span class="nx">LoadUint64</span><span class="p">(</span><span class="o">&</span><span class="nx">ops</span><span class="p">)</span>
|
||||
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"ops:"</span><span class="p">,</span> <span class="nx">opsFinal</span><span class="p">)</span>
|
||||
<div class="highlight"><pre> <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"ops:"</span><span class="p">,</span> <span class="nx">ops</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
|
||||
@ -169,14 +194,18 @@ fetch the value.</p>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Running the program shows that we executed about
|
||||
40,000 operations.</p>
|
||||
<p>We expect to get exactly 50,000 operations. Had we
|
||||
used the non-atomic <code>ops++</code> 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 <code>-race</code> flag.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre><span class="gp">$</span> go run atomic-counters.go
|
||||
<span class="go">ops: 41419</span>
|
||||
<span class="go">ops: 50000</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -205,5 +234,10 @@ state.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/atomic-counters">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A \"fmt\"\u000A \"sync\"\u000A \"sync/atomic\"\u000A)\u000A');codeLines.push('func main() {\u000A');codeLines.push(' var ops uint64\u000A');codeLines.push(' var wg sync.WaitGroup\u000A');codeLines.push(' for i := 0; i \x3C 50; i++ {\u000A wg.Add(1)\u000A');codeLines.push(' go func() {\u000A for c := 0; c \x3C 1000; c++ {\u000A');codeLines.push(' atomic.AddUint64(&ops, 1)\u000A }\u000A wg.Done()\u000A }()\u000A }\u000A');codeLines.push(' wg.Wait()\u000A');codeLines.push(' fmt.Println(\"ops:\", ops)\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
29
public/base64-encoding
generated
29
public/base64-encoding
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Base64 Encoding</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'sha1-hashes';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'reading-files';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="base64-encoding">
|
||||
<h2><a href="./">Go by Example</a>: Base64 Encoding</h2>
|
||||
@ -28,9 +42,7 @@ encoding/decoding</a>.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/y_QTcqdkvZh">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/V3oV1bvh94k"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -46,8 +58,10 @@ save us some space below.</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="nx">b64</span> <span class="s">"encoding/base64"</span>
|
||||
<span class="kn">import</span> <span class="s">"fmt"</span>
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="nx">b64</span> <span class="s">"encoding/base64"</span>
|
||||
<span class="s">"fmt"</span>
|
||||
<span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -175,5 +189,10 @@ but they both decode to the original string as desired.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/base64-encoding">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A b64 \"encoding/base64\"\u000A \"fmt\"\u000A)\u000A');codeLines.push('func main() {\u000A');codeLines.push(' data := \"abc123!?$*&()\'-=@~\"\u000A');codeLines.push(' sEnc := b64.StdEncoding.EncodeToString([]byte(data))\u000A fmt.Println(sEnc)\u000A');codeLines.push(' sDec, _ := b64.StdEncoding.DecodeString(sEnc)\u000A fmt.Println(string(sDec))\u000A fmt.Println()\u000A');codeLines.push(' uEnc := b64.URLEncoding.EncodeToString([]byte(data))\u000A fmt.Println(uEnc)\u000A uDec, _ := b64.URLEncoding.DecodeString(uEnc)\u000A fmt.Println(string(uDec))\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
23
public/channel-buffering
generated
23
public/channel-buffering
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Channel Buffering</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'channels';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'channel-synchronization';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="channel-buffering">
|
||||
<h2><a href="./">Go by Example</a>: Channel Buffering</h2>
|
||||
@ -32,9 +46,7 @@ those values.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/mPoF-Xi-rip">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/mPoF-Xi-rip"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -139,5 +151,10 @@ concurrent receive.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/channel-buffering">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func main() {\u000A');codeLines.push(' messages := make(chan string, 2)\u000A');codeLines.push(' messages \x3C- \"buffered\"\u000A messages \x3C- \"channel\"\u000A');codeLines.push(' fmt.Println(\x3C-messages)\u000A fmt.Println(\x3C-messages)\u000A}\u000A');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
23
public/channel-directions
generated
23
public/channel-directions
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Channel Directions</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'channel-synchronization';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'select';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="channel-directions">
|
||||
<h2><a href="./">Go by Example</a>: Channel Directions</h2>
|
||||
@ -30,9 +44,7 @@ the program.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/Jnn9_9hC48c">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/Jnn9_9hC48c"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -131,5 +143,10 @@ receive on this channel.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/channel-directions">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func ping(pings chan\x3C- string, msg string) {\u000A pings \x3C- msg\u000A}\u000A');codeLines.push('func pong(pings \x3C-chan string, pongs chan\x3C- string) {\u000A msg := \x3C-pings\u000A pongs \x3C- msg\u000A}\u000A');codeLines.push('func main() {\u000A pings := make(chan string, 1)\u000A pongs := make(chan string, 1)\u000A ping(pings, \"passed message\")\u000A pong(pings, pongs)\u000A fmt.Println(\x3C-pongs)\u000A}\u000A');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
29
public/channel-synchronization
generated
29
public/channel-synchronization
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Channel Synchronization</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'channel-buffering';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'channel-directions';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="channel-synchronization">
|
||||
<h2><a href="./">Go by Example</a>: Channel Synchronization</h2>
|
||||
@ -31,9 +45,7 @@ you may prefer to use a <a href="waitgroups">WaitGroup</a>.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/8lmP8beav0p">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/fe9If6OhYMk"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -46,8 +58,10 @@ you may prefer to use a <a href="waitgroups">WaitGroup</a>.</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="s">"fmt"</span>
|
||||
<span class="kn">import</span> <span class="s">"time"</span>
|
||||
<div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="s">"fmt"</span>
|
||||
<span class="s">"time"</span>
|
||||
<span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</td>
|
||||
@ -168,5 +182,10 @@ started.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/channel-synchronization">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A \"fmt\"\u000A \"time\"\u000A)\u000A');codeLines.push('func worker(done chan bool) {\u000A fmt.Print(\"working...\")\u000A time.Sleep(time.Second)\u000A fmt.Println(\"done\")\u000A');codeLines.push(' done \x3C- true\u000A}\u000A');codeLines.push('func main() {\u000A');codeLines.push(' done := make(chan bool, 1)\u000A go worker(done)\u000A');codeLines.push(' \x3C-done\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
23
public/channels
generated
23
public/channels
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Channels</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'goroutines';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'channel-buffering';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="channels">
|
||||
<h2><a href="./">Go by Example</a>: Channels</h2>
|
||||
@ -30,9 +44,7 @@ goroutine.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/bRGMAqinovA">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/bRGMAqinovA"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -154,5 +166,10 @@ message without having to use any other synchronization.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/channels">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func main() {\u000A');codeLines.push(' messages := make(chan string)\u000A');codeLines.push(' go func() { messages \x3C- \"ping\" }()\u000A');codeLines.push(' msg := \x3C-messages\u000A fmt.Println(msg)\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
BIN
public/clipboard.png
generated
Normal file
BIN
public/clipboard.png
generated
Normal file
Binary file not shown.
After Width: | Height: | Size: 488 B |
23
public/closing-channels
generated
23
public/closing-channels
generated
@ -5,6 +5,20 @@
|
||||
<title>Go by Example: Closing Channels</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'non-blocking-channel-operations';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'range-over-channels';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="closing-channels">
|
||||
<h2><a href="./">Go by Example</a>: Closing Channels</h2>
|
||||
@ -29,9 +43,7 @@ completion to the channel’s receivers.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/mkz69rVMHs6">
|
||||
<img title="Run code" class="run" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ1SURBVCjPY/j//z8DMu7o6GAAgpQgD9tLqcmJH4KDg14aaik/MtdXe2ZjY6OCrh6Fs2jRYmZ9Pd05M9uL/u9dPfU/CLS0dfxvKIz/X5Dg/z8pKdkGqwGpqakMUdExDHJSYqt37tjxf+qUSf9rc2P+79298/+RA3v+H1zV///o6r7/DrbWFQkJiQwxMTGoBjAxMTpKiQmuqMuP/f/xw/v/J0+f/W9tbvTfxVLn/8rJVf+v757z/96hRf8TQtxuCQmLMjk4OKAawMfDVWVvrvd85eTq/7tXTP6/e/XM/22lif9LCnL+b13Q/v/Kzln/L++c/X/7/Jb/VpYWuZFRUagGAAErEBtlxvi+vn944f9L26cDNcz6v21R9/8zm6aC2SBDbu+f/78kK+4/L79AO7oBYCAqxD/57JZp/y/tmPX/wrYZ/6+CbAayD6zs/78daBjIgPayFJAGG6wGAIFAcpjH/dv7F4ANABuya/b/Od3l/ye2V/+/tnv2/7ldxSANmrgMYGBhZg7fuagD7GyYIeeBrrqwdRrQgLn/l02sBGkwwWkAEAjV5EZ/vQV0LswAGAYZsLC3DKTBAJ8BzCkRni/uHFyIYcAtoNc6ypL/ANVIohigrKwMxqqqqgxMzKzM6VHeL+6iGQAKzDtAV5XlJv3n5uFLRTHgzZs3YPzz50+GwqJiPitD9Y8Pjy4BB+CNvfP+3wUmIpAhhckhr3X19LodHZ28UQxQU1MDYw0NDQYBAQEeoBOTK7JjP2xf3Pt/bkfB/4KkoDcKMmIL5OXlFerq6hhu3rzJgC8MwMDYxGSfm5vbVn9/f0cgVxAkpqioyFBfX49iAACbTAK+xT3CzgAAAABJRU5ErkJggg==" />
|
||||
</a>
|
||||
<a href="http://play.golang.org/p/mkz69rVMHs6"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre></div>
|
||||
|
||||
@ -180,5 +192,10 @@ example: <code>range</code> over channels.</p>
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/closing-channels">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func main() {\u000A jobs := make(chan int, 5)\u000A done := make(chan bool)\u000A');codeLines.push(' go func() {\u000A for {\u000A j, more := \x3C-jobs\u000A if more {\u000A fmt.Println(\"received job\", j)\u000A } else {\u000A fmt.Println(\"received all jobs\")\u000A done \x3C- true\u000A return\u000A }\u000A }\u000A }()\u000A');codeLines.push(' for j := 1; j \x3C= 3; j++ {\u000A jobs \x3C- j\u000A fmt.Println(\"sent job\", j)\u000A }\u000A close(jobs)\u000A fmt.Println(\"sent all jobs\")\u000A');codeLines.push(' \x3C-done\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user