Go指南 练习:Web 爬虫 - 使用两种解法Mutex跟channel

本文通过两种方式实现了一个简单的Web爬虫:一是采用Mutex保证数据一致性;二是利用channel进行无锁并发管理。前者通过Mutex锁定map来跟踪已访问的URL,后者则由Master分配任务给Worker,使用map记录已抓取的URL。


前言

这里主要展示一下 Go tour 练习:Web 爬虫的两种做法
官方地址


提示:以下是本篇文章正文内容,下面代码可供参考

一、使用Mutex

主要是通过map做数据的存储,通过Mutex保证数据的一直性

type UrlMap struct {
	m   map[string]int
	mux sync.Mutex
}

func (urlMap *UrlMap) getUrl(url string) int {
	urlMap.mux.Lock()
	defer urlMap.mux.Unlock()
	return urlMap.m[url]
}

func (urlMap *UrlMap) setUrl(url string) {
	urlMap.mux.Lock()
	defer urlMap.mux.Unlock()
	urlMap.m[url]++
}

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, urlMap *UrlMap) {

	if depth <= 0 {
		return
	}

	if urlMap.getUrl(url) > 1 {
		return
	}

	body, urls, err := fetcher.Fetch(url)

	if err != nil {
		fmt.Println(err)
		return
	}

	var newUrls []string
	for _, u := range urls {
		if urlMap.getUrl(u) == 0 {
			urlMap.setUrl(u)
			newUrls = append(newUrls, u)
		}
	}

	fmt.Printf("found: %s %q\n", urls, body)
	for _, u := range newUrls {
		go Crawl(u, depth-1, fetcher, urlMap)
	}

	return
}

func main() {
	urlMap := UrlMap{m: map[string]int{"https://golang.org/": 1}}
	Crawl("https://golang.org/", 4, fetcher, &urlMap)
	time.Sleep(100 * time.Millisecond)
}

二、使用channel

通过master管理worker,每个worker负责fetch的工作(I/O 工作),在master使用map统一管理fetch过的url,这样就不需要使用锁机制了

type Fetcher interface {
	Fetch(url string) (body string, urls []string, err error)
}

func worker(url string, ch chan []string, fetcher Fetcher) {
	_, urls, err := fetcher.Fetch(url)
	if err != nil {
		ch <- []string{}
	} else {
		ch <- urls
	}
}

func master(ch chan []string, fetcher Fetcher) {
	n := 1
	urlMap := map[string]bool{}
	// listen channel
	// get url list in chan []string
	for urls := range ch {
		//get single url
		for _, url := range urls {
			if urlMap[url] != true {
				n++
				urlMap[url] = true
				go worker(url, ch, fetcher)
			}
		}
		n--
		if n == 0 {
			break
		}
	}
}

func ConcurrentChannel(url string, fetcher Fetcher) {
	//make a channel to listen the fetch resutls
	c := make(chan []string)
	//send the url to channel
	go func() {
		c <- []string{url}
	}()
	master(c, fetcher)
}

func main() {
	fmt.Printf("=== ConcurrentChannel ===\n")
	ConcurrentChannel("https://golang.org/", fetcher)
}

func (f fakeFetcher) Fetch(url string) (string, []string, error) {
	if res, ok := f[url]; ok {
		fmt.Printf("found:   %s %q\n", url, res.body)
		return res.body, res.urls, nil
	}
	fmt.Printf("missing: %s\n", url)
	return "", nil, fmt.Errorf("not found: %s", url)
}

总结

在使用go语言时候,应该尽量使用通讯channel的机制来更好利用goroutine带来的便利
【轴承故障诊断】加权多尺度字典学习模型(WMSDL)及其在轴承故障诊断上的应用(Matlab代码实现)内容概要:本文介绍了加权多尺度字典学习模型(WMSDL)在轴承故障诊断中的应用,并提供了基于Matlab的代码实现。该模型结合多尺度分析与字典学习技术,能够有效提取轴承振动信号中的故障特征,提升故障识别精度。文档重点阐述了WMSDL模型的理论基础、算法流程及其在实际故障诊断中的实施步骤,展示了其相较于传统方法在特征表达能力和诊断准确性方面的优势。同时,文中还提及该资源属于一个涵盖多个科研方向的技术合集,包括智能优化算法、机器学习、信号处理、电力系统等多个领域的Matlab仿真案例。; 适合人群:具备一定信号处理和机器学习基础,从事机械故障诊断、工业自动化、智能制造等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①学习并掌握加权多尺度字典学习模型的基本原理与实现方法;②将其应用于旋转机械的轴承故障特征提取与智能诊断;③结合实际工程数据复现算法,提升故障诊断系统的准确性和鲁棒性。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注字典学习的训练过程与多尺度分解的实现细节,同时可参考文中提到的其他相关技术(如VMD、CNN、BILSTM等)进行对比实验与算法优化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值