go networking
DESCRIPTION
Go networking. Peter Borovansk ý, KAI, I-18, borovan (a)ii.fmph.uniba.sk. Prejdeme si v Go tri úrovne tzv. TCP Stacku, a naprogramujeme klient/server aplikáciu cez sockety, príklad chat sntp udp klient (time server klient) f tp server & ftp klient w ebcrawler - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/1.jpg)
Klobúky ako predjedlo(čo to má s programovaním pochopíte dnes)
3 biele a 2 čierne A, B, C si navzájom vidia farby klobúkov nesmú komunikovať, ale (aj tak) sú inteligentní vyhrávajú, ak všetci uhádnu farbu svojho klobúka resp. ak sa jeden pomýli, prehrali všetci.
Hint: A,B,C sú spoluhráči, preto predpokladaj, že sú chytrí a mysli aj za nich
Hint: úloha nie je o šťastí=hádaní správneho riešenia
![Page 2: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/2.jpg)
Do 10 sekúndak vidím dva čierne, určite mám biely, a
preto sa hneď ozvem, že "mám biely".
ak sa niekto do 10s ozval, že má biely, musí vidieť dva čierne, preto ja mám čierny, tak hneď kričím "mám čierny".
inak čakám 10s, nikto neozval, že „mám biely", preto určite nie sú v hre 2 čierne, ale najviac jeden čierny !!!
![Page 3: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/3.jpg)
10 až 20 sekúnd
ak teda vidím čierny, ja musím mať biely, tak sa ozvem hneď, že mám "mám biely".
inak, ak sa ozvú dvaja (do 10 s), že biely, ja mám čierny,
tak kričím "mám čierny".
inak, nevidím čierny a nikto sa neozval, čakám ďalších 10s,
v hre je najviac jeden čierny
![Page 4: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/4.jpg)
po 20 sekundách
keďže sa nikto neozval, tak nie je žiaden čierny, tak kričím "mám biely" a ostatní tiež
v hre nie je žiaden čierny
![Page 5: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/5.jpg)
Celý algoritmus(bez vysvetlenia, už pre cvičenú opicu)
ak vidím dva čierne, hneď ozvem, že "mám biely".
ak sa niekto do 10 s ozval, tak kričím "mám čierny".
inak čakám 10s.
ak vidím čierny, tak hneď kričím "mám biely".
inak, ak sa ozvú dvaja do 10 s, tak kričím "mám čierny".
Po 10 sek:
inak čakám ďalších 10s,
kričím "mám biely”
Po 20 sek:
Hneď:
![Page 6: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/6.jpg)
Na zamyslenie je podstatné, či kričím mám biely/mám čierny, nestačí len už
viem ?!
Dalo by sa to pre 3 biele, 3 čierne, 3 ľudia ?
Dalo by sa to pre 2 biele, 1 čierne, 2 ľudia ?
Dalo by sa to pre N biele, (N-1) čierne, N ľudia ? (napr.6,5,6)
Dalo by sa to pre >N biele, (N-1) čierne, N ľudia ? (napr. 8,5,6)
Dalo by sa to pre N biele, <(N-1) čierne, N ľudia ? (napr. 6,4,6)
![Page 7: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/7.jpg)
Komunikácia–každý s každým
![Page 8: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/8.jpg)
Správa, kanály, agentitype Message struct { who int // od koho, odosielateľ
what int } // čo, obsah správyfunc makeChannels(n int) []chan Message { chArray := make([]chan Message, n) for i:= 0; i < n; i++ {// kanál,na ktorom počúva i-ty agent chArray[i] = make(chan Message) } return chArray } func main() { chArray := makeChannels(numb) for a:= 0; a<numb; a++ { runAgent(a, chArray) } }
klobuky/modelBezDispecher.go
![Page 9: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/9.jpg)
Agenti napriamofunc runAgent(agent int, channels []chan Message) {
go func() { // ID agenta, kanaly na vsetkych agentov i := 1 // iniciálny stav agenta for { // loop forever timeout := time.After(...) select { case msg := <- channels[agent]: // agent počúva len svoj fmt.Printf("agentovi %d: prišla správa:%s",agent, msg) case <-timeout: // prešiel timeout, vyrobíme správu msg msg := Message{who:agent, what:i++} //zmeníme svoj stav
for index, ch := range channels { // povedz každému if index != agent { // okrem seba go func(cha chan Message) {// !!!!!!!!!!!!!!!! cha <- msg // správu msg }(ch)
klobuky/modelBezDispecher.go
![Page 10: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/10.jpg)
Agenti napriamofunc runAgent(agent int, channels []chan Message) {
go func() { // ID agenta, kanaly na vsetkych agentov i := 1 // iniciálny stav agenta for { // loop forever timeout := time.After(...) select { case msg := <- channels[agent]: // agent počúva len svoj fmt.Printf("agentovi %d: prišla správa:%s",agent, msg) case <-timeout: // prešiel timeout, vyrobíme správu msg msg := Message{who:agent, what:i++} //zmeníme svoj stav
for index, ch := range channels { // povedz každému if index != agent { // okrem seba go func() { // !!!!! ZLE !!!!!! ch <- msg // správu msg }()
klobuky/modelBezDispecher.go
![Page 11: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/11.jpg)
Príklad komunikácie 3 agentov1: povedal 1
agentovi 2: prisla sprava:"1: povedal 1"
agentovi 0: prisla sprava:"1: povedal 1"
0: povedal 1
agentovi 2: prisla sprava:"0: povedal 1"
agentovi 1: prisla sprava:"0: povedal 1"
1: povedal 2
agentovi 2: prisla sprava:"1: povedal 2"
0: povedal 2
1: povedal 3
agentovi 0: prisla sprava:"1: povedal 2"
agentovi 0: prisla sprava:"1: povedal 3"
agentovi 1: prisla sprava:"0: povedal 2"
agentovi 2: prisla sprava:"0: povedal 2"
agentovi 2: prisla sprava:"1: povedal 3“
![Page 12: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/12.jpg)
Aplikácia na klobúky(domáca úloha)
[0s] A: vidim 1 biele a 1 cierne [0s] A: cakam 10 sek [0s] C: vidim 1 biele a 1 cierne [0s] C: cakam 10 sek [0s] B: vidim 2 biele a 0 cierne [0s] B: cakam 10 sek
[10s] B: cakam dalsich 10 sek [11s] A: mam biely !!! true [11s] C: mam biely !!! true [11s] B:: prisla sprava, ze [11s] A: mam biely !!! true [12s] B: mam cierny !!! true finito
func vidim(name String) (int, int) {
![Page 13: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/13.jpg)
Komunikácia s dispečerom
![Page 14: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/14.jpg)
Dispatcher čo počujte to prepošle
func runDispatcher(channels []chan Message) chan Message { dispch := make(chan Message) // kanál na komunikáciu s dispatcherom go func() { for { msg := <- dispch // ak prišla správa fmt.Println("dispecer sa dozvedel: " +
msg.toString()) for _,ch := range channels { go func(x chan Message) {
x <- msg }(ch) } } }() return dispch } klobuky/modelSDispecher.go
![Page 15: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/15.jpg)
Agenti cez dispečerafunc runAgentCommunicatingWithDispatcher(agent int,
dispch chan Message, input chan Message) { go func() { i := 0 // stav agenta for { timeout := time.After(...) // náhodny delay select { case msg := <- input: // ak prišla správa agentovi, fmt.Printf("agentovi %d: prisla sprava:%s",agent,msg)
case <-timeout: // po timeout, vytvoríme správu msg := Message{who:agent, what:i} dispch <- msg // pošleme dispecerovi i++ // agent si zvýši stav } } }() }
klobuky/modelSDispecher.go
![Page 16: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/16.jpg)
Agenti cez dispečerafunc runAgentCommunicatingWithDispatcher(agent int,
dispch chan Message, input chan Message) { go func() { i := 0 // stav agenta for { timeout := time.After(...) // náhodny delay select { case msg := <- input: // ak prišla správa agentovi, fmt.Printf("agentovi %d: prisla sprava:%s",agent,msg)
case <-timeout: // po timeout, vytvoríme správu msg := Message{who:agent, what:i}
go func() { dispch <- msg }()// pošleme dispecerovi i++ // agent si zvýši stav } } }() }
klobuky/modelSDispecher.go
![Page 17: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/17.jpg)
Príklad komunikácie 3 agentov1: povedal 0
dispecer sa dozvedel: 1: povedal 0
agentovi 2: prisla sprava:"1: povedal 0"
agentovi 0: prisla sprava:"1: povedal 0"
agentovi 1: prisla sprava:"1: povedal 0"
0: povedal 0
dispecer sa dozvedel: 0: povedal 0
agentovi 2: prisla sprava:"0: povedal 0"
agentovi 0: prisla sprava:"0: povedal 0"
agentovi 1: prisla sprava:"0: povedal 0"
0: povedal 1
dispecer sa dozvedel: 0: povedal 1
agentovi 2: prisla sprava:"0: povedal 1"
agentovi 0: prisla sprava:"0: povedal 1"
agentovi 1: prisla sprava:"0: povedal 1“
![Page 18: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/18.jpg)
Aplikácia na klobúky(domáca úloha) [0s] A: vidim 1 biele a 1 cierne [0s] A: cakam 10 sek [0s] B: vidim 2 biele a 0 cierne [0s] B: cakam 10 sek [0s] C: vidim 1 biele a 1 cierne [0s] C: cakam 10 sek [10s] B: cakam dalsich 10 sek [11s] A: mam biely !!! true od A prisla sprava, ze [11s] A: mam biely !!! true [11s] C: mam biely !!! true [11s] B:: prisla sprava, ze [11s] A: mam biely !!! True od C prisla sprava, ze [11s] A: mam biely !!! true od B prisla sprava, ze [11s] A: mam biely !!! true od B prisla sprava, ze [11s] C: mam biely !!! true [12s] B: mam cierny !!! True finito
func vidim(name String) (int, int) {
![Page 19: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/19.jpg)
Go networking
Peter Borovanský, KAI, I-18, borovan(a)ii.fmph.uniba.sk
Prejdeme si v Go tri úrovne tzv. TCP Stacku, a naprogramujeme klient/server aplikáciu cez sockety, príklad chat sntp udp klient (time server klient) Webcrawler
Zdroje: http://golang.org/doc/articles/wiki/ http://jan.newmarch.name/go
![Page 20: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/20.jpg)
Client socketimport ( "bufio" "fmt" "io" "net" ) func main() { // vytvorenie spojenia socket-socket conn, err := net.Dial("tcp", "google.com:80") if err != nil { fmt.Println("connection error: " + err.Error()) } else { // písanie do conn : net.Conn fmt.Fprintf(conn, "HEAD/ HTTP/1.0\r\n\r\n") r := bufio.NewReader(conn) // bufio wrapper for { line, _, err := r.ReadLine() // čítanie z conn if err == io.EOF { break } fmt.Printf("%s\n", line) } } }
net1/netclient1.go
![Page 21: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/21.jpg)
Pomocou putty
![Page 22: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/22.jpg)
Sntp klient conn, err := net.Dial("udp","0.sk.pool.ntp.org:123")
if err != nil { return }
r := bufio.NewReader(conn)
w := bufio.NewWriter(conn) data := make([]byte, 48)
data[0] = 3<<3 | 3
conn.SetDeadline(time.Now().Add(5 * time.Second))
defer conn.Close()
w.Write(data) // send request
w.Flush()
data, _, err = r.ReadLine() // read response var sec, frac uint64
sec = uint64(data[43]) | uint64(data[42])<<8 | uint64(data[41])<<16 | uint64(data[40])<<24
frac = uint64(data[47]) | uint64(data[46])<<8 | uint64(data[45])<<16 | uint64(data[44])<<24
nsec := sec * 1e9
nsec += (frac * 1e9) >> 32
t := time.Date(1900, 1, 1, 0, 0, 0, 0,time.UTC).Add(time.Duration(nsec)).Local()
fmt.Printf("Network time: %v\n", t)
sntp/sntpclient.go
RFC 4330http://tools.ietf.org/html/rfc4330
![Page 23: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/23.jpg)
Jednovláknový serverimport ( "bufio" "fmt" "io" "net" )
func main() { // porty <1024 majú špeciálne určenie
ln, err := net.Listen("tcp", ":8080") // server socket
if err != nil {
fmt.Println("connection error: " + err.Error())
} else {
conn, err := ln.Accept() // blokuje kým ja niekto
if err != nil { // nepokúsi o spojenie
fmt.Println("error: " + err.Error())
} else {
handleConnection(conn) // vieme vytvoriť len
} // jedno spojenie na “server”
}
}net2/netserver.go
![Page 24: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/24.jpg)
HandleConnectionfunc handleConnection(conn net.Conn) {
fmt.Println("handleConnection")
r := bufio.NewReader(conn)// wrapper na conn read stream
for {
line, _, err := r.ReadLine() // čítaj až do konca
if err == io.EOF {
break
} // a píš na konzolu
fmt.Printf("%s\n", line)
}
}
net2/netserver.go
![Page 25: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/25.jpg)
Viacvláknový serverfunc main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("connection error: " + err.Error())
} else {
for {
conn, err := ln.Accept()
if err != nil { // server by mal prežiť !!!
fmt.Println("error: " + err.Error())
continue
} // obslúženie konekcie spustíme v nezávislej
go handleConnection(conn) // gorutine
}
}
} net3/netserver.go
![Page 26: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/26.jpg)
ChatClient
type ChatClient struct {
clientID int // poradové číslo klienta
reader *bufio.Reader // reader a writer z/do konekcie
writer *bufio.Writer // klienta
}
func New_ChatClient(clientID int, conn net.Conn) *ChatClient {
return &ChatClient{// konštruktor vytvorí z ID a konekcie
clientID: clientID, // ChatClient
reader: bufio.NewReader(conn),
writer: bufio.NewWriter(conn),
}
}
Keď poznáme základy, skúsime vytvoriť jednoduchý chat-server umožnujúci: •viacero pripojení, •broadcastuje status všetkým
net4/chatroom.go
![Page 27: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/27.jpg)
ChatRoomtype ChatRoom struct { // všetci ChatClienti
clients []*ChatClient
}
func NewChatRoom() *ChatRoom {// prázdny ChatRoom
chatRoom := &ChatRoom{
clients: make([]*ChatClient, 0),
}
return chatRoom
}
func (chr *ChatRoom) NewChatClient(conn net.Conn) *ChatClient {
chatclient := New_ChatClient(len(chr.clients)+1, conn)
fmt.Printf("new client: %d\n", chatclient.clientID)
chr.clients = append(chr.clients, chatclient)
return chatclient
}
net4/chatroom.go
![Page 28: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/28.jpg)
ChatRoomfunc (chr *ChatRoom) handleConnection(conn net.Conn) {
chclient := chr.NewChatClient(conn) for {
line, _, err := chclient.reader.ReadLine()
if err == io.EOF {
break
}
msg := fmt.Sprintf("%d>%s\r\n", chclient.clientID,line)
fmt.Print(msg) // výpis na konzolu chatroomu
for _, client := range chr.clients {
if client.clientID != chclient.clientID {
client.writer.WriteString(msg)
client.writer.Flush()
}
} } }
net4/chatroom.go
![Page 29: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/29.jpg)
ChatRoom v akcii
net4/chatroom.go
![Page 30: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/30.jpg)
HTTP client GET Request-URI CRLF [GET | HEAD | POST ] Request-URI HTTP-Version CRLF GET http://google:80 HTTP/1.0
url := "http://google.com" response, err := http.Head(url)
fmt.Println(response.Status) // 200 OK
for k, v := range response.Header { // Content-Type:
fmt.Println(k+":", v) } // [text/html; charset=ISO-8859-2]
response, err = http.Get(url)
fmt.Println("\nbody:")
reader := bufio.NewReader(response.Body)
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
httpclient.go
![Page 31: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/31.jpg)
Čo s telom ? for {
line, _, err := reader.ReadLine()
if err == io.EOF { break }
strline := string(line)
var httpRef = regexp.MustCompile(
`(?i)href\s*=\s*(\"([^"]*\")|'[^']*'|([^'">\s]+))`)
matches := httpRef.FindAllString(strline, -1)
for _, match := range matches {
fmt.Println(match)
} }body:href="/search?"href="http://www.google.sk/imghp?hl=sk&tab=wi"href="http://maps.google.sk/maps?hl=sk&tab=wl"href="http://www.youtube.com/?gl=SK&tab=w1"href="https://mail.google.com/mail/?tab=wm"href="https://drive.google.com/?tab=wo"href="https://www.google.com/calendar?tab=wc"... httpclient.go
![Page 32: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/32.jpg)
WebCrawlerfunc Crawl71(url string, depth int, fetcher Fetcher) {
if depth <= 0 {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
} // najivné prehľadávanie do hĺbky, bez kontroly
fmt.Printf("found: %s %q\n", url, body)
for _, u := range urls {
Crawl71(u, depth-1, fetcher)
}
return
}
Crawl uses fetcher to recursively crawl pages starting with url, to a maximum of depth
TODO: Fetch URLs in parallel. Don't fetch the same URL twice.
http://tour.golang.org/concurrency/9
![Page 33: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/33.jpg)
WebCrawlingvar 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/",},
},}
golang.org
golang.org/pkg
golang.org/pkg/fmt
golang.org/os
golang.org/cmd
webcrawler.go
![Page 34: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/34.jpg)
WebCrawlerR // HashMap navštívených linkov
var visited = make(map[string]bool)
func CrawlR(url string, depth int, maxDepth int) {
if depth <= maxDepth {// ak nie som príliš hlboko
visited[url] = true // ok, bol som tu ...
suburls := crawlPageR(url, depth) // získaj urls
for _, url := range suburls.suburls {// prejdi ich
if _, seen := visited[url]; seen {// ak si tam
continue // bol, preskoč
}
CrawlR(url, depth+1, maxDepth) // inak rekurzia
}
}
} [0:http://golang.org/] "The Go Programming Language"[1:http://golang.org/pkg/] "Packages"not found: http://golang.org/cmd/[2:http://golang.org/pkg/fmt/] "Package fmt"[2:http://golang.org/pkg/os/] "Package os"
webcrawler.go
![Page 35: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/35.jpg)
WebCrawlerRtype Urls struct {
depth int // hĺbka podstránky od koreňa
suburls []string // zoznam linkov na nej
}
func crawlPageR(url string, depth int) *Urls {
body, urls, err := fetcher.Fetch(url) // toto nemáme if err != nil {
fmt.Println(err)
} else {
fmt.Printf("found[%d:%s] %q\n", depth, url, body)
}
return &Urls{depth + 1, urls}
}
webcrawler.go
size: 2871m27.4049993s
![Page 36: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/36.jpg)
var (
// akonáhle prejdeme stránku s adresou url, všetky jej vnorené Urls zapíšeme ho do kanálu
globalQueueOfUrls = make(chan Urls)
totalRuns = 0 // počet spustení crawlPage
// t.j. veľkosť fronty nespracovaných Urls
visited = make(map[string]bool) // navštívené urls
)
func crawlPage(url string, depth int) {
body, urls, err := fetcher.Fetch(url)
if err ...
fmt.Printf("[%d:%s] %q\n", depth, url, body)
globalQueueOfUrls <- Urls{depth + 1, urls}
}
WebCrawler 2
webcrawler.go
![Page 37: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/37.jpg)
func Crawl(url string, depth int) {
totalRuns++ // spracuj hlavnú stránku
visited[url] = true // navštívili sme ju
go crawlPage(url, 0) // pridaj jej Urls do fronty
for totalRuns > 0 { // kým je niečo vo fronte
totalRuns-- // dekrementuj veľkosť fronty
next := <-globalQueueOfUrls // vyber z fronty
if next.depth > depth { continue } // prihlboko
for _, url := range next.suburls { // do hĺbky
if _, seen := visited[url]; seen { continue }
visited[url] = true
totalRuns++ // nerekurzívne spracuj
go crawlPage(url, next.depth) // podstránky
} } }
WebCrawler 2
webcrawler.go
size: 2877.6544378s
![Page 38: Go networking](https://reader036.vdocuments.net/reader036/viewer/2022081420/56814b08550346895db82254/html5/thumbnails/38.jpg)
Riešenia je podstatné, či kričím mám biely/mám čierny, stačí len „už viem“ ?!
áno Dalo by sa to pre 3 biele, 3 čierne, 3 ľudia ?
nie Dalo by sa to pre 2 biele, 1 čierne, 2 ľudia ?
áno Dalo by sa to pre N biele, (N-1) čierne, N ľudia ? (napr.6,5,6)
áno Dalo by sa to pre >N biele, (N-1) čierne, N ľudia ? (napr.
8,5,6)
áno Dalo by sa to pre N biele, <(N-1) čierne, N ľudia ? (napr.
6,4,6)
áno