Skip to content

Commit a7c2f2e

Browse files
author
eliastor
committed
unit 2 start code added
1 parent 4b8faed commit a7c2f2e

File tree

2 files changed

+81
-144
lines changed

2 files changed

+81
-144
lines changed

unit2/exercises/e1/main.go

Lines changed: 7 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,14 @@
11
package main
22

3-
import (
4-
"crypto/ed25519"
5-
"crypto/rand"
6-
"fmt"
7-
mathrand "math/rand"
8-
"time"
3+
import "golang.org/x/tour/tree"
94

10-
"github.com/brianvoe/gofakeit"
11-
)
5+
// Walk walks the tree t sending all values
6+
// from the tree to the channel ch.
7+
func Walk(t *tree.Tree, ch chan int)
128

13-
// Document stores text created by bureaucrat and have field for signature
14-
type Document struct {
15-
text string
16-
sign []byte
17-
}
18-
19-
// Let's define three roles in our office: bureaucrat, executor and verifier
20-
21-
// bureaucrat generates documents and take a rest after every document creation.
22-
// as soon as bureaucrat gets signal (done channel is closed) to finish its work it stops
23-
func bureaucrat(done <-chan struct{}, out chan<- *Document) int {
24-
docs_total := 0
25-
for {
26-
select {
27-
case _ = <-done:
28-
return docs_total
29-
case out <- &Document{text: gofakeit.Sentence(9)}:
30-
docs_total++
31-
//
32-
33-
time.Sleep(time.Millisecond * time.Duration(mathrand.Intn(100)))
34-
}
35-
}
36-
}
37-
38-
// executor signs documents it receives and send the documents further
39-
func executor(priv ed25519.PrivateKey, in <-chan *Document, out chan<- *Document) int {
40-
docs_total := 0
41-
for doc := range in {
42-
doc.sign = ed25519.Sign(priv, []byte(doc.text))
43-
docs_total++
44-
out <- doc
45-
}
46-
return docs_total
47-
}
48-
49-
// verifier checks signature in every document it receives and send the documents further
50-
func verifier(pub ed25519.PublicKey, in <-chan *Document, out chan<- *Document) int {
51-
docs_total := 0
52-
for doc := range in {
53-
if ed25519.Verify(pub, []byte(doc.text), doc.sign) {
54-
out <- doc
55-
}
56-
docs_total++
57-
}
58-
return docs_total
59-
}
60-
61-
func fanoutProxy(in <-chan *Document, fakeIn chan *Document, out chan *Document) {
62-
for msg := range in {
63-
fakeIn <- msg
64-
}
65-
close(fakeIn)
66-
close(out)
67-
}
68-
69-
// SpawnBureaucrat is generator function that spawns one bureaucrat,
70-
// and returns channel with generated documents. Also handles channel lifecycle
71-
func SpawnBureaucrat(done <-chan struct{}) <-chan *Document {
72-
out := make(chan *Document)
73-
go func() {
74-
total := bureaucrat(done, out)
75-
fmt.Println(total, "documents were created by Bureaucrat")
76-
close(out)
77-
}()
78-
return out
79-
}
80-
81-
// SpawnExecutors is generator function that create n executors,
82-
// fan out documents to executors from input channel,
83-
// and returns channel with signed documents. Also handles channel lifecycle
84-
func SpawnExecutors(n int, priv ed25519.PrivateKey, in <-chan *Document) <-chan *Document {
85-
out := make(chan *Document)
86-
fakeIn := make(chan *Document)
87-
totals := make([]int, n)
88-
// we must propagate closing of channels from INs to OUTs
89-
// close() must be called only once
90-
// we spawn multiple workers
91-
// so we need one goroutine from that we can catch channel closing and close out channel
92-
// for this purpose fanoutProxy
93-
// fanoutProxy reads documents from IN channel, sends them to fakeIn
94-
// If IN channel is closed it will close fakeIN and OUT,
95-
// so executors will be closed gracefully, because of close(fakeIN)
96-
// and close will be propagated further to Out channel
97-
go fanoutProxy(in, fakeIn, out)
98-
for i := 0; i < n; i++ {
99-
go func(i int) {
100-
totals[i] = executor(priv, fakeIn, out)
101-
fmt.Println(totals[i], "documents were signed by Executor", i) // why it is not shown in output?
102-
}(i)
103-
}
104-
105-
return out
106-
}
107-
108-
// SpawnExecutors is generator function that create one verifier,
109-
// and returns channel with verified documents. Also handles channel lifecycle
110-
func SpawnVerifier(pub ed25519.PublicKey, in <-chan *Document) <-chan *Document {
111-
out := make(chan *Document)
112-
go func() {
113-
total := verifier(pub, in, out)
114-
fmt.Println(total, "documents were verified by verifier")
115-
close(out)
116-
}()
117-
return out
118-
}
9+
// Same determines whether the trees
10+
// t1 and t2 contain the same values.
11+
func Same(t1, t2 *tree.Tree) bool
11912

