Skip to content

Instantly share code, notes, and snippets.

@charleehu
Last active March 23, 2018 07:00
Show Gist options
  • Save charleehu/fc3ca1533db96d0956e3b7bc78d4cad0 to your computer and use it in GitHub Desktop.
Save charleehu/fc3ca1533db96d0956e3b7bc78d4cad0 to your computer and use it in GitHub Desktop.
exercises of Go tour
package main
import (
"golang.org/x/tour/tree"
"fmt"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
WalkTree(t, ch)
close(ch)
}
//中序遍历
func WalkTree(t *tree.Tree, ch chan int) {
if t.Left != nil {
WalkTree(t.Left, ch)
}
ch <- t.Value
if t.Right != nil {
WalkTree(t.Right, ch)
}
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
ch1, ch2 := make(chan int), make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for {
a1, ok1 := <-ch1
a2, ok2 := <-ch2
if a1 != a2 || ok1 != ok2 {
return false
}
if ok1 == false {
break
}
}
return true
}
func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for v := range ch {
fmt.Printf("%v ", v)
}
fmt.Println()
fmt.Println(Same(tree.New(1), tree.New(2)))
fmt.Println(Same(tree.New(1), tree.New(1)))
}
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
i := 0
return func() int {
ret := recursive(i)
i++
return ret
}
}
func recursive(n int) int {
if n <= 1 {
return n
} else {
return recursive(n-1) + recursive(n-2)
}
}
func nonorecursive(n int) int {
x, y := 0, 1
for i := 0; i < n; i++ {
t := x
x = y
y = t + y
}
return x
}
func main() {
f := fibonacci()
for i := 0; i < 20; i++ {
fmt.Println(f())
}
}
package main
import (
"io"
"os"
"strings"
)
var src = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var des = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
type rot13Reader struct {
r io.Reader
}
func (r13 rot13Reader) Read(data []byte) (n int, e error) {
n, e = r13.r.Read(data)
for i, v := range data {
if v >= 'A' && v <= 'Z' || v >= 'a' && v <= 'z' {
data[i] = des[strings.IndexByte(src, v)]
}
}
return
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
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)
}
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, ch chan string) {
// TODO: Fetch URLs in parallel.
// TODO: Don't fetch the same URL twice.
// This implementation doesn't do either:
defer close(ch)
if depth <= 0 || !cache.putIfAbsence(url) {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
//fmt.Println(err)
ch <- fmt.Sprintln(err)
return
}
//fmt.Printf("found: %s %q\n", url, body)
ch <- fmt.Sprintf("found: %s %q\n", url, body)
var rs []chan string
for _, u := range urls {
ch2 := make(chan string)
rs = append(rs, ch2)
go Crawl(u, depth-1, fetcher, ch2)
}
for _, ch3 := range rs {
for v := range ch3 {
ch <- v
}
}
return
}
func main() {
ch := make(chan string)
go func() {
for v := range ch {
fmt.Print(v)
}
}()
Crawl("https://golang.org/", 4, fetcher, ch)
}
type concurrentMap struct {
data map[string]int
mux sync.Mutex
}
func (cm *concurrentMap) putIfAbsence(s string) (success bool) {
cm.mux.Lock()
if _, exist := cm.data[s]; !exist {
cm.data[s] = 1
success = true
} else {
success = false
}
cm.mux.Unlock()
return
}
var cache = concurrentMap {data: make(map[string]int)}
// 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{
"https://golang.org/": &fakeResult{
"The Go Programming Language",
[]string{
"https://golang.org/pkg/",
"https://golang.org/cmd/",
},
},
"https://golang.org/pkg/": &fakeResult{
"Packages",
[]string{
"https://golang.org/",
"https://golang.org/cmd/",
"https://golang.org/pkg/fmt/",
"https://golang.org/pkg/os/",
},
},
"https://golang.org/pkg/fmt/": &fakeResult{
"Package fmt",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
"https://golang.org/pkg/os/": &fakeResult{
"Package os",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment