Based on this stackoverflow answer 
<https://stackoverflow.com/questions/59889882/specifying-dns-server-for-lookup-in-go>
:

-----
package main

import (
        "context"
        "fmt"
        "net"
        "time"
)

const DNS_SERVER = "1.2.3.4:53"
const TIMEOUT = 3 * time.Second

func main() {
        main_context, main_cancel := 
context.WithCancel(context.Background())
        go func() {
                time.Sleep(TIMEOUT)
                main_cancel()
        }()

        r := &net.Resolver{
                PreferGo: true,
                Dial: func(ctx context.Context, network, address string) 
(net.Conn, error) {
                        d := net.Dialer{
                                Timeout: 2 * time.Second,
                        }
                        return d.DialContext(ctx, network, DNS_SERVER)
                },
        }
        ip, err := r.LookupHost(main_context, "www.google.com")
        fmt.Printf("%v (err: %v)\n", ip, err)
}
-----

What I find on macOS:

[] (err: lookup www.google.com on 10.12.0.1:53: dial udp 1.2.3.4:53: 
operation was canceled)

10.12.0.1 is the "default" DNS server on this network, and the custom 
dialer is overriding this.

The program actually aborts after *5* seconds, which is also the interval 
between retries if the overall context is not cancelled (the total time to 
give up is 20 seconds in that case).  So the net.Dialer timeout doesn't 
work in the way you might expect, and the UDP exchange isn't immediately 
cancelled when the context expires; but it *does* terminate with an 
"operation was canceled" error without further retries.

On Wednesday, 12 January 2022 at 10:05:57 UTC Brian Candler wrote:

> On Wednesday, 12 January 2022 at 08:41:23 UTC lege...@gmail.com wrote:
>
>> What I think it's not so good is that I must add the select at all the 
>> places the goroutine is waiting or looping
>>
>
> I don't think you do.  Well-behaved functions which take a Context will 
> return with an error if the context is cancelled - and presumably you're 
> already checking for an error, so it doesn't make any difference.
>
> If you're waiting for communication on a channel, then you *may* need to 
> check for context.  But if you're reading from a channel, and the context 
> propagates to the other goroutine, and the other goroutine closes the 
> channel, then that's not an issue either.
>
> When it becomes a bit awkward is with IO on sockets, since 
> io.Reader/io.Writer don't have a context.  There is a long discussion at 
> #20280 <https://github.com/golang/go/issues/20280>, and I made some notes 
> here <https://github.com/golang/go/issues/20280#issuecomment-655588450>.  
> The pattern which was explained to me is that you can have a separate 
> thread which waits for the context close, and then sets a read or write 
> deadline on the IO; that will cause an ongoing operation to terminate 
> immediately.
>
> I don't know if there's a DNS client library which implements this 
> pattern. 
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/3a4fee99-96fa-4e93-b4d0-3e8cee057c43n%40googlegroups.com.

Reply via email to