strings.Fields + 索引取值适合固定结构日志,net.SplitHostPort 是提取带端口网络地址中 IP 的唯一推荐方式,regexp.FindAllString 适用于从大文本中提取邮箱或 IPv4,*net.TCPConn 可直接类型断言获取 net.IP 对象。

strings.Fields + 索引取值适合固定结构日志
当输入是格式高度一致的单行日志(如 Destination: 192.168.1.1 (192.168.1.1)),直接用 strings.Fields 比 strings.Split(s, " ") 更安全:它自动跳过首尾空格和连续空格,避免 parts[1] panic。
- 目标字段位置必须稳定(比如 IP 总是第 2 个非空 token)
- 需手动清理括号:
strings.Trim(ip, "()") - 不适用于含 IPv6 或端口的地址(如
[::1]:8080),会错切 - 性能最优,无正则编译开销,适合高频、低变体场景
net.SplitHostPort 是提取网络地址中 IP 的唯一推荐方式
从 conn.RemoteAddr().String() 这类带端口的地址中取纯 IP,别碰 strings.Split —— 它在 IPv6 地址(如 [2001:db8::1]:443)上必然失败。
-
net.SplitHostPort自动识别方括号包裹的 IPv6,并返回已去括号的ip字符串 - 输入不含端口(如
"127.0.0.1")时返回 error,必须显式处理 - 不支持 Unix 域套接字地址(如
"unix:///tmp/sock"),需先判断addr.Network() - 返回的
ip是字符串,不是net.IP类型;如需校验合法性,再调用net.ParseIP(ip)
regexp.MustCompile 提取所有匹配项(Email/IP)
要从大文本里捞出全部邮箱或 IPv4 地址,FindAllString 是最直白的选择,但正则写法和编译时机很关键。
- 邮箱正则建议用:
[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}(注意转义-和.) - IPv4 正则别写太松(如
\d+\.\d+\.\d+\.\d+),会匹配到999.999.999.999;更稳妥的是分段验证 - 务必复用编译后的
*regexp.Regexp对象,避免在循环里反复调用regexp.Compile -
FindAllString(text, -1)返回[]string;若需捕获组(如只取域名部分),改用FindAllStringSubmatch
从 *net.TCPConn 直接取 net.IP 对象
如果你已经拿到 *net.TCPConn,就别再去解析它的 RemoteAddr().String() —— 类型断言一步到位。
立即学习“go语言免费学习笔记(深入)”;
- 写法是:
conn.RemoteAddr().(*net.TCPAddr).IP - 该
IP是net.IP类型,可直接用于net.IP.Equal、子网判断等逻辑 - 仅适用于 TCP 连接;UDP 或其他协议需对应断言为
*net.UDPAddr等 - 如果连接已关闭或类型不符,断言会 panic,生产环境应加
ok判断:if tcpAddr, ok := conn.RemoteAddr().(*net.TCPAddr); ok { ... }
strings.Fields 仍能稳住,而硬切 strings.Split(s, ":") 可能直接越界;又比如没预判 net.SplitHostPort 的 error 分支,服务在 IPv6 环境下就 quietly 失败。选哪条路,得看你的输入到底有多“脏”。


















