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.

Reply via email to