You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang net.ParseIP()误判合法IPv6为IPv4的惯用解决方法问询

How to handle IPv4-mapped IPv6 addresses correctly in Go

Great question! This behavior isn’t a bug—it’s actually intentional in Go’s standard library. Addresses like ::ffff:0100:0 are IPv4-mapped IPv6 addresses (defined in RFC 4291), and net.ParseIP() returns their underlying IPv4 representation by design because that’s what most network operations expect to work with. But if you need to preserve the original IPv6 form, here are the most idiomatic Go approaches:

Option 1: Detect and reconstruct the IPv6 address (compatible with all Go versions)

If you’re stuck on an older Go version, you can check if an IP is an IPv4-mapped IPv6 and manually rebuild the full IPv6 address. This avoids rewriting the entire parsing logic and leverages the standard library’s existing IP handling:

import "net"

func preserveIPv6Mapped(ip net.IP) net.IP {
    // Check if this is an IPv4 address derived from a mapped IPv6
    if ip4 := ip.To4(); ip4 != nil {
        // Construct the IPv4-mapped IPv6 prefix + the IPv4 bytes
        mapped := make(net.IP, net.IPv6len)
        copy(mapped[:12], []byte{0,0,0,0,0,0,0,0,0,0,0xff,0xff})
        copy(mapped[12:], ip4)
        return mapped
    }
    // Return as-is if it's already IPv6 or a regular IPv4
    return ip
}

Usage example:

ip := net.ParseIP("::ffff:0100:0")
fmt.Println(ip.String())       // Outputs "1.0.0.0"
fixedIP := preserveIPv6Mapped(ip)
fmt.Println(fixedIP.String())  // Outputs "::ffff:100:0"

Option 2: Use the netip package (Go 1.18+)

Go 1.18 introduced the netip package, which fixes many quirks in the older net.IP type. A key improvement is that it preserves the original address type, including IPv4-mapped IPv6 addresses:

import "net/netip"

addr, err := netip.ParseAddr("::ffff:0100:0")
if err != nil {
    // Handle error
}
fmt.Println(addr.String()) // Outputs "::ffff:100:0"
fmt.Println(addr.Is4())    // false (treated as IPv6)
fmt.Println(addr.Is6())    // true

If you need the underlying IPv4 address later, you can use addr.As4(), but the default representation stays true to your input. This is the cleanest solution for recent Go versions—it’s part of the standard library and avoids manual address construction.

Why these are idiomatic Go

  • Avoid reinventing the wheel: Both solutions use standard library components instead of rewriting parsing logic, keeping your code maintainable and aligned with Go’s philosophy of trusted, well-tested tools.
  • Explicit intent: The first option clearly checks for the mapped case and adjusts it, making your code’s purpose obvious to other developers. The second option uses a modern library designed to handle these edge cases correctly out of the box.

内容的提问来源于stack exchange,提问作者Stefan Beyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:37:52