Skip to content

🚫 保留 IP 地址

私有、回环、组播等保留地址没有地理意义,查询会返回特定错误。

什么是保留 IP

保留地址(reserved IP)是 IANA 规定不分配给公网设备的特殊地址段,例如:

用途
10.0.0.0/8私有网络
172.16.0.0/12私有网络
192.168.0.0/16私有网络
127.0.0.0/8回环(localhost)
0.0.0.0未指定
169.254.0.0/16链路本地
::1IPv6 回环

这些地址没有真实的地理归属

查询保留 IP 会怎样

ipapi.co 对保留 IP 返回特殊错误响应,本库映射为 ErrReservedIP

go
_, err := client.GetIPInfo(ctx, "10.0.0.1", "json")
if errors.Is(err, ipapi.ErrReservedIP) {
	fmt.Println("保留地址,无地理信息")
}

错误结构

服务端返回的 APIError 会带 Reserved: trueIP 字段,handleError 据此映射:

go
case "Reserved IP Address":
	return fmt.Errorf("%w: %s", ErrReservedIP, apiErr.IP)

errors.As 取细节:

go
var apiErr *ipapi.APIError
if errors.As(err, &apiErr) {
	fmt.Println("保留地址:", apiErr.IP, "Reserved:", apiErr.Reserved)
}

🎨 一图抵千言

下面用时序图展示客户端与 ipapi.co 服务端在一次保留 IP 查询中的交互过程,重点呈现 APIError 携带 Reserved: true 的回传时机。

如何处理

go
info, err := client.GetIPInfo(ctx, userInput, "json")
switch {
case errors.Is(err, ipapi.ErrReservedIP):
	// 内网地址,跳过或用默认值
	info = &ipapi.IPInfo{CountryCode: "XX"}
case err != nil:
	return err
}

校验前置

ValidateIP 不会拦截保留地址——它只判断格式合法性(net.ParseIP 能解析即合法)。保留判断在服务端完成。

🎨 一图抵千言

下图展示保留 IP 的判断链路:本地校验放行后,请求到达服务端,最终由 handleError 映射为 ErrReservedIP

go
ipapi.ValidateIP("10.0.0.1") // nil,格式合法
// 但 GetIPInfo 会返回 ErrReservedIP

💡 想本地预判保留地址?

net.IP.IsPrivate()IsLoopback() 等:

go
ip := net.ParseIP("10.0.0.1")
if ip.IsPrivate() { /* 跳过 */ }

下一步

基于 MIT 许可证发布