Тип net.DNSError

Тип net.DNSError используется для представления ошибок, которые возникают при разрешении доменных имен через DNS. Он реализует интерфейс error и содержит дополнительные поля, позволяющие определить причину ошибки: имя хоста, которое не удалось разрешить, является ли ошибка временной, а также вызвана ли она неверным форматом имени. Этот тип возвращается функциями, выполняющими DNS-запросы, такими как net.LookupHost, net.LookupIP и другими.

Структура

gotype DNSError struct {
  Err     string
  Name    string
  Server    string
  IsTimeout   bool
  IsTemporary bool
  IsNotFound  bool
}

Поле Err содержит текстовое описание ошибки, Name — доменное имя, которое вызвало ошибку, Server — адрес DNS-сервера (если доступен). Поле IsTimeout указывает, была ли ошибка вызвана таймаутом, IsTemporary — является ли ошибка временной, а IsNotFound говорит о том, что запрошенное имя не найдено.

Синтаксис

govar err error = &net.DNSError{
  Err:  "no such host",
  Name: "example.com",
}

Обычно объект net.DNSError создается не вручную, а возвращается функциями пакета net при ошибке DNS-запроса.

Пример

Выполним разрешение несуществующего домена и обработаем ошибку как net.DNSError:

gopackage main

import (
  "fmt"
  "net"
)

func main() {
  ips, err := net.LookupIP("nonexistent.domain")
  if err != nil {
    if dnsErr, ok := err.(*net.DNSError); ok {
      fmt.Println("DNS error:", dnsErr.Err)
      fmt.Println("Name:", dnsErr.Name)
      fmt.Println("IsTimeout:", dnsErr.IsTimeout)
      fmt.Println("IsTemporary:", dnsErr.IsTemporary)
      fmt.Println("IsNotFound:", dnsErr.IsNotFound)
    } else {
      fmt.Println("Other error:", err)
    }
    return
  }
  fmt.Println("IPs:", ips)
}

Результат выполнения кода (зависит от DNS-сервера):

go"DNS error: no such host"
"Name: nonexistent.domain"
"IsTimeout: false"
"IsTemporary: false"
"IsNotFound: true"

В этом примере мы выполняем запрос для несуществующего домена. При возникновении ошибки мы приводим ее к типу net.DNSError и выводим все поля, чтобы понять причину.

Пример

Проверим, является ли ошибка временной, и выполним повторный запрос:

gopackage main

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

func main() {
  host := "example.com"
  for i := 0; i < 3; i++ {
    ips, err := net.LookupIP(host)
    if err != nil {
      if dnsErr, ok := err.(*net.DNSError); ok && dnsErr.IsTemporary {
        fmt.Printf("Temporary error, retrying (%d/3)...\n", i+1)
        time.Sleep(1 * time.Second)
        continue
      }
      fmt.Println("Fatal error:", err)
      return
    }
    fmt.Println("IPs:", ips)
    return
  }
  fmt.Println("Failed after retries")
}

Результат выполнения кода (в случае успешного разрешения):

go"IPs: [93.184.216.34 2606:2800:220:1:248:1893:25c8:1946]"

Здесь мы проверяем флаг IsTemporary и при его установке выполняем повторные попытки с задержкой. Если ошибка не временная, мы завершаем выполнение.

Смотрите также

  • функцию net.LookupHost,
    которая выполняет DNS-запрос для получения адресов хоста
  • функцию net.LookupIP,
    которая возвращает IP-адреса для указанного домена
  • тип net.OpError,
    представляющий общую ошибку сетевой операции
  • интерфейс net.Error,
    который определяет методы для временных ошибок