Recent use of Go to import data from Excel into the server is for http requests
But there is a problem that new Goroutine will be added indefinitely after reading from the file.
Causes all cards to be stuck in the initialization request and then gets stuck.
Problem simulation
- Simulation code
func main() { pool := sync.WaitGroup{} for i := 0; i < 500; i++ { pool.Add(1) go func(i int) { resp, err := http.Get("http://ip.3322.org") if err != nil { fmt.Println(i, err) } else { defer resp.Body.Close() result, _ := ioutil.ReadAll(resp.Body) fmt.Println(i, string(result)) } pool.Done() }(i) } pool.Wait() }
- If the number is small, it will be fine, but if the number is large, it will be found that the program is directly stuck for a period of time, then the error will be reported and no requests will be made.
Problem solving
- In fact, it can be seen that too many HTTP requests should be initiated at the same time, causing the system to jam data and not send it.
- When I think of submitting requests in Java with Thread, I think I can't limit the number of Goroutine s.
- The use of powerful fruit to find the cooperating pool has been written by the big guys.
- I added comments to the code as follows
package gopool import ( "sync" ) // Pool Goroutine Pool type Pool struct { queue chan int wg *sync.WaitGroup } // New Creates a New Cooperative Pool func New(size int) *Pool { if size <= 0 { size = 1 } return &Pool{ queue: make(chan int, size), wg: &sync.WaitGroup{}, } } // Add a new execution func (p *Pool) Add(delta int) { // If delta is positive, add it for i := 0; i < delta; i++ { p.queue <- 1 } // When delta is negative, it decreases. for i := 0; i > delta; i-- { <-p.queue } p.wg.Add(delta) } // Done execution completion minus one func (p *Pool) Done() { <-p.queue p.wg.Done() } // Wait waits for Goroutine to finish executing func (p *Pool) Wait() { p.wg.Wait() }
- Then modify the test method just now.
package main import ( "io/ioutil" "log" "net/http" "yumc.pw/cloud/lib/gopool" ) func main() { // Five concurrencies are limited here pool := gopool.New(5)// sync.WaitGroup{} for i := 0; i < 500; i++ { pool.Add(1) go func(i int) { resp, err := http.Get("http://ip.3322.org") if err != nil { fmt.Println(i, err) } else { defer resp.Body.Close() result, _ := ioutil.ReadAll(resp.Body) fmt.Println(i, string(result)) } pool.Done() }(i) } pool.Wait() }
- Perfect solution