12013
func main() {
121-
// to get executors and verifier work we need to provide private and public keys
122-
pub, priv, _ := ed25519.GenerateKey(rand.Reader)
123-
124-
done := make(chan struct{})
125-
docsNew := SpawnBureaucrat(done)
126-
docsSigned := SpawnExecutors(2, priv, docsNew)
127-
docsVerified := SpawnVerifier(pub, docsSigned)
128-
129-
// we don't want this to run infinitely, so we'll stop this by signaling bureaucrat to stop
130-
go func(done chan struct{}) {
131-
time.Sleep(3 * time.Second)
132-
close(done)
133-
// channel closing flow is:
134-
// close(done) --> close(docsNew)--> [fanoutProxy] --> close(docsSigned) --> close(docsVerified)
135-
}(done)
136-
137-
// the whole structure will be like that:
138-
// / [executor 1] \
139-
// [bureaucrat]---------| |--------[verifier]-------[range in main]
140-
// \ [executor 2] /
141-
142-
sentToNowhere := 0
143-
// nowhere emulation
144-
for range docsVerified {
145-
sentToNowhere++
146-
}
147-
148-
fmt.Println(sentToNowhere, "documents were sent to nowhere")
14914
}

unit2/exercises/e2/main.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,82 @@ import (
44
"fmt"
55
)
66

7-
func Sqrt(x float64) float64 {
7+
type Fetcher interface {
8+
// Fetch returns the body of URL and
9+
// a slice of URLs found on that page.
10+
Fetch(url string) (body string, urls []string, err error)
11+
}
12+
13+
// Crawl uses fetcher to recursively crawl
14+
// pages starting with url, to a maximum of depth.
15+
func Crawl(url string, depth int, fetcher Fetcher) {
16+
// TODO: Fetch URLs in parallel.
17+
// TODO: Don't fetch the same URL twice.
18+
// This implementation doesn't do either:
19+
if depth <= 0 {
20+
return
21+
}
22+
body, urls, err := fetcher.Fetch(url)
23+
if err != nil {
24+
fmt.Println(err)
25+
return
26+
}
27+
fmt.Printf("found: %s %q\n", url, body)
28+
for _, u := range urls {
29+
Crawl(u, depth-1, fetcher)
30+
}
31+
return
832
}
933

1034
func main() {
11-
fmt.Println(Sqrt(2))
35+
Crawl("https://golang.org/", 4, fetcher)
36+
}
37+
38+
// fakeFetcher is Fetcher that returns canned results.
39+
type fakeFetcher map[string]*fakeResult
40+
41+
type fakeResult struct {
42+
body string
43+
urls []string
44+
}
45+
46+
func (f fakeFetcher) Fetch(url string) (string, []string, error) {
47+
if res, ok := f[url]; ok {
48+
return res.body, res.urls, nil
49+
}
50+
return "", nil, fmt.Errorf("not found: %s", url)
1251
}
1352

53+
// fetcher is a populated fakeFetcher.
54+
var fetcher = fakeFetcher{
55+
"https://golang.org/": &fakeResult{
56+
"The Go Programming Language",
57+
[]string{
58+
"https://golang.org/pkg/",
59+
"https://golang.org/cmd/",
60+
},
61+
},
62+
"https://golang.org/pkg/": &fakeResult{
63+
"Packages",
64+
[]string{
65+
"https://golang.org/",
66+
"https://golang.org/cmd/",
67+
"https://golang.org/pkg/fmt/",
68+
"https://golang.org/pkg/os/",
69+
},
70+
},
71+
"https://golang.org/pkg/fmt/": &fakeResult{
72+
"Package fmt",
73+
[]string{
74+
"https://golang.org/",
75+
"https://golang.org/pkg/",
76+
},
77+
},
78+
"https://golang.org/pkg/os/": &fakeResult{
79+
"Package os",
80+
[]string{
81+
"https://golang.org/",
82+
"https://golang.org/pkg/",
83+
},
84+
},
85+
}

0 commit comments

Comments
 (0)