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.