Задать вопрос
@Pryby

Как правильно настроить канал в Golang?

Подскажите пожалуйста где мне тут поправить, что бы у меня в итоге функции ждали друг друга, main заканчивается и не успевают наполнится мапы
package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "strings"
    "time"
)

type inputDataStruct struct {
    url           []string
    count         int
    timeOut       int
    dataResponses map[string][]float64
    noResponses   map[string]int
}

func getResponse(urlChan chan string, inputData inputDataStruct) {
    url := <-urlChan
    start := time.Now()
    client := http.Client{
        Timeout: time.Duration(inputData.timeOut) * time.Second,
    }
    result, err := client.Get(url)
    if err != nil {
        inputData.noResponses[url] = inputData.noResponses[url] + 1
        log.Fatal(err)
    }
    elapsed := time.Since(start).Seconds()
    defer result.Body.Close()
    s := fmt.Sprintf("%s %f", url, elapsed)
    log.Println(s)
    if result.StatusCode == http.StatusOK {
        go appendResponse(urlChan, elapsed, inputData)
        urlChan <- url
    }
}

func appendResponse(urlChan chan string, time float64, inputData inputDataStruct) {
    inputData.dataResponses[<-urlChan] = append(inputData.dataResponses[<-urlChan], time)
}

func httpRequest(waitChan chan struct{}, inputData inputDataStruct) {
    //url := <- urlChan
    defer close(waitChan)
    urlChan := make(chan string)
    count := inputData.count
    j := 0
    for i := range inputData.url {
        for j < count {
            go getResponse(urlChan, inputData)
            urlChan <- inputData.url[i]
            j++
        }
        j = 0
    }

}

func parseArgument(item string) []string {
    return strings.Split(item, ",")
}
func findMinMaxAvg(values []float64) (min float64, max float64, avg float64) {
    if len(values) == 0 {
        return 0, 0, 0
    }

    min = values[0]
    max = values[0]
    var sum float64 = 0
    for _, v := range values {
        if v < min {
            min = v
        }
        if v > max {
            max = v
        }
        sum = sum + v
    }
    var count = float64(len(values))
    avg = sum / count
    return min, max, avg
}

func printMinMaxAvg(dataResponses map[string][]float64) {
    for key, _ := range dataResponses {
        min, max, avg := findMinMaxAvg(dataResponses[key])
        fmt.Printf("url: %s, min: %f, max: %f, avg: %f \n", key, min, max, avg)

    }
}

func main() {
    //urlArrChan := make(chan []string)
    waitChan := make(chan struct{})
    //var dataResponses = map[string][]float64{}
    //var noResponses = map[string]int{}
    url := flag.String("url", "", "url.")
    count := flag.Int("count", 1, "count response.")
    timeout := flag.Int("timeout", 1, "count response.")
    flag.Parse()
    var inputData inputDataStruct
    inputData.count = *count
    inputData.timeOut = *timeout
    inputData.dataResponses = map[string][]float64{}
    inputData.noResponses = map[string]int{}
    //inputData.urlChan = make(chan string)
    //inputData.syncChan = make(chan struct{})
    inputData.url = parseArgument(*url)
    //inputValue := parseArgument(*url)
    start := time.Now()
    //i := 0
    go httpRequest(waitChan, inputData)
    //urlArrChan <- inputValue
    <-waitChan
    //for i := range inputValue {
    //  //fmt.Print(inputValue[i])
    //  inputData.url = inputValue[i]
    //  httpRequest(inputData)
    //  //urlChan<-inputValue[i]
    //  i++
    //}
    elapsed := time.Since(start).Seconds()
    //<-inputData.urlChan
    //time.Sleep(1 * time.Second)
    fmt.Println(inputData.dataResponses)
    printMinMaxAvg(inputData.dataResponses)
    fmt.Printf("Total time: %f \n", elapsed)
    fmt.Println(inputData.noResponses)
    fmt.Scanln()
}
  • Вопрос задан
  • 113 просмотров
Подписаться 1 Простой 1 комментарий
Решения вопроса 1
@ghostiam
На Go писатель, серверов пинатель.
Вам нужно добавить sync.WaitGroup во внутрь функции httpRequest

Получиться приблизительно так:
func httpRequest(waitChan chan struct{}, inputData inputDataStruct) {
    //url := <- urlChan
    defer close(waitChan)
    urlChan := make(chan string)
    count := inputData.count
    j := 0
    var wg sync.WaitGroup
    for i := range inputData.url {
        for j < count {
            wg.Add(1)
            go func() {
getResponse(urlChan, inputData)
wg.Done()
}
            urlChan <- inputData.url[i]
            j++
        }
        j = 0
    }
wg.Wait()
}


Я конечно не уверен, что ваш код станет после этого рабочим, так как у вас там дальше запускаются горутины, например appendResponse(), только не понятно зачем.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы