V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
whoami9894
V2EX  ›  Go 编程语言

请教这段 go 代码哪里造成阻塞

  •  
  •   whoami9894 · 2018-08-05 11:48:18 +08:00 · 3138 次点击
    这是一个创建于 2336 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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--*--
    
    
    11 条回复    2018-08-05 22:57:48 +08:00
    XxxxD
        1
    XxxxD  
       2018-08-05 15:18:00 +08:00
    这是弄代理池么,不过我不懂 go, 路过
    lcorange
        2
    lcorange  
       2018-08-05 18:01:43 +08:00
    --*--block here--*--这里会再往后会报错么?我没法运行你的代码,那几个网页我试了试,刷新太快是不会返回数据的。是不是中间发生了异常,defer wg1.Done() ,这句一直没法执行,一共是 8 个,看日志只消耗了 4 个,导致外部卡在 wg1.Wait() 上
    myself659
        3
    myself659  
       2018-08-05 20:35:15 +08:00
    chan result 在哪里有接收 ?
    whoami9894
        4
    whoami9894  
    OP
       2018-08-05 21:17:37 +08:00 via Android
    @XxxxD
    是的
    whoami9894
        5
    whoami9894  
    OP
       2018-08-05 21:22:03 +08:00 via Android
    @lcorange

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

    函数里三个 defer,正常输出了 exit 的话,倒序就是卡在 io.reader.close 或 wg.done 那里了
    whoami9894
        6
    whoami9894  
    OP
       2018-08-05 21:24:17 +08:00 via Android
    @myself659

    在另一个函数里接收,这八个网页解析出的 proxy 只有不到两百,channel 缓冲给了 500 不会阻塞在这里
    sunznx
        7
    sunznx  
       2018-08-05 21:30:03 +08:00
    ```
    for i := 0; i < len(queue); i++ {
    ```

    这里有 bug 吧,你 queue 是一直在减的,i = 4,len(queue) = 4
    whoami9894
        8
    whoami9894  
    OP
       2018-08-05 22:15:58 +08:00 via Android
    @sunznx

    你说的 i==4 是因为前一个循环终值是 4 吗,前一个循环里的 i 作用域只在那个循环里
    后面那个循环是新声明的 i=0 ~ 7 开了 8 个 goroutine
    sunznx
        9
    sunznx  
       2018-08-05 22:49:25 +08:00
    @whoami9894 len(queue) 是一直在减少的
    sagaxu
        10
    sagaxu  
       2018-08-05 22:54:44 +08:00 via Android
    for i := 0; i < len(queue); i++

    改为
    qlen := len(queue)
    for i := 0; i < qlen; i++
    whoami9894
        11
    whoami9894  
    OP
       2018-08-05 22:57:48 +08:00 via Android
    @sunznx
    @sagaxu

    嗷嗷明白问题了,感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2798 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:54 · PVG 21:54 · LAX 05:54 · JFK 08:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.