On 28 August 2012 10:50, Thomas Gawehns <
thomas....@gmail.com> wrote:
> Found a solution without data race and without mutex:
>
> func Crawl(url string, depth int, fetcher Fetcher) {
>
> var nextUrlToVisit func(in chan string, out chan string)
> nextUrlToVisit = func(in chan string, out chan string) {
> visitedUrls := make(map[string]bool, 100)
> for {
> url := <-in
> if( url == "" ){
> return
> }
> if(visitedUrls[url]){
> out<- ""
> }else{
> out<- url
> }
> }
> }
The above is pretty much equivalent to using a mutex.
(I assume you actually wanted to add urls to the visitedUrls map)
When I'm designing concurrent Go code, I often try to think:
"what piece of code *wants* this data?". If I'm creating a goroutine
solely to guard access to a particular piece of data, with no
extra functionality, then I tend to think I'm doing something wrong.
Sometimes, of course, several goroutines *do* need access to the
same data, in which case a mutex is a fine thing, but I don't think
that's the case here.
> in := make(chan string)
> out := make(chan string)
> var InnerCrawl func(url string, depth int,
> fetcher Fetcher, finish chan bool)
> InnerCrawl = func (url string, depth int,
> fetcher Fetcher, finish chan bool) {
Another minor point: it's not that usual in Go to
write recursive closures - a separate function is almost
as easy to write, and somewhat easier to read.