Тип net.OpError

Тип net.OpError реализует интерфейс error и используется для описания ошибок, которые происходят при выполнении сетевых операций, таких как соединение, чтение, запись или закрытие соединения. Он содержит полезную информацию для диагностики проблем: тип операции (Op), сеть (Net), адрес (Addr) и исходную ошибку (Err), которая может быть более детальной.

Структура типа

gotype OpError struct {
  Op  string
  Net string
  Addr Addr
  Err  error
}

Поле Op содержит название операции (например, "dial", "read", "write"), Net — сетевой протокол (например, "tcp", "udp"), Addr — сетевой адрес, а Err — вложенную ошибку с подробным описанием проблемы.

Пример 1: Обработка ошибки соединения

Попробуем установить соединение с несуществующим хостом и обработать ошибку типа net.OpError:

gopackage main

import (
  "fmt"
  "net"
)

func main() {
  conn, err := net.Dial("tcp", "nonexistent.example.com:80")
  if err != nil {
    if opErr, ok := err.(*net.OpError); ok {
      fmt.Printf("Operation: %s\n", opErr.Op)
      fmt.Printf("Network: %s\n", opErr.Net)
      fmt.Printf("Address: %s\n", opErr.Addr)
      fmt.Printf("Error: %v\n", opErr.Err)
    } else {
      fmt.Println("Other error:", err)
    }
    return
  }
  defer conn.Close()
  fmt.Println("Connection successful")
}

Результат выполнения кода (зависит от системы, но будет содержать информацию об ошибке):

go"Operation: dial"
"Network: tcp"
"Address: nonexistent.example.com:80"
"Error: dial tcp: lookup nonexistent.example.com: no such host"

Пример 2: Ошибка записи в закрытое соединение

Попробуем записать данные в закрытое соединение и перехватим ошибку:

gopackage main

import (
  "fmt"
  "net"
)

func main() {
  // Создаем локальное TCP-соединение
  ln, err := net.Listen("tcp", "127.0.0.1:0")
  if err != nil {
    fmt.Println("Listen error:", err)
    return
  }
  defer ln.Close()

  conn, err := net.Dial("tcp", ln.Addr().String())
  if err != nil {
    fmt.Println("Dial error:", err)
    return
  }
  defer conn.Close()

  // Закрываем соединение
  conn.Close()

  // Пытаемся записать данные
  _, err = conn.Write([]byte("test"))
  if err != nil {
    if opErr, ok := err.(*net.OpError); ok {
      fmt.Printf("Operation: %s\n", opErr.Op)
      fmt.Printf("Network: %s\n", opErr.Net)
      fmt.Printf("Address: %s\n", opErr.Addr)
      fmt.Printf("Error: %v\n", opErr.Err)
    } else {
      fmt.Println("Other error:", err)
    }
  }
}

Результат выполнения кода:

go"Operation: write"
"Network: tcp"
"Address: 127.0.0.1:xxxxx"
"Error: write tcp 127.0.0.1:xxxxx->127.0.0.1:yyyyy: use of closed network connection"

Пример 3: Проверка временной ошибки

Иногда ошибка может быть временной. Проверим, является ли ошибка временной с помощью метода Temporary:

gopackage main

import (
  "fmt"
  "net"
)

func main() {
  _, err := net.Dial("tcp", "invalid:80")
  if err != nil {
    if opErr, ok := err.(*net.OpError); ok {
      fmt.Printf("Is temporary: %t\n", opErr.Temporary())
      fmt.Printf("Is timeout: %t\n", opErr.Timeout())
    }
  }
}

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

go"Is temporary: false"
"Is timeout: false"

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

  • тип net.Error — базовый интерфейс для сетевых ошибок
  • тип net.AddrError — ошибка, связанная с некорректным адресом
  • тип net.DNSError — ошибка при разрешении DNS-имени
  • функцию net.Dial — установка сетевого соединения