File tree Expand file tree Collapse file tree 8 files changed +283
-0
lines changed Expand file tree Collapse file tree 8 files changed +283
-0
lines changed Original file line number Diff line number Diff line change
1
+ // concurrent web crawler
2
+ // Adopted from the example from "The Go Programming Language"
3
+ package main
4
+
5
+ import (
6
+ "log"
7
+ "os"
8
+
9
+ "gopl.io/ch5/links"
10
+ )
11
+
12
+ var done = make (chan bool )
13
+ //var rateLimiter = make(chan int, 4)
14
+
15
+ // visits given URL and returns all the links present in that page
16
+ func crawl (url string ) []string {
17
+ //rateLimiter <- 0
18
+ log .Println (url )
19
+
20
+ links , err := links .Extract (url )
21
+
22
+ //<-rateLimiter
23
+
24
+ if err != nil {
25
+ log .Print (err ) // print error and ignore
26
+ }
27
+ return links
28
+ }
29
+
30
+ func startCrawler (worklist chan string ) {
31
+ visited := make (map [string ]bool )
32
+
33
+ for link := range worklist {
34
+ if visited [link ] {
35
+ continue // skip already visited pages
36
+ }
37
+ visited [link ] = true // mark as visited
38
+
39
+ // passing link as argument is very important here.
40
+ // If we don't do that then the function will pick the value of link
41
+ // at the time of running, not at the time of starting this
42
+ // function. Since the loop variable `link` is changing in every
43
+ // iteration, it is important to pass a copy of that to the
44
+ // goroutine
45
+ go func (link string ) {
46
+ newLinks := crawl (link )
47
+ for _ , newLink := range newLinks {
48
+ worklist <- newLink
49
+ }
50
+ }(link )
51
+ }
52
+ }
53
+
54
+ func main () {
55
+ worklist := make (chan string )
56
+ go startCrawler (worklist )
57
+
58
+ worklist <- os .Args [1 ]
59
+
60
+ <- done
61
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "time"
6
+ )
7
+
8
+ func display (name string , n int ) {
9
+ for i := 0 ; i < n ; i ++ {
10
+ fmt .Printf ("%d: %s\n " , i , name )
11
+ }
12
+ }
13
+
14
+ func main () {
15
+ go display ("A" , 10 )
16
+ display ("B" , 10 )
17
+
18
+ // hack to wait till the goroutine finished
19
+ time .Sleep (1 * time .Second )
20
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ )
6
+
7
+ func display (name string , n int , done chan bool ) {
8
+ for i := 0 ; i < n ; i ++ {
9
+ fmt .Printf ("%d: %s\n " , i , name )
10
+ }
11
+ done <- true
12
+ }
13
+
14
+ func main () {
15
+ done := make (chan bool )
16
+
17
+ go display ("A" , 10 , done )
18
+ go display ("B" , 10 , done )
19
+ go display ("C" , 10 , done )
20
+
21
+ // receive something from the channel. blocks until someone sends it
22
+ <- done
23
+ <- done
24
+ <- done
25
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "bufio"
5
+ "fmt"
6
+ "io"
7
+ "log"
8
+ "net"
9
+ )
10
+
11
+ func handleConn (c net.Conn ) {
12
+ defer c .Close ()
13
+
14
+ input := bufio .NewScanner (c )
15
+ for input .Scan () {
16
+ echo (c , input .Text ())
17
+ }
18
+ }
19
+
20
+ func echo (c net.Conn , msg string ) {
21
+ _ , err := io .WriteString (c , msg + "\n " )
22
+ if err != nil {
23
+ log .Print ("err" ) // connection failed
24
+ }
25
+ }
26
+
27
+ func main () {
28
+ // start listening on port 8000
29
+ listener , err := net .Listen ("tcp" , "localhost:8000" )
30
+ if err != nil {
31
+ log .Fatal (err )
32
+ }
33
+ fmt .Println ("started server on localhost:8000" )
34
+
35
+ for {
36
+ conn , err := listener .Accept ()
37
+ if err != nil {
38
+ log .Print ("err" ) // connection failed
39
+ continue
40
+ }
41
+ go handleConn (conn )
42
+ }
43
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "io"
6
+ "log"
7
+ "net"
8
+ "time"
9
+ )
10
+
11
+ func handleConn (c net.Conn ) error {
12
+ defer c .Close ()
13
+ _ , err := io .WriteString (c , "Hello from Server!\n " )
14
+ if err != nil {
15
+ return err
16
+ }
17
+ time .Sleep (5 * time .Second )
18
+ _ , err = io .WriteString (c , "Bye from Server!\n " )
19
+ if err != nil {
20
+ return err
21
+ }
22
+ return nil
23
+ }
24
+
25
+ func main () {
26
+ // start listening on port 8000
27
+ listener , err := net .Listen ("tcp" , "localhost:8000" )
28
+ if err != nil {
29
+ log .Fatal (err )
30
+ }
31
+ fmt .Println ("started server on localhost:8000" )
32
+
33
+ for {
34
+ conn , err := listener .Accept ()
35
+ if err != nil {
36
+ log .Print ("err" ) // connection failed
37
+ continue
38
+ }
39
+ go handleConn (conn )
40
+ }
41
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "io"
5
+ "log"
6
+ "net"
7
+ "os"
8
+ )
9
+
10
+ func mustCopy (dst io.Writer , src io.Reader ) {
11
+ if _ , err := io .Copy (dst , src ); err != nil {
12
+ log .Fatal (err )
13
+ }
14
+ }
15
+
16
+ func main () {
17
+ host := os .Args [1 ]
18
+ port := os .Args [2 ]
19
+ conn , err := net .Dial ("tcp" , host + ":" + port )
20
+ if err != nil {
21
+ log .Fatal (err )
22
+ }
23
+ defer conn .Close ()
24
+ go mustCopy (os .Stdout , conn )
25
+ mustCopy (conn , os .Stdin )
26
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import "fmt"
4
+
5
+ func numbers (n int ) <- chan int {
6
+ c := make (chan int )
7
+ go func () {
8
+ for i := 0 ; i < n ; i ++ {
9
+ c <- i
10
+ }
11
+ close (c )
12
+ }()
13
+ return c
14
+ }
15
+
16
+ func squares (seq <- chan int ) <- chan int {
17
+ c := make (chan int )
18
+ go func () {
19
+ for n := range seq {
20
+ c <- n * n
21
+ }
22
+ close (c )
23
+ }()
24
+ return c
25
+ }
26
+
27
+ func printer (seq <- chan int ) {
28
+ for n := range seq {
29
+ fmt .Println (n )
30
+ }
31
+ }
32
+
33
+ func main () {
34
+ n := numbers (10 )
35
+ sq := squares (n )
36
+ printer (sq )
37
+ }
Original file line number Diff line number Diff line change
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "sync"
6
+ )
7
+
8
+ var sum int
9
+ var lock sync.Mutex
10
+
11
+ func compute (n int , w * sync.WaitGroup ) {
12
+ for i := 0 ; i < n ; i ++ {
13
+ //lock.Lock()
14
+ sum ++
15
+ //lock.Unlock()
16
+ }
17
+ w .Done ()
18
+ }
19
+
20
+ func main () {
21
+ var w sync.WaitGroup
22
+
23
+ w .Add (3 )
24
+ n := 100000
25
+ go compute (n , & w )
26
+ go compute (n , & w )
27
+ go compute (n , & w )
28
+ w .Wait ()
29
+ fmt .Println ("sum =" , sum )
30
+ }
You can’t perform that action at this time.
0 commit comments