That is an excellent example. Thanks!

On Thursday, May 24, 2018 at 8:26:36 AM UTC-7, alex....@gmail.com wrote:
>
> No, not the entire case statements, only the statements on the right of 
> the "<-"
>
> btw if you run it out of the playground (which makes concurrency more 
> deterministic)
> You would get timeout sometimes and nil sometimes
>
> Also maybe this example would help you understand what's going on.
> https://play.golang.org/p/DokMlHtdzi7
>
> On Thursday, 24 May 2018 16:58:20 UTC+8, gopher...@gmail.com wrote:
>>
>> 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