У меня есть веб-сервер, работающий на порте и обрабатывающий почтовый запрос, который внутренне вызывает другой URL для получения ответа с помощью goroutine и продолжения.
Я разделил весь поток на другой метод.Черновик кода.
package main
import (
"bytes"
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
"time"
)
var status_codes string
func main() {
router := mux.NewRouter().StrictSlash(true)
/*router := NewRouter()*/
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintf(w, "Hello!!!")
})
router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
prepare(w, r, vars["name"])
}).Methods("POST")
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", 8080), router))
}
func prepare(w http.ResponseWriter, r *http.Request, name string) {
//initializing for the current request, need to maintain this variable for each request coming
status_codes = ""
//other part of the code and call to goroutine
var urls []string
//lets say all the url loaded, call the go routine func and wait for channel to respond and then proceed with the response of all url
results := callUrls(urls)
process(w, results)
}
type Response struct {
status int
url string
body string
}
func callUrls(urls []string) []*Response {
ch := make(chan *Response, len(urls))
for _, url := range urls {
go func(url string) {
//http post on url,
//base on status code of url call, add to status code
//some thing like
req, err := http.NewRequest("POST", url, bytes.NewBuffer(somePostData))
req.Header.Set("Content-Type", "application/json")
req.Close = true
client := &http.Client{
Timeout: time.Duration(time.Duration(100) * time.Second),
}
response, err := client.Do(req)
if err != nil {
status_codes += "200,"
//do other thing with the response received
} else {
status_codes += "500,"
}
// return to channel accordingly
ch <- &Response{200, "url", "response body"}
}(url)
}
var results []*Response
for {
select {
case r := <-ch:
results = append(results, r)
if len(results) == len(urls) {
//Done
close(ch)
return results
}
}
}
}
func process(w http.ResponseWriter, results []*Response){
//read those status code received from all urls call for the given request
fmt.Println("status", status_codes)
//Now the above line keep getting status code from other request as well
//for eg. if I have called 5 urls then it should have
//200,500,204,404,200,
//but instead it is
//200,500,204,404,200,204,404,200,204,404,200, and some more keep growing with time
}
Приведенный выше код выполняет следующие действия:
- Переменная объявляет глобально, инициализируется в функции prepare.
- добавляет значение в функцию go callUrls.
- читать эти переменные в функции процесса
Теперь я должен передать эти переменные, объявленные глобально, каждому вызову функции, чтобы сделать их локальными, поскольку тогда они не будут использоваться совместно (я бы не хотелчтобы сделать это.)
Или есть какой-то другой подход для достижения того же самого, не добавляя больше аргумента к вызываемой функции.
Поскольку у меня будет немного других строковых и целых значений, чтобудет использоваться во всей программе и в обычной функции go.
Какой будет правильный способ сделать их поточно-ориентированными, и только 5 кодов для каждого запроса, поступающего на порт одновременно.