2016-12-28 2 views
0

が私のコードです:なぜ `sync.WaitGroup`が終了できないのですか?ここで

package main 

import (
    "bytes" 
    "crypto/md5" 
    "encoding/hex" 
    "encoding/json" 
    "fmt" 
    "io/ioutil" 
    "log" 
    "net/http" 
    "runtime" 
    "sync" 
) 

type Data struct { 
    Link string `json:"url"` 
} 
type Result struct { 
    Code uint32 
    Msg string `json:"msg"` 
    Data Data `json:"data"` 
} 

const (
    URL  = "http://qiye.wxsdc.ediankai.com/api/v1/suppliers/1/staff/1/box/get" 
    SIGNKEY = "i5OqMrNXVyOJ5GEMYoEtRHqN1P9ghk6I" 
    DATA_ID = "2965612126" 
    EQU_ID = "1482806063" 
) 

func getMD5Hash(text string) string { 
    hasher := md5.New() 
    hasher.Write([]byte(text)) 
    return hex.EncodeToString(hasher.Sum(nil)) 
} 

func getUrl(payload []byte, wg *sync.WaitGroup, result chan string) { 
    req, err := http.NewRequest("POST", URL, bytes.NewBuffer(payload)) 
    req.Header.Set("Content-Type", "application/json") 

    client := &http.Client{} 
    resp, err := client.Do(req) 
    if err != nil { 
     panic(err) 
    } 
    defer resp.Body.Close() 

    body, err := ioutil.ReadAll(resp.Body) 
    if err != nil { 
     panic(err) 
    } 
    var res Result 
    json.Unmarshal(body, &res) 
    log.Println(res.Data.Link) 
    result <- res.Data.Link 
    wg.Add(-1) 
} 
func main() { 
    parameterStr := fmt.Sprintf("%vdata_id%vequ_id%v%v", SIGNKEY, DATA_ID, EQU_ID, SIGNKEY) 
    log.Println(parameterStr) 
    sign := getMD5Hash(parameterStr) 
    log.Println(sign) 
    var payload map[string]string = make(map[string]string) 
    payload["equ_id"] = EQU_ID 
    payload["data_id"] = DATA_ID 
    payload["sign"] = sign 

    payloadJson, err := json.Marshal(payload) 
    if err != nil { 
     log.Fatalln("convet paylod failed!") 
    } 
    log.Println(string(payloadJson)) 

    runtime.GOMAXPROCS(runtime.NumCPU()) 
    var wg sync.WaitGroup 
    result := make(chan string) 
    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go getUrl(payloadJson, &wg, result) 
    } 
    wg.Wait() 
    for link := range result { 
     fmt.Println(link) 
    } 
    log.Println("Done!") 
} 

しかし:

for link := range result { 
    fmt.Println(link) 
} 
log.Println("Done!") 

を実行することができない、その理由は何ですか?

+0

あなたはどこでも 'result'チャンネルを閉じていません。 'for'ループが始まる前にそれを閉じます。また、 'getUrl'関数の最後に-1をハッキングするのではなく、' woo.Done() 'を置くのはなぜですか? – nosequeldeebee

答えて

1

あなたは結果チャネルを閉じる必要があり、これを試してみてください。そのために最後の部分を次のように書き直すことができます:

var wg sync.WaitGroup 
result := make(chan string) 
go func() { 
    for link := range result { 
     fmt.Println(link) 
    } 
}() 
for i := 0; i < 10; i++ { 
    wg.Add(1) 
    go getUrl(payloadJson, &wg, result) 
} 
wg.Wait() 
close(result) 
0

あなたのforループは決して停止しません。 getUrlがすべて終了すると、それはresultで待機し続けます。あなたは結果を印刷したい場合は、あなたが好きでした

wg.Wait() 

close(result) 

for link := range result { 
    fmt.Println(link) 
} 
log.Println("Done!") 

:ときに完成し、それからの読み込みループのために中断されるように

package main 

import (
    "bytes" 
    "crypto/md5" 
    "encoding/hex" 
    "encoding/json" 
    "fmt" 
    "io/ioutil" 
    "log" 
    "net/http" 
    "runtime" 
    "sync" 
) 

type Data struct { 
    Link string `json:"url"` 
} 
type Result struct { 
    Code uint32 
    Msg string `json:"msg"` 
    Data Data `json:"data"` 
} 

const (
    URL  = "http://qiye.wxsdc.ediankai.com/api/v1/suppliers/1/staff/1/box/get" 
    SIGNKEY = "i5OqMrNXVyOJ5GEMYoEtRHqN1P9ghk6I" 
    DATA_ID = "2965612126" 
    EQU_ID = "1482806063" 
) 

func getMD5Hash(text string) string { 
    hasher := md5.New() 
    hasher.Write([]byte(text)) 
    return hex.EncodeToString(hasher.Sum(nil)) 
} 

func getUrl(payload []byte, wg *sync.WaitGroup, result chan string) { 
    defer func(){ 
wg.Done() 
}(); 

    req, err := http.NewRequest("POST", URL, bytes.NewBuffer(payload)) 
    req.Header.Set("Content-Type", "application/json") 

    client := &http.Client{} 
    resp, err := client.Do(req) 
    if err != nil { 
return 
    } 
    defer resp.Body.Close() 

    body, err := ioutil.ReadAll(resp.Body) 
    if err != nil { 
     return 
    } 
    var res Result 
    json.Unmarshal(body, &res) 
    log.Println(res.Data.Link) 
    result <- res.Data.Link 
} 

func monitor(wg *sync.WaitGroup, cs chan string) { 
    wg.Wait() 
    close(cs) 
} 
func printResult(result <-chan string, done chan<- bool) { 
    for i := range result { 
     fmt.Println(i) 
    } 

    done <- true 
} 

func main() { 
    parameterStr := fmt.Sprintf("%vdata_id%vequ_id%v%v", SIGNKEY, DATA_ID, EQU_ID, SIGNKEY) 
    log.Println(parameterStr) 
    sign := getMD5Hash(parameterStr) 
    log.Println(sign) 
    var payload map[string]string = make(map[string]string) 
    payload["equ_id"] = EQU_ID 
    payload["data_id"] = DATA_ID 
    payload["sign"] = sign 

    payloadJson, err := json.Marshal(payload) 
    if err != nil { 
     log.Fatalln("convet paylod failed!") 
    } 
    log.Println(string(payloadJson)) 

    runtime.GOMAXPROCS(runtime.NumCPU()) 
    var wg sync.WaitGroup 
    result := make(chan string) 
    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go getUrl(payloadJson, &wg, result) 
    } 

    go monitor(&wg, result) 

    done := make(chan bool, 1) 
    go printResult(result, done) 
    <-done 
    log.Println("Done!") 
} 
関連する問題