Go net 包详解
概述
net 包提供了可移植的网络 I/O 接口,包括 TCP/IP、UDP、域名解析和 Unix 域套接字。虽然该包提供了对底层网络原语的访问,但大多数客户端只需要使用 Dial、Listen 和 Accept 函数以及相关的 Conn 和 Listener 接口提供的基本接口。crypto/tls 包使用相同的接口以及类似的 Dial 和 Listen 函数。
重要说明:
- ✓ 提供 TCP/IP、UDP、Unix 域套接字支持
- ✓ 支持域名解析(DNS)
- ✓ 提供 IPv4 和 IPv6 支持
- ✓ 支持上下文(Context)操作
- ✓ 支持 TCP keep-alive
- ✓ 支持多路径 TCP(MPTCP)
- ✓ Go 1.0+ 引入,持续增强
DNS 解析器说明:
- 纯 Go 解析器:直接向
/etc/resolv.conf中的 DNS 服务器发送请求 - cgo 解析器:调用 C 库函数(如 getaddrinfo)
- 默认选择:Unix 上优先使用纯 Go 解析器
- 强制指定:通过
GODEBUG=netdns=go或GODEBUG=netdns=cgo - 并发限制:cgo 解析器限制 500 个并发查询
包导入
import (
"net"
)
基本使用
1. TCP 客户端连接
package main
import (
"fmt"
"net"
)
func main() {
// 连接到服务器
conn, err := net.Dial("tcp", "golang.org:80")
if err != nil {
panic(err)
}
defer conn.Close()
// 发送数据
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
// 接收响应
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
fmt.Printf("Received: %s\n", string(buf[:n]))
}
2. TCP 服务器
package main
import (
"fmt"
"net"
)
func handleConnection(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
fmt.Printf("Received: %s\n", string(buf[:n]))
conn.Write([]byte("Hello!"))
}
func main() {
// 创建监听器
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
defer ln.Close()
fmt.Println("Server listening on :8080")
// 接受连接
for {
conn, err := ln.Accept()
if err != nil {
continue
}
go handleConnection(conn)
}
}
3. DNS 查询
package main
import (
"fmt"
"net"
)
func main() {
// 查询主机 IP
addrs, err := net.LookupHost("golang.org")
if err != nil {
panic(err)
}
fmt.Printf("IP addresses: %v\n", addrs)
// 查询 MX 记录
mxRecords, err := net.LookupMX("gmail.com")
if err != nil {
panic(err)
}
for _, mx := range mxRecords {
fmt.Printf("MX: %s (Pref: %d)\n", mx.Host, mx.Pref)
}
}
一、常量
IPv4 地址常量
定义:
var (
IPv4bcast = IPv4(255, 255, 255, 255) // IPv4 广播地址
IPv4allsys = IPv4(224, 0, 0, 1) // 所有系统多播
IPv4allrouter = IPv4(224, 0, 0, 2) // 所有路由器多播
IPv4zero = IPv4(0, 0, 0, 0) // IPv4 零地址
)
说明:
- IPv4bcast:IPv4 广播地址(255.255.255.255)
- IPv4allsys:所有系统多播地址(224.0.0.1)
- IPv4allrouter:所有路由器多播地址(224.0.0.2)
- IPv4zero:IPv4 零地址(0.0.0.0)
IPv6 地址常量
定义:
var (
IPv6zero = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
IPv6unspecified = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
IPv6loopback = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
IPv6linklocalallnodes = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
IPv6linklocalallrouters = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
)
说明:
- IPv6zero:IPv6 零地址
- IPv6unspecified:IPv6 未指定地址
- IPv6loopback:IPv6 环回地址(::1)
- IPv6linklocalallnodes:链路本地所有节点多播
- IPv6linklocalallrouters:链路本地所有路由器多播
Flags 常量
定义:
const (
FlagUp Flags = 1 << iota // 接口已启用
FlagBroadcast // 支持广播
FlagLoopback // 环回接口
FlagPointToPoint // 点对点接口
FlagMulticast // 支持多播
FlagRunning // 接口正在运行
)
说明:
- FlagUp:网络接口已启用
- FlagBroadcast:接口支持广播
- FlagLoopback:环回接口
- FlagPointToPoint:点对点接口
- FlagMulticast:接口支持多播
- FlagRunning:接口正在运行
二、变量
DefaultResolver
定义:
var DefaultResolver = &Resolver{}
说明:
- 功能:包级别的 Lookup 函数和没有指定 Resolver 的 Dialer 使用的解析器
- 用途:提供默认的 DNS 解析器
ErrClosed
定义:
var ErrClosed = errClosed
说明:
- 功能:在已关闭的网络连接上进行 I/O 操作时返回的错误
- 用途:使用
errors.Is(err, net.ErrClosed)检测
三、函数(按 a-z 排序)
Dial
定义:
func Dial(network, address string) (Conn, error)
说明:
- 功能:连接到指定网络上的地址
- 参数:
network- 网络类型(“tcp”、“tcp4”、“tcp6”、“udp”、“ip”、“unix” 等)address- 地址字符串
- 返回:
Conn- 连接接口error- 错误信息
- 用途:建立网络连接
支持的网络类型:
- TCP:
tcp、tcp4(仅 IPv4)、tcp6(仅 IPv6) - UDP:
udp、udp4、udp6 - IP:
ip、ip4、ip6(后跟协议号或名称) - Unix:
unix、unixgram、unixpacket
地址格式:
- TCP/UDP:
host:port(如"golang.org:80"、"192.0.2.1:80") - IPv6:
[host]:port(如"[2001:db8::1]:80") - IP:
host(如"192.0.2.1") - Unix:文件系统路径(如
"/var/run/docker.sock")
示例:
package main
import (
"fmt"
"net"
)
func main() {
// TCP 连接
conn, err := net.Dial("tcp", "golang.org:80")
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Println("Connected to golang.org")
// UDP 连接
udpConn, err := net.Dial("udp", "8.8.8.8:53")
if err != nil {
panic(err)
}
defer udpConn.Close()
fmt.Println("Connected to DNS server")
// IPv6 连接
conn6, err := net.Dial("tcp6", "[::1]:8080")
if err != nil {
fmt.Println("IPv6 not available")
} else {
defer conn6.Close()
fmt.Println("Connected via IPv6")
}
}
DialTimeout
定义:
func DialTimeout(network, address string, timeout time.Duration) (Conn, error)
说明:
- 功能:带超时的 Dial
- 参数:
network- 网络类型address- 地址timeout- 超时时间(包括名称解析)
- 返回:
Conn- 连接接口error- 错误信息
- 特点:超时时间分散到每个 IP 地址的拨号中
示例:
package main
import (
"fmt"
"net"
"time"
)
func main() {
// 5 秒超时
conn, err := net.DialTimeout("tcp", "golang.org:80", 5*time.Second)
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Println("Connected within 5 seconds")
}
InterfaceAddrs
定义:
func InterfaceAddrs() ([]Addr, error)
说明:
- 功能:返回系统单播接口地址列表
- 返回:
[]Addr- 地址列表error- 错误信息
- 用途:获取本地网络接口地址
示例:
package main
import (
"fmt"
"net"
)
func main() {
addrs, err := net.InterfaceAddrs()
if err != nil {
panic(err)
}
for _, addr := range addrs {
fmt.Printf("Address: %s\n", addr.String())
}
}
Interfaces
定义:
func Interfaces() ([]Interface, error)
说明:
- 功能:返回系统网络接口列表
- 返回:
[]Interface- 接口列表error- 错误信息
- 用途:枚举所有网络接口
示例:
package main
import (
"fmt"
"net"
)
func main() {
ifaces, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, iface := range ifaces {
fmt.Printf("Interface: %s, Index: %d, MTU: %d\n",
iface.Name, iface.Index, iface.MTU)
fmt.Printf(" Flags: %v\n", iface.Flags)
fmt.Printf(" HardwareAddr: %v\n", iface.HardwareAddr)
}
}
InterfaceByIndex
定义:
func InterfaceByIndex(index int) (*Interface, error)
说明:
- 功能:根据索引返回网络接口
- 参数:
index- 接口索引
- 返回:
*Interface- 接口指针error- 错误信息
InterfaceByName
定义:
func InterfaceByName(name string) (*Interface, error)
说明:
- 功能:根据名称返回网络接口
- 参数:
name- 接口名称(如 “eth0”)
- 返回:
*Interface- 接口指针error- 错误信息
JoinHostPort
定义:
func JoinHostPort(host, port string) string
说明:
- 功能:组合 host 和 port 为网络地址
- 参数:
host- 主机名或 IPport- 端口
- 返回:
host:port格式字符串 - 特点:IPv6 地址自动添加方括号
示例:
package main
import (
"fmt"
"net"
)
func main() {
// IPv4
addr1 := net.JoinHostPort("192.168.1.1", "8080")
fmt.Println(addr1) // 192.168.1.1:8080
// IPv6
addr2 := net.JoinHostPort("2001:db8::1", "8080")
fmt.Println(addr2) // [2001:db8::1]:8080
// 空 host
addr3 := net.JoinHostPort("", "8080")
fmt.Println(addr3) // :8080
}
Listen
定义:
func Listen(network, address string) (Listener, error)
说明:
- 功能:在本地网络地址上监听
- 参数:
network- 网络类型(“tcp”、“tcp4”、“tcp6”、“unix”、“unixpacket”)address- 地址
- 返回:
Listener- 监听器接口error- 错误信息
- 用途:创建 TCP 或 Unix 服务器
示例:
package main
import (
"fmt"
"net"
)
func main() {
// TCP 监听
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
defer ln.Close()
fmt.Printf("Listening on %s\n", ln.Addr())
// Unix 监听
unixLn, err := net.Listen("unix", "/tmp/test.sock")
if err != nil {
panic(err)
}
defer unixLn.Close()
}
ListenPacket
定义:
func ListenPacket(network, address string) (PacketConn, error)
说明:
- 功能:在本地网络地址上监听数据包
- 参数:
network- 网络类型(“udp”、“udp4”、“udp6”、“ip”、“ip4”、“ip6”、“unixgram”)address- 地址
- 返回:
PacketConn- 数据包连接接口error- 错误信息
- 用途:创建 UDP 或 IP 服务器
ListenTCP
定义:
func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error)
说明:
- 功能:监听 TCP 地址
- 参数:
network- TCP 网络类型laddr- 本地 TCP 地址
- 返回:
*TCPListener- TCP 监听器error- 错误信息
ListenUDP
定义:
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)
说明:
- 功能:监听 UDP 地址
- 参数:
network- UDP 网络类型laddr- 本地 UDP 地址
- 返回:
*UDPConn- UDP 连接error- 错误信息
ListenMulticastUDP
定义:
func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error)
说明:
- 功能:监听多播 UDP 地址
- 参数:
network- UDP 网络类型ifi- 网络接口(nil 表示系统分配)gaddr- 多播组地址
- 返回:
*UDPConn- UDP 连接error- 错误信息
ListenIP
定义:
func ListenIP(network string, laddr *IPAddr) (*IPConn, error)
说明:
- 功能:监听 IP 地址
- 参数:
network- IP 网络类型laddr- 本地 IP 地址
- 返回:
*IPConn- IP 连接error- 错误信息
ListenUnix
定义:
func ListenUnix(network string, laddr *UnixAddr) (*UnixListener, error)
说明:
- 功能:监听 Unix 域套接字
- 参数:
network- Unix 网络类型laddr- 本地 Unix 地址
- 返回:
*UnixListener- Unix 监听器error- 错误信息
ListenUnixgram
定义:
func ListenUnixgram(network string, laddr *UnixAddr) (*UnixConn, error)
说明:
- 功能:监听 Unixgram 套接字
- 参数:
network- 必须为 “unixgram”laddr- 本地 Unix 地址
- 返回:
*UnixConn- Unix 连接error- 错误信息
LookupAddr
定义:
func LookupAddr(addr string) (names []string, err error)
说明:
- 功能:反向 DNS 查询(IP 到域名)
- 参数:
addr- IP 地址
- 返回:
[]string- 域名列表error- 错误信息
- 用途:根据 IP 查找域名
示例:
package main
import (
"fmt"
"net"
)
func main() {
names, err := net.LookupAddr("8.8.8.8")
if err != nil {
panic(err)
}
fmt.Printf("Names for 8.8.8.8: %v\n", names)
}
LookupCNAME
定义:
func LookupCNAME(host string) (cname string, err error)
说明:
- 功能:查询主机的规范名称(CNAME)
- 参数:
host- 主机名
- 返回:
string- 规范名称error- 错误信息
- 用途:获取 CNAME 记录
LookupHost
定义:
func LookupHost(host string) (addrs []string, err error)
说明:
- 功能:查询主机的 IP 地址
- 参数:
host- 主机名
- 返回:
[]string- IP 地址列表error- 错误信息
- 用途:DNS 正向查询
示例:
package main
import (
"fmt"
"net"
)
func main() {
addrs, err := net.LookupHost("golang.org")
if err != nil {
panic(err)
}
fmt.Printf("IP addresses: %v\n", addrs)
}
LookupIP
定义:
func LookupIP(host string) ([]IP, error)
说明:
- 功能:查询主机的 IP 地址(返回 IP 类型)
- 参数:
host- 主机名
- 返回:
[]IP- IP 地址列表error- 错误信息
LookupMX
定义:
func LookupMX(name string) ([]*MX, error)
说明:
- 功能:查询 DNS MX 记录(邮件交换记录)
- 参数:
name- 域名
- 返回:
[]*MX- MX 记录列表(按优先级排序)error- 错误信息
示例:
package main
import (
"fmt"
"net"
)
func main() {
mxRecords, err := net.LookupMX("gmail.com")
if err != nil {
panic(err)
}
for _, mx := range mxRecords {
fmt.Printf("Mail server: %s (Priority: %d)\n", mx.Host, mx.Pref)
}
}
LookupNS
定义:
func LookupNS(name string) ([]*NS, error)
说明:
- 功能:查询 DNS NS 记录(名称服务器记录)
- 参数:
name- 域名
- 返回:
[]*NS- NS 记录列表error- 错误信息
LookupPort
定义:
func LookupPort(network, service string) (port int, err error)
说明:
- 功能:查询服务对应的端口号
- 参数:
network- 网络类型service- 服务名称(如 “http”、“ssh”)
- 返回:
int- 端口号error- 错误信息
示例:
package main
import (
"fmt"
"net"
)
func main() {
port, err := net.LookupPort("tcp", "http")
if err != nil {
panic(err)
}
fmt.Printf("HTTP port: %d\n", port) // 80
}
LookupSRV
定义:
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error)
说明:
- 功能:查询 DNS SRV 记录(服务记录)
- 参数:
service- 服务名称proto- 协议(“tcp” 或 “udp”)name- 域名
- 返回:
string- 规范名称[]*SRV- SRV 记录列表error- 错误信息
LookupTXT
定义:
func LookupTXT(name string) ([]string, error)
说明:
- 功能:查询 DNS TXT 记录
- 参数:
name- 域名
- 返回:
[]string- TXT 记录列表error- 错误信息
示例:
package main
import (
"fmt"
"net"
)
func main() {
txtRecords, err := net.LookupTXT("google.com")
if err != nil {
panic(err)
}
for _, txt := range txtRecords {
fmt.Printf("TXT: %s\n", txt)
}
}
ParseCIDR
定义:
func ParseCIDR(s string) (IP, *IPNet, error)
说明:
- 功能:解析 CIDR 表示法(如 “192.0.2.0/24”)
- 参数:
s- CIDR 字符串
- 返回:
IP- IP 地址*IPNet- 网络error- 错误信息
示例:
package main
import (
"fmt"
"net"
)
func main() {
ip, ipNet, err := net.ParseCIDR("192.168.1.0/24")
if err != nil {
panic(err)
}
fmt.Printf("IP: %s\n", ip) // 192.168.1.0
fmt.Printf("Network: %s\n", ipNet) // 192.168.1.0/24
fmt.Printf("Contains 192.168.1.100: %v\n", ipNet.Contains(net.ParseIP("192.168.1.100")))
}
ParseIP
定义:
func ParseIP(s string) IP
说明:
- 功能:解析 IP 地址字符串
- 参数:
s- IP 地址字符串
- 返回:IP 地址(无效时返回 nil)
- 支持格式:IPv4、IPv6、IPv4 映射的 IPv6
示例:
package main
import (
"fmt"
"net"
)
func main() {
ipv4 := net.ParseIP("192.168.1.1")
fmt.Printf("IPv4: %s\n", ipv4)
ipv6 := net.ParseIP("2001:db8::1")
fmt.Printf("IPv6: %s\n", ipv6)
invalid := net.ParseIP("invalid")
fmt.Printf("Invalid: %v\n", invalid) // <nil>
}
ParseMAC
定义:
func ParseMAC(s string) (hw HardwareAddr, err error)
说明:
- 功能:解析 MAC 地址字符串
- 参数:
s- MAC 地址字符串
- 返回:
HardwareAddr- 硬件地址error- 错误信息
- 支持格式:
00:00:5e:00:53:0100-00-5e-00-53-010000.5e00.530100005e005301
示例:
package main
import (
"fmt"
"net"
)
func main() {
mac, err := net.ParseMAC("00:00:5e:00:53:01")
if err != nil {
panic(err)
}
fmt.Printf("MAC: %s\n", mac)
}
Pipe
定义:
func Pipe() (Conn, Conn)
说明:
- 功能:创建同步的、内存中的全双工网络连接
- 返回:两个 Conn 接口
- 特点:
- 无内部缓冲
- 一端读取直接匹配另一端写入
- 用于测试
示例:
package main
import (
"fmt"
"net"
)
func main() {
c1, c2 := net.Pipe()
defer c1.Close()
defer c2.Close()
// 协程写入
go c1.Write([]byte("Hello"))
// 主协程读取
buf := make([]byte, 10)
n, _ := c2.Read(buf)
fmt.Printf("Received: %s\n", string(buf[:n]))
}
ResolveIPAddr
定义:
func ResolveIPAddr(network, address string) (*IPAddr, error)
说明:
- 功能:解析 IP 地址
- 参数:
network- IP 网络类型address- 地址字符串
- 返回:
*IPAddr- IP 地址error- 错误信息
ResolveTCPAddr
定义:
func ResolveTCPAddr(network, address string) (*TCPAddr, error)
说明:
- 功能:解析 TCP 地址
- 参数:
network- TCP 网络类型address- 地址字符串
- 返回:
*TCPAddr- TCP 地址error- 错误信息
示例:
package main
import (
"fmt"
"net"
)
func main() {
addr, err := net.ResolveTCPAddr("tcp", "localhost:8080")
if err != nil {
panic(err)
}
fmt.Printf("TCP Address: %s\n", addr)
fmt.Printf("IP: %s, Port: %d\n", addr.IP, addr.Port)
}
ResolveUDPAddr
定义:
func ResolveUDPAddr(network, address string) (*UDPAddr, error)
说明:
- 功能:解析 UDP 地址
- 参数:
network- UDP 网络类型address- 地址字符串
- 返回:
*UDPAddr- UDP 地址error- 错误信息
ResolveUnixAddr
定义:
func ResolveUnixAddr(network, address string) (*UnixAddr, error)
说明:
- 功能:解析 Unix 域套接字地址
- 参数:
network- Unix 网络类型address- 地址字符串
- 返回:
*UnixAddr- Unix 地址error- 错误信息
SplitHostPort
定义:
func SplitHostPort(hostport string) (host, port string, err error)
说明:
- 功能:分割网络地址为主机和端口
- 参数:
hostport- 网络地址(如 “host:port”)
- 返回:
host- 主机(可能包含区域)port- 端口error- 错误信息
- 特点:正确处理 IPv6 地址的方括号
示例:
package main
import (
"fmt"
"net"
)
func main() {
// IPv4
host, port, err := net.SplitHostPort("192.168.1.1:8080")
if err != nil {
panic(err)
}
fmt.Printf("Host: %s, Port: %s\n", host, port)
// IPv6
host, port, err = net.SplitHostPort("[2001:db8::1]:8080")
if err != nil {
panic(err)
}
fmt.Printf("Host: %s, Port: %s\n", host, port)
}
TCPAddrFromAddrPort
定义:
func TCPAddrFromAddrPort(addr netip.AddrPort) *TCPAddr
说明:
- 功能:从 netip.AddrPort 转换为 TCPAddr
- 参数:
addr- netip.AddrPort
- 返回:
*TCPAddr - 版本:Go 1.20+
UDPAddrFromAddrPort
定义:
func UDPAddrFromAddrPort(addr netip.AddrPort) *UDPAddr
说明:
- 功能:从 netip.AddrPort 转换为 UDPAddr
- 参数:
addr- netip.AddrPort
- 返回:
*UDPAddr - 版本:Go 1.20+
IPv4
定义:
func IPv4(a, b, c, d byte) IP
说明:
- 功能:创建 IPv4 地址(返回 16 字节形式)
- 参数:4 个字节的 IPv4 地址
- 返回:16 字节的 IP 地址
示例:
package main
import (
"fmt"
"net"
)
func main() {
ip := net.IPv4(8, 8, 8, 8)
fmt.Printf("Google DNS: %s\n", ip) // 8.8.8.8
}
FileConn
定义:
func FileConn(f *os.File) (Conn, error)
说明:
- 功能:从文件创建网络连接
- 参数:
f- 打开的文件
- 返回:
Conn- 连接接口error- 错误信息
FileListener
定义:
func FileListener(f *os.File) (Listener, error)
说明:
- 功能:从文件创建网络监听器
- 参数:
f- 打开的文件
- 返回:
Listener- 监听器接口error- 错误信息
FilePacketConn
定义:
func FilePacketConn(f *os.File) (PacketConn, error)
说明:
- 功能:从文件创建数据包连接
- 参数:
f- 打开的文件
- 返回:
PacketConn- 数据包连接接口error- 错误信息
(由于 net 包内容非常多,这里继续展示主要类型和方法)
四、类型(按 a-z 排序)
Addr
定义:
type Addr interface {
Network() string // 网络名称
String() string // 字符串表示
}
说明:
- 功能:表示网络端点地址
- 实现者:
*TCPAddr、*UDPAddr、*IPAddr、*UnixAddr、*IPNet
AddrError
定义:
type AddrError struct {
Err string
Addr string
}
说明:
- 功能:地址相关错误
- 方法:
Error()- 错误消息Temporary()- 是否为临时错误Timeout()- 是否为超时错误
Buffers
定义:
type Buffers [][]byte
说明:
- 功能:包含零个或多个字节运行
- 优化:在某些系统上优化为批量写入(如 writev)
- 方法:
Read(p []byte)- 读取WriteTo(w io.Writer)- 写入到
Conn
定义:
type Conn interface {
Read(b []byte) (int, error)
Write(b []byte) (int, error)
Close() error
LocalAddr() Addr
RemoteAddr() Addr
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
}
说明:
- 功能:通用流式网络连接
- 实现者:
*TCPConn、*UDPConn、*IPConn、*UnixConn - 特点:支持多个 goroutine 并发调用
Dialer
定义:
type Dialer struct {
Timeout time.Duration
Deadline time.Time
LocalAddr Addr
DualStack bool
FallbackDelay time.Duration
KeepAlive time.Duration
Resolver *Resolver
Control func(network, address string, c syscall.RawConn) error
// ...
}
说明:
- 功能:包含连接选项
- 方法:
Dial(network, address)- 拨号DialContext(ctx, network, address)- 带上下文的拨号DialTCP/DialUDP/DialIP/DialUnix- 特定网络类型拨号SetMultipathTCP(use)- 设置 MPTCP
示例:
package main
import (
"fmt"
"net"
"time"
)
func main() {
dialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}
conn, err := dialer.Dial("tcp", "golang.org:80")
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Println("Connected with custom dialer")
}
DNSError
定义:
type DNSError struct {
Err string
Name string
Server string
IsTimeout bool
IsTemporary bool
}
说明:
- 功能:DNS 查询错误
- 方法:
Error()- 错误消息Temporary()- 是否临时错误Timeout()- 是否超时Unwrap()- 解包错误
DNSConfigError
定义:
type DNSConfigError struct {
Err error
}
说明:
- 功能:DNS 配置错误(已废弃,保留兼容性)
Error
定义:
type Error interface {
error
Temporary() bool
Timeout() bool
}
说明:
- 功能:网络错误接口
Flags
定义:
type Flags int
说明:
- 功能:网络接口标志
- 方法:
String()- 字符串表示
HardwareAddr
定义:
type HardwareAddr []byte
说明:
- 功能:物理硬件地址(MAC 地址)
- 方法:
String()- 字符串表示- 配合
ParseMAC使用
IP
定义:
type IP []byte
说明:
- 功能:IP 地址(4 字节 IPv4 或 16 字节 IPv6)
- 方法(丰富):
String()- 字符串表示To4()- 转换为 IPv4To16()- 转换为 IPv6Equal(x)- 比较IsLoopback()- 是否环回IsMulticast()- 是否多播IsPrivate()- 是否私有地址IsGlobalUnicast()- 是否全局单播Mask(mask)- 应用掩码DefaultMask()- 默认掩码MarshalText()- 文本编码UnmarshalText()- 文本解码AppendText()- 文本追加
示例:
package main
import (
"fmt"
"net"
)
func main() {
ip := net.ParseIP("192.168.1.1")
fmt.Printf("String: %s\n", ip.String())
fmt.Printf("To4: %s\n", ip.To4())
fmt.Printf("IsPrivate: %v\n", ip.IsPrivate())
fmt.Printf("IsLoopback: %v\n", ip.IsLoopback())
mask := net.CIDRMask(24, 32)
fmt.Printf("Masked: %s\n", ip.Mask(mask))
}
IPAddr
定义:
type IPAddr struct {
IP IP
Zone string // IPv6 区域
}
说明:
- 功能:IP 端点地址
- 方法:
Network()- 返回 “ip”String()- 字符串表示
IPConn
定义:
type IPConn struct {
// 未导出字段
}
说明:
- 功能:IP 网络连接,实现 Conn 和 PacketConn
- 方法:
Read/Write- 读写ReadFrom/WriteTo- 带地址的读写ReadFromIP/WriteToIP- 带 IPAddr 的读写ReadMsgIP/WriteMsgIP- 带控制信息的读写LocalAddr/RemoteAddr- 本地/远程地址SetDeadline/SetReadDeadline/SetWriteDeadline- 设置截止时间SetReadBuffer/SetWriteBuffer- 设置缓冲区大小Close- 关闭File- 获取底层文件SyscallConn- 获取系统调用连接
IPMask
定义:
type IPMask []byte
说明:
- 功能:IP 地址掩码
- 方法:
Size()- 返回 1 的位数和总位数String()- 十六进制字符串
IPNet
定义:
type IPNet struct {
IP IP // 网络地址
Mask IPMask // 子网掩码
}
说明:
- 功能:IP 网络
- 方法:
Contains(ip)- 是否包含 IPString()- CIDR 表示法Network()- 返回 “ip+net”
示例:
package main
import (
"fmt"
"net"
)
func main() {
_, ipNet, _ := net.ParseCIDR("192.168.1.0/24")
fmt.Printf("Network: %s\n", ipNet)
fmt.Printf("Contains 192.168.1.100: %v\n", ipNet.Contains(net.ParseIP("192.168.1.100")))
fmt.Printf("Contains 192.168.2.1: %v\n", ipNet.Contains(net.ParseIP("192.168.2.1")))
}
Interface
定义:
type Interface struct {
Index int // 接口索引
MTU int // 最大传输单元
Name string // 接口名称
HardwareAddr HardwareAddr // MAC 地址
Flags Flags // 标志
}
说明:
- 功能:网络接口映射
- 方法:
Addrs()- 单播地址列表MulticastAddrs()- 多播地址列表
InvalidAddrError
定义:
type InvalidAddrError string
说明:
- 功能:无效地址错误
KeepAliveConfig
定义:
type KeepAliveConfig struct {
Enable bool
Idle time.Duration
Interval time.Duration
Count int
}
说明:
- 功能:TCP keep-alive 配置
- 字段:
Enable- 是否启用Idle- 空闲时间Interval- 探测间隔Count- 探测次数
ListenConfig
定义:
type ListenConfig struct {
Control func(network, address string, c syscall.RawConn) error
KeepAlive time.Duration
InitialPacketSize func(network, address string) int
// ...
}
说明:
- 功能:监听配置
- 方法:
Listen(ctx, network, address)- 监听ListenPacket(ctx, network, address)- 监听数据包SetMultipathTCP(use)- 设置 MPTCP
Listener
定义:
type Listener interface {
Accept() (Conn, error)
Close() error
Addr() Addr
}
说明:
- 功能:通用网络监听器
- 实现者:
*TCPListener、*UnixListener
MX
定义:
type MX struct {
Host string
Pref uint16
}
说明:
- 功能:DNS MX 记录
- 字段:
Host- 邮件服务器主机名Pref- 优先级(越小优先级越高)
NS
定义:
type NS struct {
Host string
}
说明:
- 功能:DNS NS 记录
OpError
定义:
type OpError struct {
Op string
Net string
Source Addr
Addr Addr
Err error
}
说明:
- 功能:网络操作错误
- 方法:
Error()- 错误消息Temporary()- 是否临时错误Timeout()- 是否超时Unwrap()- 解包错误
PacketConn
定义:
type PacketConn interface {
ReadFrom(p []byte) (n int, addr Addr, err error)
WriteTo(p []byte, addr Addr) (n int, err error)
Close() error
LocalAddr() Addr
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
}
说明:
- 功能:通用数据包连接
- 实现者:
*UDPConn、*IPConn、*UnixConn
ParseError
定义:
type ParseError struct {
Type string
Text string
}
说明:
- 功能:网络地址解析错误
Resolver
定义:
type Resolver struct {
PreferGo bool
StrictErrors bool
Dial func(ctx context.Context, network, address string) (Conn, error)
}
说明:
- 功能:DNS 解析器
- 方法:
LookupHost(ctx, host)- 查询主机 IPLookupIP(ctx, network, host)- 查询 IPLookupAddr(ctx, addr)- 反向查询LookupCNAME(ctx, host)- 查询 CNAMELookupMX(ctx, name)- 查询 MXLookupNS(ctx, name)- 查询 NSLookupSRV(ctx, service, proto, name)- 查询 SRVLookupTXT(ctx, name)- 查询 TXTLookupPort(ctx, network, service)- 查询端口LookupNetIP(ctx, network, host)- 查询 netip.AddrLookupIPAddr(ctx, host)- 查询 IPAddr
示例:
package main
import (
"context"
"fmt"
"net"
)
func main() {
resolver := &net.Resolver{
PreferGo: true,
}
addrs, err := resolver.LookupHost(context.Background(), "golang.org")
if err != nil {
panic(err)
}
fmt.Printf("IP addresses: %v\n", addrs)
}
SRV
定义:
type SRV struct {
Target string
Port uint16
Priority uint16
Weight uint16
}
说明:
- 功能:DNS SRV 记录
- 字段:
Target- 目标主机Port- 端口Priority- 优先级Weight- 权重
TCPAddr
定义:
type TCPAddr struct {
IP IP
Port int
Zone string // IPv6 区域
}
说明:
- 功能:TCP 端点地址
- 方法:
Network()- 返回 “tcp”String()- 字符串表示AddrPort()- 返回 netip.AddrPort(Go 1.20+)
TCPConn
定义:
type TCPConn struct {
// 未导出字段
}
说明:
- 功能:TCP 连接,实现 Conn
- 方法(除 Conn 方法外):
CloseRead()- 关闭读端CloseWrite()- 关闭写端SetNoDelay(noDelay)- 设置 TCP_NODELAYSetKeepAlive(keepalive)- 设置 keep-aliveSetKeepAlivePeriod(d)- 设置 keep-alive 周期SetKeepAliveConfig(config)- 设置 keep-alive 配置SetLinger(sec)- 设置 lingerMultipathTCP()- 检查是否使用 MPTCPReadFrom(r)- 从 reader 读取并写入WriteTo(w)- 读取并写入 writerFile()- 获取底层文件SyscallConn()- 获取系统调用连接
TCPListener
定义:
type TCPListener struct {
// 未导出字段
}
说明:
- 功能:TCP 监听器
- 方法:
Accept()- 接受连接AcceptTCP()- 接受 TCP 连接Close()- 关闭Addr()- 监听地址SetDeadline(t)- 设置截止时间File()- 获取底层文件SyscallConn()- 获取系统调用连接
UDPAddr
定义:
type UDPAddr struct {
IP IP
Port int
Zone string // IPv6 区域
}
说明:
- 功能:UDP 端点地址
- 方法:
Network()- 返回 “udp”String()- 字符串表示AddrPort()- 返回 netip.AddrPort(Go 1.20+)
UDPConn
定义:
type UDPConn struct {
// 未导出字段
}
说明:
- 功能:UDP 连接,实现 Conn 和 PacketConn
- 方法(除 Conn/PacketConn 方法外):
ReadFromUDP(b)- 从 UDP 读取WriteToUDP(b, addr)- 写入 UDPReadFromUDPAddrPort(b)- 从 UDP 读取(返回 AddrPort)WriteToUDPAddrPort(b, addr)- 写入 UDP(使用 AddrPort)ReadMsgUDP(b, oob)- 读取 UDP 消息WriteMsgUDP(b, oob, addr)- 写入 UDP 消息ReadMsgUDPAddrPort(b, oob)- 读取 UDP 消息(AddrPort)WriteMsgUDPAddrPort(b, oob, addr)- 写入 UDP 消息(AddrPort)File()- 获取底层文件SyscallConn()- 获取系统调用连接
UnixAddr
定义:
type UnixAddr struct {
Net string
Name string
}
说明:
- 功能:Unix 域套接字地址
- 方法:
Network()- 返回网络类型String()- 字符串表示
UnixConn
定义:
type UnixConn struct {
// 未导出字段
}
说明:
- 功能:Unix 域套接字连接
- 方法:
CloseRead()- 关闭读端CloseWrite()- 关闭写端ReadFromUnix(b)- 从 Unix 读取WriteToUnix(b, addr)- 写入 UnixReadMsgUnix(b, oob)- 读取 Unix 消息WriteMsgUnix(b, oob, addr)- 写入 Unix 消息- 其他类似 TCPConn 的方法
UnixListener
定义:
type UnixListener struct {
// 未导出字段
}
说明:
- 功能:Unix 域套接字监听器
- 方法:
Accept()- 接受连接AcceptUnix()- 接受 Unix 连接Close()- 关闭Addr()- 监听地址SetDeadline(t)- 设置截止时间SetUnlinkOnClose(unlink)- 设置关闭时是否删除 socket 文件File()- 获取底层文件SyscallConn()- 获取系统调用连接
UnknownNetworkError
定义:
type UnknownNetworkError string
说明:
- 功能:未知网络类型错误
五、典型示例
示例 1:HTTP 客户端(原始 TCP)
package main
import (
"bufio"
"fmt"
"net"
)
func main() {
// 连接服务器
conn, err := net.Dial("tcp", "httpbin.org:80")
if err != nil {
panic(err)
}
defer conn.Close()
// 发送 HTTP 请求
request := "GET / HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n"
_, err = fmt.Fprint(conn, request)
if err != nil {
panic(err)
}
// 读取响应
reader := bufio.NewReader(conn)
status, _ := reader.ReadString('\n')
fmt.Printf("Status: %s", status)
// 读取头部
for {
line, _ := reader.ReadString('\n')
fmt.Printf("%s", line)
if line == "\r\n" {
break
}
}
}
示例 2:并发 TCP 服务器
package main
import (
"bufio"
"fmt"
"net"
"strings"
)
func handleConn(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
response := strings.ToUpper(strings.TrimSpace(line))
conn.Write([]byte(response + "\n"))
}
}
func main() {
ln, err := net.Listen("tcp", ":12345")
if err != nil {
panic(err)
}
defer ln.Close()
fmt.Println("Echo server listening on :12345")
for {
conn, err := ln.Accept()
if err != nil {
continue
}
go handleConn(conn)
}
}
示例 3:UDP 客户端/服务器
package main
import (
"fmt"
"net"
)
func main() {
// 服务器
go func() {
addr, _ := net.ResolveUDPAddr("udp", ":12346")
conn, _ := net.ListenUDP("udp", addr)
defer conn.Close()
buf := make([]byte, 1024)
n, clientAddr, _ := conn.ReadFromUDP(buf)
fmt.Printf("Server received: %s from %s\n", string(buf[:n]), clientAddr)
conn.WriteToUDP([]byte("Hello back!"), clientAddr)
}()
// 客户端
addr, _ := net.ResolveUDPAddr("udp", "localhost:12346")
conn, _ := net.DialUDP("udp", nil, addr)
defer conn.Close()
conn.Write([]byte("Hello server!"))
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
fmt.Printf("Client received: %s\n", string(buf[:n]))
}
示例 4:网络接口信息
package main
import (
"fmt"
"net"
)
func main() {
ifaces, _ := net.Interfaces()
for _, iface := range ifaces {
fmt.Printf("\n=== %s ===\n", iface.Name)
fmt.Printf("Index: %d\n", iface.Index)
fmt.Printf("MTU: %d\n", iface.MTU)
fmt.Printf("Flags: %v\n", iface.Flags)
fmt.Printf("Hardware Address: %s\n", iface.HardwareAddr)
addrs, _ := iface.Addrs()
fmt.Println("Addresses:")
for _, addr := range addrs {
fmt.Printf(" %s\n", addr)
}
}
}
示例 5:DNS 查询工具
package main
import (
"context"
"fmt"
"net"
"time"
)
func main() {
resolver := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: 5 * time.Second,
}
return d.DialContext(ctx, network, "8.8.8.8:53")
},
}
host := "golang.org"
// A 记录
addrs, _ := resolver.LookupHost(context.Background(), host)
fmt.Printf("A records: %v\n", addrs)
// MX 记录
mxRecords, _ := resolver.LookupMX(context.Background(), host)
fmt.Printf("MX records: %v\n", mxRecords)
// TXT 记录
txtRecords, _ := resolver.LookupTXT(context.Background(), host)
fmt.Printf("TXT records: %v\n", txtRecords)
// CNAME
cname, _ := resolver.LookupCNAME(context.Background(), host)
fmt.Printf("CNAME: %s\n", cname)
}
示例 6:TCP Keep-Alive
package main
import (
"fmt"
"net"
"time"
)
func main() {
dialer := &net.Dialer{
KeepAlive: 30 * time.Second,
}
conn, err := dialer.Dial("tcp", "golang.org:80")
if err != nil {
panic(err)
}
defer conn.Close()
tcpConn := conn.(*net.TCPConn)
// 设置 keep-alive
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
// 设置 keep-alive 配置
config := net.KeepAliveConfig{
Enable: true,
Idle: 60 * time.Second,
Interval: 10 * time.Second,
Count: 3,
}
tcpConn.SetKeepAliveConfig(config)
fmt.Println("TCP keep-alive configured")
}
示例 7:Unix 域套接字
package main
import (
"fmt"
"net"
"os"
)
func main() {
socketPath := "/tmp/test.sock"
os.Remove(socketPath) // 清理旧 socket
// 服务器
go func() {
addr, _ := net.ResolveUnixAddr("unix", socketPath)
ln, _ := net.ListenUnix("unix", addr)
defer ln.Close()
conn, _ := ln.AcceptUnix()
defer conn.Close()
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
fmt.Printf("Server received: %s\n", string(buf[:n]))
}()
// 客户端
addr, _ := net.ResolveUnixAddr("unix", socketPath)
conn, _ := net.DialUnix("unix", nil, addr)
defer conn.Close()
conn.Write([]byte("Hello via Unix socket!"))
// 等待服务器处理
time.Sleep(100 * time.Millisecond)
}
示例 8:IP 网络操作
package main
import (
"fmt"
"net"
)
func main() {
// 解析 CIDR
ip, ipNet, _ := net.ParseCIDR("192.168.1.0/24")
fmt.Printf("Network: %s\n", ipNet)
// 检查 IP 是否在网段内
testIPs := []string{
"192.168.1.1",
"192.168.1.254",
"192.168.2.1",
}
for _, ipStr := range testIPs {
ip := net.ParseIP(ipStr)
if ipNet.Contains(ip) {
fmt.Printf("%s is in %s\n", ipStr, ipNet)
} else {
fmt.Printf("%s is NOT in %s\n", ipStr, ipNet)
}
}
// IP 地址判断
ips := []net.IP{
net.ParseIP("127.0.0.1"),
net.ParseIP("192.168.1.1"),
net.ParseIP("8.8.8.8"),
net.ParseIP("::1"),
}
for _, ip := range ips {
fmt.Printf("\n%s:\n", ip)
fmt.Printf(" IsLoopback: %v\n", ip.IsLoopback())
fmt.Printf(" IsPrivate: %v\n", ip.IsPrivate())
fmt.Printf(" IsMulticast: %v\n", ip.IsMulticast())
fmt.Printf(" IsGlobalUnicast: %v\n", ip.IsGlobalUnicast())
}
}
六、最佳实践
1. 使用 Dialer 控制连接
// ✓ 正确:使用 Dialer 设置超时和 keep-alive
dialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}
conn, err := dialer.Dial("tcp", "example.com:80")
// ✗ 错误:没有超时控制
conn, err := net.Dial("tcp", "example.com:80")
2. 正确处理连接关闭
// ✓ 正确:使用 defer 确保关闭
conn, err := net.Dial("tcp", "example.com:80")
if err != nil {
return err
}
defer conn.Close()
// ✗ 错误:忘记关闭
conn, _ := net.Dial("tcp", "example.com:80")
// 连接未关闭,资源泄漏
3. 并发处理连接
// ✓ 正确:每个连接使用 goroutine
for {
conn, err := ln.Accept()
if err != nil {
continue
}
go handleConnection(conn)
}
// ✗ 错误:串行处理
for {
conn, err := ln.Accept()
handleConnection(conn) // 阻塞,无法接受新连接
}
4. 使用 Context 控制 DNS 查询
// ✓ 正确:使用 Context 设置超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resolver := &net.Resolver{}
addrs, err := resolver.LookupHost(ctx, "example.com")
// ✗ 错误:没有超时控制
addrs, err := net.LookupHost("example.com")
5. 错误处理
// ✓ 正确:检查错误类型
if err != nil {
if opErr, ok := err.(*net.OpError); ok {
if opErr.Timeout() {
// 处理超时
}
if errors.Is(err, net.ErrClosed) {
// 处理连接已关闭
}
}
}
// ✗ 错误:忽略错误
conn.Write(data) // 不检查错误
6. 设置读写超时
// ✓ 正确:设置超时防止阻塞
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
// ✗ 错误:没有超时
// 可能永久阻塞
7. 使用 ListenConfig
// ✓ 正确:使用 ListenConfig 配置监听器
lc := &net.ListenConfig{
KeepAlive: 30 * time.Second,
}
ln, err := lc.Listen(context.Background(), "tcp", ":8080")
// ✗ 错误:没有配置
ln, err := net.Listen("tcp", ":8080")
七、与其他包配合
1. 与 context 配合
import (
"context"
"net"
"time"
)
func dialWithContext() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
dialer := &net.Dialer{}
conn, err := dialer.DialContext(ctx, "tcp", "example.com:80")
if err != nil {
// 处理错误(可能是超时)
}
defer conn.Close()
}
2. 与 crypto/tls 配合
import (
"crypto/tls"
"net"
)
func dialTLS() {
// 先建立 TCP 连接
conn, err := net.Dial("tcp", "example.com:443")
if err != nil {
panic(err)
}
defer conn.Close()
// 升级为 TLS
tlsConn := tls.Client(conn, &tls.Config{
ServerName: "example.com",
})
err = tlsConn.Handshake()
}
3. 与 bufio 配合
import (
"bufio"
"net"
)
func bufferedIO() {
conn, _ := net.Dial("tcp", "example.com:80")
defer conn.Close()
// 缓冲读取
reader := bufio.NewReader(conn)
line, _ := reader.ReadString('\n')
// 缓冲写入
writer := bufio.NewWriter(conn)
writer.WriteString("Hello\n")
writer.Flush()
}
4. 与 io 配合
import (
"io"
"net"
)
func copyData() {
conn, _ := net.Dial("tcp", "example.com:80")
defer conn.Close()
// 流式复制
go io.Copy(conn, os.Stdin)
io.Copy(os.Stdout, conn)
}
八、快速参考
函数速查
| 函数 | 功能 | 返回 |
|---|---|---|
Dial(network, address) | 建立连接 | Conn, error |
DialTimeout(network, address, timeout) | 带超时拨号 | Conn, error |
Listen(network, address) | TCP/Unix 监听 | Listener, error |
ListenPacket(network, address) | UDP/IP 监听 | PacketConn, error |
LookupHost(host) | DNS 查询 | []string, error |
LookupAddr(addr) | 反向 DNS | []string, error |
ParseIP(s) | 解析 IP | IP |
ParseCIDR(s) | 解析 CIDR | IP, *IPNet, error |
ParseMAC(s) | 解析 MAC | HardwareAddr, error |
SplitHostPort(hostport) | 分割地址 | host, port, error |
JoinHostPort(host, port) | 组合地址 | string |
类型速查
| 类型 | 功能 |
|---|---|
Conn | 流式连接接口 |
Listener | 监听器接口 |
PacketConn | 数据包连接接口 |
Dialer | 拨号器配置 |
Resolver | DNS 解析器 |
IP | IP 地址 |
TCPAddr/UDPAddr/IPAddr/UnixAddr | 各种地址类型 |
TCPConn/UDPConn/IPConn/UnixConn | 各种连接类型 |
TCPListener/UnixListener | 各种监听器类型 |
网络类型
| 网络 | 说明 |
|---|---|
tcp | TCP(IPv4+IPv6) |
tcp4 | 仅 TCP IPv4 |
tcp6 | 仅 TCP IPv6 |
udp | UDP(IPv4+IPv6) |
udp4 | 仅 UDP IPv4 |
udp6 | 仅 UDP IPv6 |
ip:proto | 原始 IP |
unix | Unix 流套接字 |
unixgram | Unix 数据报套接字 |
unixpacket | Unix 包套接字 |
九、注意事项
1. IPv6 地址格式
// ✓ 正确:IPv6 地址需要方括号
addr := "[2001:db8::1]:8080"
conn, _ := net.Dial("tcp", addr)
// ✗ 错误:缺少方括号
addr := "2001:db8::1:8080" // 解析错误
2. 端口 0 的含义
// 端口 0 表示系统自动选择
ln, _ := net.Listen("tcp", ":0")
fmt.Printf("Chosen port: %s\n", ln.Addr()) // 随机端口
3. 空 host 的含义
// 空 host 或 "0.0.0.0" 表示监听所有接口
ln, _ := net.Listen("tcp", ":8080") // 所有 IPv4
ln, _ := net.Listen("tcp", "[::]:8080") // 所有 IPv6(可能包括 IPv4)
4. 连接超时
// ✓ 正确:设置超时
dialer := &net.Dialer{Timeout: 5 * time.Second}
conn, err := dialer.Dial("tcp", "example.com:80")
// ✗ 错误:可能永久阻塞
conn, err := net.Dial("tcp", "example.com:80")
5. DNS 缓存
// Go 不缓存 DNS 结果(默认)
// 每次 Lookup 都会查询
// 使用 Resolver 可以自定义行为
6. 文件描述符继承
// File() 返回的文件描述符与原连接不同
// 关闭原连接不影响返回的文件
file := tcpConn.File()
tcpConn.Close()
file.Close() // 需要手动关闭
7. MPTCP 支持
// Go 1.21+ 支持 MPTCP
dialer := &net.Dialer{}
dialer.SetMultipathTCP(true) // 尝试使用 MPTCP
// 检查是否使用 MPTCP
tcpConn.MultipathTCP() // (bool, error)
8. 平台差异
// Windows: Unix 域套接字支持有限
// Plan 9: 部分功能不支持
// JS/WASM: 网络功能受限
// 某些 BSD: IPv4/IPv6 需要分别监听
最后更新: 2026-04-05
Go 版本: Go 1.0+(部分功能需要 Go 1.20+)
包文档: https://pkg.go.dev/net
相关 RFC: RFC 793 (TCP), RFC 768 (UDP), RFC 1123 (Host Requirements)