Here is my code:
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!")
}
But:
for link := range result {
fmt.Println(link)
}
log.Println("Done!")
can't be executed, what's the reason?
You need to close the result channel so the for loop which reads from it is interrupted when its finished. For that you could rewrite the last part as:
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)
Your for loop never stop. When all the getUrl
finish, it continues to wait on result
. Try this:
wg.Wait()
close(result)
for link := range result {
fmt.Println(link)
}
log.Println("Done!")
If you want to print the result, you could do like:
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!")
}