Golang Go语言中请教这段代码哪里造成阻塞

发布于 1周前 作者 songsunli 来自 Go语言
func process_kuaidaili() chan Proxy {
	var wg1 sync.WaitGroup
	result := make(result_list, 500)
	index_url := "https://www.kuaidaili.com/free"
	queue := make(task_list, 10) //change count
	for i := 1; i <= 4; i++ {
		queue <- index_url + "/inha/" + strconv.Itoa(i)
		queue <- index_url + "/intr/" + strconv.Itoa(i)
	}
	fmt.Println(len(queue))
	wg1.Add(len(queue))
	for i := 0; i < len(queue); i++ {
		go func() {
			defer wg1.Done()
            //request 函数传 channel 进去,取出一个 URL 发起请求
			resp := request(queue, "www.kuaidaili.com")		
			defer resp.Body.Close()
			defer fmt.Println("exit")
			doc, _ := goquery.NewDocumentFromResponse(resp)
			doc.Find("tr").Each(func(i int, contentSelection *goquery.Selection) {
				_IP := contentSelection.Find("td").Eq(0).Text()
				if reg_ip.Find([]byte(_IP)) != nil {
					_Port := contentSelection.Find("td").Eq(1).Text()
					_Anonymous := contentSelection.Find("td").Eq(2).Text()
					if _Anonymous == "高匿名" {
						_Anonymous = "1"
					} else {
						_Anonymous = "0"
					}
					_SSL := contentSelection.Find("td").Eq(3).Text()
					if _SSL == "HTTPS" {
						_SSL = "1"
					} else {
						_SSL = "0"
					}
					append_proxy := Proxy{
						IP:        _IP,
						Port:      _Port,
						Anonymous: _Anonymous,
						SSL:       _SSL,
					}
					result <- append_proxy
					fmt.Printf("-----%v------\n", len(result))
				}
			})
		}()
	}
	wg1.Wait()
	fmt.Println("return")
	return result
}

main 函数调用

func main() {
	fmt.Println("start")
	aa := process_kuaidaili()
	fmt.Println(len(aa))
}

程序阻塞,输出:

start
8
https://www.kuaidaili.com/free/inha/1
-----1------
-----2------
-----3------
-----4------
-----5------
-----6------
-----7------
-----8------
-----9------
-----10------
-----11------
-----12------
-----13------
-----14------
-----15------
exit
https://www.kuaidaili.com/free/intr/1
exit
https://www.kuaidaili.com/free/inha/2
exit
https://www.kuaidaili.com/free/intr/2
exit
--*--block here--*--


Golang Go语言中请教这段代码哪里造成阻塞

更多关于Golang Go语言中请教这段代码哪里造成阻塞的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

这是弄代理池么,不过我不懂 go, 路过

更多关于Golang Go语言中请教这段代码哪里造成阻塞的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


–block here––这里会再往后会报错么?我没法运行你的代码,那几个网页我试了试,刷新太快是不会返回数据的。是不是中间发生了异常,defer wg1.Done() ,这句一直没法执行,一共是 8 个,看日志只消耗了 4 个,导致外部卡在 wg1.Wait() 上

chan result 在哪里有接收 ?



不会报错是一直阻塞在这里

函数里三个 defer,正常输出了 exit 的话,倒序就是卡在 io.reader.close 或 wg.done 那里了



在另一个函数里接收,这八个网页解析出的 proxy 只有不到两百,channel 缓冲给了 500 不会阻塞在这里

<br>for i := 0; i &lt; len(queue); i++ {<br>

这里有 bug 吧,你 queue 是一直在减的,i = 4,len(queue) = 4



你说的 i==4 是因为前一个循环终值是 4 吗,前一个循环里的 i 作用域只在那个循环里
后面那个循环是新声明的 i=0 ~ 7 开了 8 个 goroutine

len(queue) 是一直在减少的

for i := 0; i < len(queue); i++

改为
qlen := len(queue)
for i := 0; i < qlen; i++




嗷嗷明白问题了,感谢

当然,我很乐意帮助你分析Go语言代码中的阻塞问题。不过,由于你没有提供具体的代码片段,我将基于一些常见的情况进行解释,希望这些能帮助你找到问题所在。

在Go语言中,常见的阻塞情况包括:

  1. 死锁(Deadlock):当两个或多个goroutine互相等待对方持有的锁时,会发生死锁。检查代码中的锁使用,确保每次加锁后都有对应的解锁操作。

  2. 通道(Channel)阻塞:当向一个无缓冲或满缓冲的通道发送数据时,或从一个空缓冲的通道接收数据时,goroutine会阻塞。确保发送和接收操作都能匹配上,避免单方面的等待。

  3. I/O操作阻塞:网络请求、文件读写等I/O操作可能会阻塞。使用goroutine和通道来处理这些操作,可以保持程序的并发性。

  4. 同步原语(Sync Primitives):如sync.WaitGroupsync.Mutexsync.Cond等,使用不当也可能导致阻塞。确保正确地管理这些同步原语的状态。

为了更具体地定位问题,你可以:

  • 使用Go的race detector(通过运行go run -race your_program.go)来检测数据竞争和死锁。
  • 检查所有通道的发送和接收操作,确保它们都能正确匹配。
  • 审查代码中所有的锁和同步原语的使用,确保它们不会导致死锁或不必要的等待。

如果可能,提供具体的代码片段将有助于更精确地诊断问题。

回到顶部