This file contains 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
//Exercise: Web Crawler http://tour.golang.org/concurrency/10 | |
package main | |
import ( | |
"fmt" | |
"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 syncStringSet struct { | |
set map[string]bool | |
mux sync.Mutex | |
} | |
// set.add(string) returns true if it does not have string in set, but has now inserted | |
// the string into the set. | |
// set.add(url) returns false if it has the url in its cache | |
func (ss *syncStringSet) add(str string) bool { | |
ss.mux.Lock() | |
defer ss.mux.Unlock() | |
if _, hasEntry := ss.set[str]; hasEntry { | |
return false | |
} | |
ss.set[str] = true | |
return true | |
} | |
type result struct { | |
url string | |
body string | |
err error | |
} | |
type crawlError struct { | |
error | |
} | |
func crawl( | |
url string, | |
depth int, | |
fetcher Fetcher, | |
results chan result, | |
seen *syncStringSet, | |
crawlers *sync.WaitGroup, | |
) { | |
defer crawlers.Done() | |
if depth < 1 { | |
results <- result{ | |
url: url, | |
err: crawlError{fmt.Errorf("depth exceeded (%d)", depth)}, | |
} | |
return | |
} | |
if !seen.add(url) { | |
results <- result{ | |
url: url, | |
err: crawlError{fmt.Errorf("seen.add(%q) == false", url)}, | |
} | |
return | |
} | |
body, urls, err := fetcher.Fetch(url) | |
for _, u := range urls { | |
crawlers.Add(1) | |
go crawl(u, depth-1, fetcher, results, seen, crawlers) | |
} | |
results <- result{url, body, err} | |
} | |
func Crawl(url string, depth int, fetcher Fetcher) { | |
seen := &syncStringSet{set: make(map[string]bool)} | |
crawlers := &sync.WaitGroup{} | |
results := make(chan result) | |
//expected_msgs.inc() | |
crawlers.Add(1) | |
go crawl(url, depth, fetcher, results, seen, crawlers) | |
go func() { | |
crawlers.Wait() | |
close(results) | |
}() | |
for res := range results { | |
_, isCrawlError := res.err.(crawlError) | |
switch { | |
case isCrawlError: | |
//fmt.Println(res.err) | |
case res.err != nil: | |
fmt.Println(res.err) | |
default: | |
fmt.Printf("found: %s %q\n", res.url, res.body) | |
} | |
} | |
} | |
func main() { | |
Crawl("http://golang.org/", 4, fetcher) | |
} | |
// fakeFetcher is Fetcher that returns 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 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
// Exercise: Equivalent Binary Trees http://tour.golang.org/concurrency/8 | |
// | |
// 1. Implement the Walk function. | |
// | |
// 2. Test the Walk function. | |
// | |
// The function tree.New(k) constructs a randomly-structured binary tree | |
// holding the values k, 2k, 3k, ..., 10k. | |
// | |
// Create a new channel ch and kick off the walker: | |
// | |
// go Walk(tree.New(1), ch) | |
// | |
// Then read and print 10 values from the channel. It should be the numbers | |
// 1, 2, 3, ..., 10. | |
// | |
// 3. Implement the Same function using Walk to determine whether t1 and t2 | |
// store the same values. | |
// | |
// 4. Test the Same function. | |
// | |
// Same(tree.New(1), tree.New(1)) should return true, and Same(tree.New(1), | |
// tree.New(2)) should return false. | |
package main | |
import ( | |
"fmt" | |
"golang.org/x/tour/tree" | |
) | |
// Walk walks the tree t sending all values | |
// from the tree to the channel ch. | |
func Walk(t *tree.Tree, ch chan int) { | |
if t.Left != nil { | |
Walk(t.Left, ch) | |
} | |
ch <- t.Value | |
if t.Right != nil { | |
Walk(t.Right, ch) | |
} | |
} | |
// Same determines whether the trees | |
// t1 and t2 contain the same values. | |
func Same(t1, t2 *tree.Tree) bool { | |
ch1 := make(chan int) | |
ch2 := make(chan int) | |
go Walk(t1, ch1) | |
go Walk(t2, ch2) | |
for i:=0; i<10; i++ { | |
v1 := <- ch1 | |
v2 := <- ch2 | |
if v1 != v2 { | |
return false | |
} | |
} | |
return true | |
} | |
func main() { | |
if Same(tree.New(1), tree.New(1)) { | |
fmt.Println("The trees are the same.") | |
} else { | |
fmt.Println("The trees are NOT the same.") | |
} | |
} | |
/* | |
func main() { | |
ch := make(chan int) | |
go Walk(tree.New(1), ch) | |
for i := 0; i < 10; i++ { | |
fmt.Println(<-ch) | |
} | |
} | |
*/ |
This file contains 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
//Exercise: Loops and Functions http://tour.golang.org/flowcontrol/8 | |
// Next, change the loop condition to stop once the value has stopped changing | |
// (or only changes by a very small delta). See if that's more or fewer | |
// iterations. How close are you to the math.Sqrt? | |
package main | |
import ( | |
"fmt" | |
"math" | |
) | |
func Sqrt(x float64) float64 { | |
delta := 0.0001 //terminates at i=7 | |
//delta := 0.00001 //terminates at i=9 | |
//delta := 0.000001 //terminates at i=11 | |
z := float64(1) | |
for i := 0; i < 100; i++ { | |
z0 := z | |
z = z - ((z*z - x) / (2*x)) | |
if math.Abs(z-z0) < delta { | |
fmt.Printf("small enough i=%d, delta=%f\n", i, delta) | |
break | |
} | |
} | |
return z | |
} | |
func main() { | |
fmt.Println(Sqrt(2)) | |
fmt.Println("math.Sqrt(2) =", math.Sqrt(2)) | |
} |
This file contains 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
//Exercise: Loops and Functions http://tour.golang.org/flowcontrol/8 | |
package main | |
import ( | |
"fmt" | |
) | |
func Sqrt(x float64) float64 { | |
z := float64(1) | |
for i := 0; i < 10; i++ { | |
z = z - ((z*z - x) / (2*x)) | |
} | |
return z | |
} | |
func main() { | |
fmt.Println(Sqrt(2)) | |
} |
This file contains 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
//Exercise: Stringers http://tour.golang.org/methods/18 | |
package main | |
import "fmt" | |
type IPAddr [4]byte | |
// TODO: Add a "String() string" method to IPAddr. | |
func (ip IPAddr) String() string { | |
return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) | |
} | |
func main() { | |
addrs := map[string]IPAddr{ | |
"loopback": {127, 0, 0, 1}, | |
"googleDNS": {8, 8, 8, 8}, | |
} | |
for n, a := range addrs { | |
fmt.Printf("%v: %v\n", n, a) | |
} | |
} |
This file contains 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
//Exercise: Errors http://tour.golang.org/methods/20 | |
package main | |
import ( | |
"fmt" | |
"math" | |
) | |
type ErrNegativeSqrt float64 | |
func (err ErrNegativeSqrt) Error() string { | |
return fmt.Sprintf("cannot Sqrt negative number: %d", err) | |
} | |
func Sqrt(x float64) (float64, error) { | |
if x < 0 { | |
return math.NaN(), ErrNegativeSqrt(x) | |
} | |
z := float64(1) | |
for i :=1; i<10; i++ { | |
z = z - ((z*z)-x)/(2*x) | |
} | |
return z, nil | |
} | |
func main() { | |
fmt.Println(Sqrt(2)) | |
fmt.Println(Sqrt(-2)) | |
} |
This file contains 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
//Exercise: Readers http://tour.golang.org/methods/22 | |
package main | |
import "golang.org/x/tour/reader" | |
type MyReader struct{} | |
func (m MyReader) Read(b []byte) (n int, err error) { | |
for n = range b { | |
b[n] = 'A' | |
} | |
return | |
} | |
func main() { | |
reader.Validate(MyReader{}) | |
} |
This file contains 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
//Exercise: rot13Reader http://tour.golang.org/methods/23 | |
package main | |
import ( | |
"io" | |
"os" | |
"strings" | |
) | |
type rot13Reader struct { | |
r io.Reader | |
} | |
func (rot *rot13Reader) Read(b []byte) (n int, err error) { | |
n, err = rot.r.Read(b) | |
for i, v := range b { | |
switch { | |
case v >= 'A' && v <= 'Z': | |
if v < 'N' { | |
b[i] += 13 | |
} else { | |
b[i] -= 13 | |
} | |
case v >= 'a' && v <= 'z': | |
if v < 'n' { | |
b[i] += 13 | |
} else { | |
b[i] -= 13 | |
} | |
} | |
} | |
return | |
} | |
func main() { | |
s := strings.NewReader("Lbh penpxrq gur pbqr!") | |
r := rot13Reader{s} | |
io.Copy(os.Stdout, &r) | |
} |
This file contains 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
//Exercise: Images http://tour.golang.org/methods/25 | |
package main | |
import ( | |
"golang.org/x/tour/pic" | |
"image" | |
"image/color" | |
) | |
type Image struct{} | |
func (i Image) ColorModel() color.Model { | |
return color.RGBAModel | |
} | |
func (i Image) Bounds() image.Rectangle { | |
return image.Rect(0, 0, 256, 256) | |
} | |
func (i Image) At(x, y int) color.Color { | |
return color.RGBA{72, 72, uint8(x^y), 255} | |
} | |
func main() { | |
m := Image{} | |
pic.ShowImage(m) | |
} |
This file contains 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
//Exercise: Slices http://tour.golang.org/moretypes/15 | |
package main | |
import "golang.org/x/tour/pic" | |
func Pic(dx, dy int) [][]uint8 { | |
var p = make([]([]uint8), dy) | |
for y := 0; y < len(p); y++ { | |
p[y] = make([]uint8, dx) | |
for x := 0; x < len(p[y]); x++ { | |
//p[y][x] = uint8((y + x) / 2) | |
//p[y][x] = uint8(y * x) | |
p[y][x] = uint8(y ^ x) | |
} | |
} | |
return p | |
} | |
func main() { | |
pic.Show(Pic) | |
} |
This file contains 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
//Exercise: Maps http://tour.golang.org/moretypes/20 | |
package main | |
import ( | |
"golang.org/x/tour/wc" | |
"strings" | |
) | |
func WordCount(s string) map[string]int { | |
wordcount := make(map[string]int) | |
for _, w := range strings.Fields(s) { | |
wordcount[w]++ | |
} | |
return wordcount | |
} | |
func main() { | |
wc.Test(WordCount) | |
} |
This file contains 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
//Exercise: Fibonacci closure http://tour.golang.org/moretypes/23 | |
package main | |
import "fmt" | |
// fibonacci is a function that returns | |
// a function that returns an int. | |
func fibonacci() func() int { | |
prev, curr := 0, 1 | |
return func() int { | |
ret := prev | |
prev, curr = curr, prev+curr | |
return ret | |
} | |
} | |
func main() { | |
f := fibonacci() | |
for i := 0; i < 10; i++ { | |
fmt.Println(f()) | |
} | |
} |