func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
	co, err := c.Dial(address)
	if err != nil {
		return nil, 0, err
	}
	defer co.Close()
	return c.ExchangeWithConn(m, co)
}
Exchange performs a synchronous query. It sends the message m to the address
contained in a and waits for a reply. Basic use pattern with a *dns.Client:

c := new(dns.Client)
in, rtt, err := c.Exchange(message, "127.0.0.1:53")

Exchange does not retry a failed query, nor will it fall back to TCP in
case of truncation.
It is up to the caller to create a message that allows for larger responses to be
returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
of 512 bytes
To specify a local address or a timeout, the caller has to set the `Client.Dialer`
attribute appropriately
package dns
import (
	"context"
	"crypto/tls"
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"strings"
	"time"
)
const (
	dnsTimeout     time.Duration = 2 * time.Second
	tcpIdleTimeout time.Duration = 8 * time.Second
)
type Conn struct {
	net.Conn                          
	UDPSize        uint16             
	TsigSecret     map[string]string  
	TsigProvider   TsigProvider       
	tsigRequestMAC string
}
type Client struct {
	Net       string       
	UDPSize   uint16       
	TLSConfig *tls.Config  
	Dialer    *net.Dialer  
	Timeout        time.Duration
	DialTimeout    time.Duration      
	ReadTimeout    time.Duration      
	WriteTimeout   time.Duration      
	TsigSecret     map[string]string  
	TsigProvider   TsigProvider       
	SingleInflight bool               
	group          singleflight
}
func Exchange(m *Msg, a string) (r *Msg, err error) {
	client := Client{Net: "udp"}
	r, _, err = client.Exchange(m, a)
	return r, err
}
func (c *Client) dialTimeout() time.Duration {
	if c.Timeout != 0 {
		return c.Timeout
	}
	if c.DialTimeout != 0 {
		return c.DialTimeout
	}
	return dnsTimeout
}
func (c *Client) readTimeout() time.Duration {
	if c.ReadTimeout != 0 {
		return c.ReadTimeout
	}
	return dnsTimeout
}
func (c *Client) writeTimeout() time.Duration {
	if c.WriteTimeout != 0 {
		return c.WriteTimeout
	}
	return dnsTimeout
}
func (c *Client) Dial(address string) (conn *Conn, err error) {
	var d net.Dialer
	if c.Dialer == nil {
		d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())}
	} else {
		d = *c.Dialer
	}
	network := c.Net
	if network == "" {
		network = "udp"
	}
	useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
	conn = new(Conn)
	if useTLS {
		network = strings.TrimSuffix(network, "-tls")
		conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
	} else {
		conn.Conn, err = d.Dial(network, address)
	}
	if err != nil {
		return nil, err
	}
	conn.UDPSize = c.UDPSize
	return conn, nil
}