Thanks for the reply. So you're saying that all case statements are evaluated first before a choice is made. Which means that the full request/response must complete even if the timeout case finishes first.
If I swap the cases, now I consistently get a `timeout`. All cases are run to completion, so the full request/response occurs. Whats the reason for selecting the timeout? shouldn't it be pseudo-random? https://play.golang.org/p/M-7rMPJxOWq How should the done channel be setup to get this example working properly? On Tuesday, May 22, 2018 at 5:29:43 PM UTC-7, alex....@gmail.com wrote: > > https://golang.org/ref/spec#Select_statements > > Execution of a "select" statement proceeds in several steps: >> >> 1. For all the cases in the statement, the channel operands of >> receive operations and the channel and right-hand-side expressions of >> send >> statements are evaluated exactly once, in source order, upon entering the >> "select" statement. The result is a set of channels to receive from or >> send >> to, and the corresponding values to send. Any side effects in that >> evaluation will occur irrespective of which (if any) communication >> operation is selected to proceed. Expressions on the left-hand side of a >> RecvStmt with a short variable declaration or assignment are not yet >> evaluated. >> 2. If one or more of the communications can proceed, a single one >> that can proceed is chosen via a uniform pseudo-random selection. >> Otherwise, if there is a default case, that case is chosen. If there is >> no >> default case, the "select" statement blocks until at least one of the >> communications can proceed. >> 3. Unless the selected case is the default case, the respective >> communication operation is executed. >> 4. If the selected case is a RecvStmt with a short variable >> declaration or an assignment, the left-hand side expressions are >> evaluated >> and the received value (or values) are assigned. >> 5. The statement list of the selected case is executed. >> >> > So it evaluates all your function calls before doing the select in the > order they appear in single threadeddly. > > On Wednesday, 23 May 2018 07:29:59 UTC+8, ag wrote: >> >> This is interesting and I still don't get why it's not working. >> >> I modified the code a bit and expected it to immediately break out of >> select but it still waits for http calls to finish >> >> https://play.golang.org/p/z1mmqpQtOre >> >> package main >> >> import ( >> "errors" >> "fmt" >> "net/http" >> "net/http/httptest" >> "time" >> ) >> >> func main() { >> ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r >> *http.Request) { >> time.Sleep(1 * time.Second) >> w.WriteHeader(http.StatusOK) >> })) >> defer ts.Close() >> >> req, _ := http.NewRequest(http.MethodGet, ts.URL, nil) >> >> f := func(r *http.Request, n int) error { >> fmt.Println("Making the http call ", n) >> _, err := http.DefaultClient.Do(r) >> return err >> } >> >> ch := make(chan error, 1) >> >> timeout := 1 * time.Millisecond >> select { >> case ch <- errors.New("immediate timeout"): >> case ch <- f(req, 1): >> case ch <- f(req, 2): >> case <-time.After(timeout): >> fmt.Println("Timeout being called") >> ch <- errors.New("timeout") >> } >> >> err1 := <-ch >> fmt.Println("Received first error", err1) >> close(ch) >> >> >> // Output: >> >> // Making the http call 1 // Making the http call 2 // >> Received first error immediate timeout >> >> } >> >> >> >> >> >> On Monday, May 21, 2018 at 10:25:08 PM UTC-7, Burak Serdar wrote: >>> >>> On Mon, May 21, 2018 at 12:13 PM, <gopher...@gmail.com> wrote: >>> > timeout := 1 * time.Millisecond >>> > select { >>> > case ch <-f(req): >>> > case <-time.After(timeout): >>> > ch <- errors.New("timeout") >>> > } >>> >>> The instant 'select' is evaluated, ch is writable. Also time.After() >>> is called, and returns a channel that will be ready to be read in a >>> millisecond, i.e. not readable immediately. So it'll write to ch, and >>> will never timeout. >>> >>> To do what you described, you need to run the request piece in a >>> goroutine, and write the result to a channel: >>> >>> go func() { >>> _,err:=http.DefaultClient.Do(...) >>> ch<-err >>> }() >>> >>> Then, wait for the error to arrive on ch, or timeout: >>> >>> select { >>> case err:=<-ch: >>> case <-time.After(timeout): >>> } >>> >>> >>> > err:= <-ch >>> > close(ch) >>> > fmt.Println(err) // outputs <nil>, not timeout >>> > // Output: >>> > // timeout >>> > } >>> > >>> > >>> > -- >>> > You received this message because you are subscribed to the Google >>> Groups >>> > "golang-nuts" group. >>> > To unsubscribe from this group and stop receiving emails from it, send >>> an >>> > email to golang-nuts...@googlegroups.com. >>> > For more options, visit https://groups.google.com/d/optout. >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.