Схема работы:
- делаем запрос;
- получаем ответ JSON, парсим его;
- создаем срез с uri адресами(срез содержит до 100 ссылок);
- отправляем в канал другой горутине;
- эта горутина делает запрос ко всем uri(которые находятся в срезе);
- получаем ответ, парсим его;
func Test() {
chnl := make(chan string)
wg := new(sync.WaitGroup)
client := tools.HttpClient()
wg.Add(1)
go getSports(chnl, client, wg)
go getOdds(chnl, client, wg)
wg.Wait()
}
// Getting live id events and send it to other func-goroutine.
// It sends only data to channel [>> chan<- string].
func getSports(ch chan<- string, client *http.Client, wg *sync.WaitGroup) {
defer wg.Done()
// make request
body := tools.GetRequest(client, "GET", API["sports"])
// parse json
var s bet.Sport
json.Unmarshal(body, &s)
count := 0
for _, rawdata := range s {
// get only necessary events id
for _, sport := range rawdata.Payload.CompetitionsWithEvents {
for key := range SportsMap {
// if sport id not in map
if sport.Competition.SportID != key {
continue
}
// send event id to goroutine with chanal
// this goroutine will make request to get markets
for _, event := range sport.Events {
ch <- event.ID
count++
}
}
}
}
fmt.Println()
fmt.Println("[Total events: ", count, "]")
}
// Getting live events markets.
func getOdds(c <-chan string, client *http.Client, wg *sync.WaitGroup) {
defer wg.Done()
for {
// make request
uri := fmt.Sprintf(API["odds"] + <-c + ":")
body := tools.GetRequest(client, "GET", uri)
// parse json
var e bet.Event
json.Unmarshal(body, &e)
meta := make(map[string]interface{})
for _, rawdata := range e {
// make meta info.
meta["nativeID"] = rawdata.Payload.ID,
}
fmt.Println(meta)
}
}
По факту, у меня две горутины работют синхронно, одна делает запрос, парсит ответ и отправляет по одному евенту в другой канал и тот уже отправляет запрос к uri.
Хотелось бы, что бы код работал паралельно.
Я написал примерный код, но не уверен, что он корретный:
var (
maxWorkers = runtime.GOMAXPROCS(0)
sem = semaphore.NewWeighted(int64(maxWorkers))
out = make([]int, 32)
)
// Func getSports is getting live events id.
func getSports(client *http.Client) []string {
// make request
body := tools.GetRequest(client, "GET", API["sports"])
// parse json
var s Sport
json.Unmarshal(body, &s)
// events id will using to make url for requests.
var uri string
var events []string
for _, rawdata := range s {
for _, sport := range rawdata.Payload.CompetitionsWithEvents {
// get only necessary events id
for key := range SportsMap {
// if sport id not in map
if sport.Competition.SportID != key {
continue
}
for _, event := range sport.Events {
uri = fmt.Sprintf(API["odds"] + event.ID + ":")
events = append(events, uri)
}
}
}
}
return events
}
// getOdds is geting live events markets.
func getOdds(client *http.Client, url string, wg *sync.WaitGroup) {
defer wg.Done()
defer sem.Release(1)
body := tools.GetRequest(client, "GET", url)
MakeMeta(body)
}
// Run scanner.
func Test() {
ctx := context.Background()
client := tools.HttpClient()
wg := new(sync.WaitGroup)
events := getSports(client)
for _, url := range events {
if err := sem.Acquire(ctx, 1); err != nil {
log.Printf("Failed to acquire semaphore: %v", err)
break
}
wg.Add(1)
go getOdds(client, url, wg)
}
wg.Wait()
// If you are already waiting for the workers by some other means (such as an
// errgroup.Group), you can omit this final Acquire call.
if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil {
log.Printf("Failed to acquire semaphore: %v", err)
}
fmt.Println()
fmt.Println("[Total events: ", len(events), "]")
}
P.S. если сделать слишком быстрым прогу, сайт-донор присылает пустой массив, думал добавить ограничение горутин)