I send http requests on the channel and return a channel to read off each request:
func reqs(done <-chan bool, reqs ...*http.Request) chan *http.Request {
out := make(chan *http.Request)
go func() {
defer close(out)
for _, r := range reqs {
select {
case out <- r:
case <-done:
return
}
}
}()
return out
}
func (a *ReadReq) req1(done chan bool, ch chan *http.Request) chan []byte {
out := make(chan []byte)
go func(ch chan *http.Request) {
defer close(out)
r, ok := <-ch
if !ok{
panic("no value received on channel for req1")
}
rb, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
errj := json.Unmarshal(rb, a)
if errj != nil {
panic(errj)
}
rbody := a.withdrawRequest().inAmount()
bb, errbb := json.Marshal(rbody)
if errbb != nil {
panic(errbb)
}
select {
case out <- bb:
case <-done:
return
}
}(ch)
return out
}
a.req1(done, ch)
, the request is not received on the channelfunc (a *ReadReq) ServeHTTP(w http.ResponseWriter, r *http.Request) {
done := make(chan bool)
defer close(done)
ch := reqs(done, r)
for request := range ch {
err := request.ParseForm()
if err != nil{
panic(err)
}
switch param := request.Form.Get("reqx"); param {
case "001":
chreq1 := a.req1(done, ch)
w.Write(<-chreq1)
return
case "002":
chreq2 := a.req2(done, ch)
w.Write(<-chreq2)
return
}
}
}
Where am I going wrong in this implemenation.
I've simplified your code to 3 functions, and explained reasons in comments:
package main
import "fmt"
// pass parameters into channel and handle them orderly
// f1 will work properly
func f1(doneCh chan bool, args ...int) chan int {
argCh := make(chan int)
go func() {
defer close(argCh) // cause
for _, arg := range args {
select {
case argCh <- arg:
case <-doneCh:
return
}
}
fmt.Println("f1: exit loop goroutine, close the argCh")
}()
return argCh
}
func f2(n int) {
doneCh := make(chan bool)
defer close(doneCh)
argCh := f1(doneCh, n)
for arg := range argCh {
// 1. we taken the ONLY ONE arg from argCh, just like you taken request object from out channel
fmt.Printf("f2: taken %d from argCh\n", arg)
// 2. now f1 goroutine exiting the loop, and argCh channel will be defer closed
// here is the problem
// 3. you passed the CLOSED channel argCh info f3
outCh := f3(doneCh, argCh)
fmt.Println("f3 result:", <-outCh)
}
}
func f3(doneCh chan bool, inCh chan int) chan int {
outCh := make(chan int)
go func(ch chan int) {
defer close(outCh)
n, ok := <-ch
fmt.Printf("f3: n: %d, ok: %t\n", n, ok)
// want 10, true
// got 0, false
// since ch has been closed, the false is expected, 0 is default value of channel type which shouldn't be used
select {
case outCh <- n + 1:
case <-doneCh:
return
}
}(inCh)
return outCh
}
func main() {
f2(999)
}
output:
f1: exit loop goroutine, close the argCh
f2: taken 999 from argCh
f3: n: 0, ok: false
f3 result: 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.