Created
July 16, 2016 20:14
-
-
Save ruandao/0c36d2eca2fb0ccfdb2bcb802b0f773e to your computer and use it in GitHub Desktop.
golang tour finished
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import "fmt" | |
| func main() { | |
| ch := make(chan int, 2) | |
| ch <- 1 | |
| ch <- 2 | |
| fmt.Println(<-ch) | |
| fmt.Println(<- ch) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import "fmt" | |
| func sum(s []int, c chan int) { | |
| sum := 0 | |
| for _, v := range s { | |
| sum += v | |
| } | |
| c <- sum | |
| } | |
| func main() { | |
| s := []int{7, 2, 8, -9, 4, 0} | |
| c := make(chan int) | |
| go sum(s[:len(s)/2], c) | |
| go sum(s[len(s)/2:], c) | |
| x, y := <-c, <-c | |
| fmt.Println(x, y, x+y) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "time" | |
| "fmt" | |
| ) | |
| func main() { | |
| tick := time.Tick(100 * time.Millisecond) | |
| boom := time.After(500 * time.Millisecond) | |
| for { | |
| select { | |
| case <-tick: | |
| fmt.Println("tick.") | |
| case <- boom: | |
| fmt.Println("BOOM!") | |
| return | |
| default: | |
| fmt.Println(" .") | |
| time.Sleep(50 * time.Millisecond) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "golang.org/x/tour/tree" | |
| "fmt" | |
| ) | |
| type Tree struct { | |
| Left *Tree | |
| Value int | |
| Right *Tree | |
| } | |
| func EqualTree(t1, t2 *Tree) bool { | |
| if t1 == t2 { | |
| return true | |
| } | |
| if t1 == nil || t2 == nil { | |
| return false | |
| } | |
| if t1.Value != t2.Value { | |
| return false | |
| } | |
| return EqualTree(t1.Left, t2.Left) && | |
| EqualTree(t1.Right, t2.Right) | |
| } | |
| /* | |
| t shouldn't be nil | |
| */ | |
| func walkRecurse(t *tree.Tree, ch chan int) { | |
| if t == nil { | |
| return | |
| } | |
| ch <- t.Value | |
| walkRecurse(t.Left, ch) | |
| walkRecurse(t.Right, ch) | |
| } | |
| func Walk(t *tree.Tree, ch chan int) { | |
| walkRecurse(t, ch) | |
| close(ch) | |
| } | |
| func Same(t1, t2 *tree.Tree) bool { | |
| ch1 := make(chan int) | |
| ch2 := make(chan int) | |
| if t1 == t2 { | |
| return true | |
| } | |
| go Walk(t1, ch1) | |
| go Walk(t2, ch2) | |
| for { | |
| v1, ok1 := <- ch1 | |
| v2, ok2 := <- ch2 | |
| fmt.Printf("%v %v\n", v1, v2) | |
| if v1 != v2 || ok1 != ok2 { | |
| return false | |
| } | |
| if ok1 { | |
| return true | |
| } | |
| } | |
| } | |
| func main() { | |
| fmt.Println(Same(tree.New(1), tree.New(1))) | |
| fmt.Println(Same(tree.New(10), tree.New(4))) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "fmt" | |
| "time" | |
| "sync" | |
| ) | |
| type Fetcher interface { | |
| // Fetch returns the body of URL and | |
| // a slice of URLs found on that page. | |
| Fetch(url string) (body string, urls []string, err error) | |
| } | |
| type fetchObj struct { | |
| url string | |
| depth int | |
| } | |
| type MutexMap struct { | |
| m sync.Mutex | |
| urlCount map[string]int | |
| } | |
| func (mm *MutexMap)Inc(key string) int { | |
| mm.m.Lock() | |
| defer mm.m.Unlock() | |
| mm.urlCount[key]++ | |
| count := mm.urlCount[key] | |
| return count | |
| } | |
| var mutexM = &MutexMap{urlCount: make(map[string]int)} | |
| func craw(fo fetchObj, urlChan chan fetchObj, remainderChan chan int) { | |
| defer func() { | |
| remainderChan <- -1 | |
| }() | |
| if fo.depth == 0 { | |
| return | |
| } | |
| if mutexM.Inc(fo.url) > 1 { | |
| return | |
| } | |
| body, urls, err := fetcher.Fetch(fo.url) | |
| if err != nil { | |
| fmt.Println(err) | |
| return | |
| } | |
| fmt.Printf("found: %s %q\n", fo.url, body) | |
| for _, url := range urls { | |
| urlChan <- fetchObj{url, fo.depth - 1} | |
| remainderChan <- 1 | |
| } | |
| } | |
| // Crawl uses fetcher to recursively crawl | |
| // pages starting with url, to a maximum of depth. | |
| func Crawl(url string, depth int, fetcher Fetcher) { | |
| // TODO: Fetch URLs in parallel | |
| // TODO: Don't fetch the same URL twice. | |
| // This implementation doesn't do either | |
| defer fmt.Println("end") | |
| urlChan := make(chan fetchObj) | |
| remainderChan := make(chan int) | |
| fo := fetchObj{url, depth} | |
| count := 1 | |
| go craw(fo, urlChan, remainderChan) | |
| for { | |
| select { | |
| case fo = <- urlChan: | |
| go craw(fo, urlChan, remainderChan) | |
| case change := <- remainderChan: | |
| count += change | |
| if count == 0 { | |
| return | |
| } | |
| default: | |
| time.Sleep(100 * time.Millisecond) | |
| } | |
| } | |
| } | |
| func main() { | |
| Crawl("http://golang.org/", 4, fetcher) | |
| } | |
| // fakeFetcher is Fetcher that return canned results. | |
| type fakeFetcher map[string]*fakeResult | |
| type fakeResult struct { | |
| body string | |
| urls []string | |
| } | |
| func (f fakeFetcher) Fetch(url string) (string, []string, error) { | |
| if res, ok := f[url]; ok { | |
| return res.body, res.urls, nil | |
| } | |
| return "", nil, fmt.Errorf("not found: %s", url) | |
| } | |
| // fetcher is a populated fakeFetcher. | |
| var fetcher = fakeFetcher{ | |
| "http://golang.org/": &fakeResult{ | |
| "The Go Programming Language", | |
| []string{ | |
| "http://golang.org/pkg/", | |
| "http://golang.org/cmd/", | |
| }, | |
| }, | |
| "http://golang.org/pkg/": &fakeResult{ | |
| "Packages", | |
| []string{ | |
| "http://golang.org/", | |
| "http://golang.org/cmd/", | |
| "http://golang.org/pkg/fmt/", | |
| "http://golang.org/pkg/os/", | |
| }, | |
| }, | |
| "http://golang.org/pkg/fmt/": &fakeResult{ | |
| "Package fmt", | |
| []string{ | |
| "http://golang.org/", | |
| "http://golang.org/pkg/", | |
| }, | |
| }, | |
| "http://golang.org/pkg/os/": &fakeResult{ | |
| "Package os", | |
| []string{ | |
| "http://golang.org/", | |
| "http://golang.org/pkg/", | |
| }, | |
| }, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "time" | |
| "fmt" | |
| ) | |
| func say(s string) { | |
| for i := 0; i < 5; i++ { | |
| time.Sleep(100 * time.Millisecond) | |
| fmt.Println(s) | |
| } | |
| } | |
| func main() { | |
| go say("world") | |
| say("hello") | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "sync" | |
| "time" | |
| "fmt" | |
| ) | |
| type SafeCounter struct { | |
| v map[string]int | |
| mux sync.Mutex | |
| } | |
| func (c *SafeCounter) Inc(key string) { | |
| c.mux.Lock() | |
| defer c.mux.Unlock() | |
| c.v[key]++ | |
| } | |
| func (c *SafeCounter) Value(key string) int { | |
| c.mux.Lock() | |
| defer c.mux.Unlock() | |
| return c.v[key] | |
| } | |
| func main() { | |
| c := SafeCounter{v: make(map[string]int)} | |
| for i := 0; i < 1000; i++ { | |
| go c.Inc("somekey") | |
| } | |
| time.Sleep(time.Second) | |
| fmt.Println(c.Value("somekey")) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import "fmt" | |
| func fibonacci(n int, c chan int) { | |
| x, y := 0, 1 | |
| for i := 0; i < n; i++ { | |
| c <- x | |
| x, y = y, x + y | |
| } | |
| close(c) | |
| } | |
| func main() { | |
| c := make(chan int, 10) | |
| go fibonacci(cap(c), c) | |
| for i := range c { | |
| fmt.Println(i) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "fmt" | |
| "math" | |
| "time" | |
| ) | |
| type MyError struct { | |
| When time.Time | |
| What string | |
| } | |
| func (e *MyError) Error() string { | |
| return fmt.Sprintf("at %v, %s", e.When, e.What) | |
| } | |
| func run() error { | |
| return &MyError{ | |
| time.Now(), | |
| "it didn't work", | |
| } | |
| } | |
| type ErrNegativeSqrt struct { | |
| srcValue float64 | |
| } | |
| func (e *ErrNegativeSqrt) Error() string { | |
| return fmt.Sprintf("negative value: %v don't have Sqrt", e.srcValue) | |
| } | |
| func Sqrt(x float64) (float64, error) { | |
| if x < 0 { | |
| return 0, &ErrNegativeSqrt{x} | |
| } | |
| return math.Sqrt(x), nil | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "strings" | |
| "testing" | |
| ) | |
| func TestMyError_Error(t *testing.T) { | |
| if err := run(); err != nil { | |
| if strings.EqualFold(err.Error(), "it didn't work") { | |
| t.Errorf("err should return %q", "it didn't work") | |
| } | |
| } | |
| } | |
| func TestErrNegativeSqrt_Error(t *testing.T) { | |
| if _, err := Sqrt(-203); err == nil { | |
| t.Error("Sqrt(-203) should return err") | |
| } | |
| if _, err := Sqrt(64); err != nil { | |
| t.Error("Sqrt(64) should not return err") | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "image/color" | |
| "image" | |
| ) | |
| type Image struct { | |
| } | |
| func (img *Image)ColorModel() color.Model { | |
| return color.RGBAModel | |
| } | |
| func (img *Image) Bounds() image.Rectangle { | |
| return image.Rect(0, 0, 100, 100) | |
| } | |
| func (img *Image) At(x, y int) color.Color { | |
| r := 100 / 2 | |
| borderWidth := 2 | |
| x, y = x - r, y - r | |
| x2 := x*x | |
| y2 := y*y | |
| minR2 := (r-borderWidth/2) * (r-borderWidth/2) | |
| maxR2 := (r+borderWidth/2) * (r+borderWidth/2) | |
| if x2 + y2 >= minR2 && x2 + y2 <= maxR2 { | |
| return color.RGBA{255,255,255,255} | |
| } | |
| return color.RGBA{100, 100, 255, 255} | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "testing" | |
| "golang.org/x/tour/pic" | |
| ) | |
| func TestImage(t *testing.T) { | |
| m := Image{} | |
| pic.ShowImage(&m) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "io" | |
| ) | |
| type MyReader struct { | |
| } | |
| func (my *MyReader) Read(b []byte) (int, error) { | |
| if len(b) == 0 { | |
| return 0, io.ErrShortBuffer | |
| } | |
| for i := range b { | |
| b[i] = 'A' | |
| } | |
| return len(b), nil | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "golang.org/x/tour/reader" | |
| "testing" | |
| ) | |
| func TestMyReader_Read(t *testing.T) { | |
| reader.Validate(&MyReader{}) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "io" | |
| ) | |
| type rot13Reader struct { | |
| r io.Reader | |
| } | |
| func (rot *rot13Reader) Read(b []byte) (int, error) { | |
| n, err := rot.r.Read(b) | |
| if err != nil { | |
| return n, err | |
| } | |
| for i := 0; i < n; i++ { | |
| b[i] = rot13(b[i]) | |
| } | |
| return n, nil | |
| } | |
| func rot13(b byte) byte { | |
| if (b >= 'A' && b < 'N') || (b >='a' && b < 'n') { | |
| b += 13 | |
| } else if (b > 'M' && b <= 'Z') || (b > 'm' && b <= 'z'){ | |
| b -= 13 | |
| } | |
| return b | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "testing" | |
| "strings" | |
| "io" | |
| "os" | |
| ) | |
| func TestRot13Reader_Read(t *testing.T) { | |
| s := strings.NewReader("Lbh penpxrq gur phqr!") | |
| r := rot13Reader{s} | |
| io.Copy(os.Stdout, &r) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import "fmt" | |
| type Abser interface { | |
| Abs() float64 | |
| } | |
| type I interface { | |
| M() | |
| } | |
| type T struct { | |
| S string | |
| } | |
| func (t *T) M() { | |
| if t == nil { | |
| fmt.Println("<nil>") | |
| return | |
| } | |
| fmt.Println(t.S) | |
| } | |
| func describe(i I) { | |
| fmt.Printf("(%v, %T)\n", i, i) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import "testing" | |
| import ( | |
| "fmt" | |
| "math" | |
| "strings" | |
| ) | |
| func TestVertex_Abs2(t *testing.T) { | |
| var a Abser | |
| f := MyFloat(-math.Sqrt2) | |
| v := Vertex{3, 4} | |
| a = f // a MyFloat implements Abser | |
| a = &v // a *Vertex implements Abser | |
| a.Abs() | |
| } | |
| func do(i interface{}) string { | |
| switch v := i.(type) { | |
| case int: | |
| return fmt.Sprintf("Twice %v is %v\n", v, v*2) | |
| case string: | |
| return fmt.Sprintf("%q is %v bytes long\n", v, len(v)) | |
| default: | |
| return fmt.Sprintf("I don't know about type %T!\n", v) | |
| } | |
| } | |
| func Test_do(t *testing.T) { | |
| if s := do(21); strings.EqualFold(s, "Twice 21 is 42\\n") { | |
| t.Errorf("do(21) not return 'Twice 21 is 42\\n' %v'", s) | |
| } | |
| if s := do("hello"); strings.EqualFold(s, "'hello' is 5 bytes long\n") { | |
| t.Error("do('hello') error") | |
| } | |
| if s := do(true); strings.EqualFold(s, "I don't know about type bool!\\n") { | |
| t.Errorf("do(true) %v", s) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "math" | |
| ) | |
| type Vertex struct { | |
| X, Y float64 | |
| } | |
| func (v *Vertex) Abs() float64 { | |
| return math.Sqrt(v.X*v.X + v.Y*v.Y) | |
| } | |
| func (v *Vertex) Scale(f float64) { | |
| v.X = v.X * f | |
| v.Y = v.Y * f | |
| } | |
| type MyFloat float64 | |
| func (f MyFloat) Abs() float64 { | |
| if f < 0 { | |
| return float64(-f) | |
| } | |
| return float64(f) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <module version="4"> | |
| <component name="NewModuleRootManager" inherit-compiler-output="false"> | |
| <orderEntry type="sourceFolder" forTests="false" /> | |
| </component> | |
| </module> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "math" | |
| "testing" | |
| ) | |
| func TestVertex_Abs(t *testing.T) { | |
| v := Vertex{3, 4} | |
| if v.Abs() != 5 { | |
| t.Error("Vertex{3, 4}.Abs() != 5") | |
| } | |
| } | |
| func TestMyFloat_Abs(t *testing.T) { | |
| f := MyFloat(-math.Sqrt2) | |
| if f.Abs() != math.Sqrt2 { | |
| t.Error("MyFloat(-math.Sqrt2).Abs() != math.Sqrt2") | |
| } | |
| } | |
| func TestVertex_Scale(t *testing.T) { | |
| v := Vertex{3, 4} | |
| v.Scale(10) | |
| expect := 50.0 | |
| if v.Abs() != expect { | |
| t.Errorf("Vertex{3, 4} after scale(10) .Abs() = %v != %v", v.Abs(), expect) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import "fmt" | |
| func fibonacci(c, quit chan int) { | |
| x, y := 0, 1 | |
| for { | |
| select { | |
| case c <- x: | |
| x, y = y, x+y | |
| case <-quit: | |
| fmt.Println("quit") | |
| return | |
| } | |
| } | |
| } | |
| func main() { | |
| c := make(chan int) | |
| quit := make(chan int) | |
| go func() { | |
| for i :=0; i < 10; i++ { | |
| fmt.Println(<-c) | |
| } | |
| quit <- 0 | |
| }() | |
| fibonacci(c, quit) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import "fmt" | |
| type Person struct { | |
| Name string | |
| Age int | |
| } | |
| func (p Person) String() string { | |
| return fmt.Sprintf("%v (%v years)", p.Name, p.Age) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package methods | |
| import ( | |
| "fmt" | |
| "testing" | |
| "strings" | |
| ) | |
| type IPAddr [4]byte | |
| func (ip IPAddr) String() string { | |
| return fmt.Sprintf("%v.%v.%v.%v", | |
| int(ip[0]), | |
| int(ip[1]), | |
| int(ip[2]), | |
| int(ip[3]), | |
| ) | |
| } | |
| func TestIPAddr(t *testing.T) { | |
| hosts := map[string]IPAddr{ | |
| "loopback": {127, 0, 0, 1}, | |
| "googleDNS": {8, 8, 8, 8}, | |
| } | |
| expectedResult := map[string]string { | |
| "loopback": "127.0.0.1", | |
| "googleDNS": "8.8.8.8", | |
| } | |
| for name, ip := range hosts { | |
| expectedIP := expectedResult[name] | |
| if !strings.EqualFold(expectedIP, ip.String()) { | |
| t.Errorf("name: %v result: %v expect: %v", name, ip, expectedIP) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment