加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

Go1.18 资讯 新的 IP 包

发布时间:2021-12-07 04:05:25 所属栏目:语言 来源:互联网
导读:Go 1.18 标准库新增了一个包:net/netip,大部分人可能用不上这个包,但这个包的设计思路以及和现有标准库 IP 的比较值得学习。 标准库 net.IP 的问题 前 Go Team 成员之一 Brad Fitzpatrick 加入 Tailscale[1] 后,经常需要操作 IP 地址。因为使用 Go 语言实
Go 1.18 标准库新增了一个包:net/netip,大部分人可能用不上这个包,但这个包的设计思路以及和现有标准库 IP 的比较值得学习。
 
  标准库 net.IP 的问题
前 Go Team 成员之一 Brad Fitzpatrick 加入 Tailscale[1] 后,经常需要操作 IP 地址。因为使用 Go 语言实现的,自然会使用过标准库的 net.IP 和 net.IPNet 等类型。但他们认为标准库的相关类型有很多问题,所以他们自己写了一个包:https://github.com/inetaf/netaddr。
 
早在 2017 年 1 月,Brad Fitzpatrick 就提了 issue,认为 net.IP 的设计存在问题:https://github.com/golang/go/issues/18804,那时他还在 Go Team。
 
具体来说,net.IP 存在如下几个问题:
 
可变的。net.IP 的底层类型是 []byte,它的定义是:type IP []byte,这意味着你可以随意修改它。不可变数据结构更安全、更简单。
不可比较的。因为 Go 中 slice 类型是不可比较的,也就是说 net.IP 不支持 ==,也不能作为 map 的 key。
有两个 IP 地址类型,net.IP 表示基本的 IPv4 或 IPv6 地址,而 net.IPAddr 表示支持 zone scopes 的 IPv6。因为有两个类型,使用时就存在选择问题,到底使用哪个。标准库存在两个这样的方法:Resolver.LookupIP vs Resolver.LookupIPAddr。(关于什么是 IPv6 zone scopes 见维基百科:https://en.wikipedia.org/wiki/IPv6_address#Scoped_literal_IPv6_addresses_(with_zone_index 。)
太大。在 Go 中,64 位机器上,slice 类型占 24 个字节,这只是 slice header。因此,net.IP 的大小实际包含两部分:24 字节的 slice header 和 4 或 6 字节的 IP 地址。而 net.IPAddr 更有额外的字符串类型 Zone 字段,占用空间更多。
不是 allocates free 的,会增加 GC 的工作。当你调用 net.ParseIP 或接收一个 UDP 包时,它为了记录 IP 地址会分配底层数组的内存,然后指针放入 net.IP 的 slice header 中。
当解析一个字符串形式的 IP 地址时,net.IP 无法区分 IPv4 映射的 IPv6 地址[2]和 IPv4 地址。因为 net.IP 不会记录原始的地址族(address family)。见 issue 37921[3]
它是一种透明类型(transparent type)。因为它的定义是:type IP []byte,底层类型是一个字节切片。这有什么问题呢?我们没法改变 IP 的底层类型了,因为它已经是导出 API 的一部分。标准库中一个很好的例子是 time.Time 类型,它是一个不透明类型:type Time struct { /* unexported */ },也就是里面有什么没公开,这样库作者可以随便修改里面的内容,只需要保证导出 API 不变即可。实际上 Go1.9 就改过一次 time.Time 的内部结构,完全不会破坏兼容性。
但为了兼容性,以上这些问题没法通过改进 net.IP 类型解决。于是才有了 Brad Fitzpatrick 上面开发的包。该包已经正式合入 Go1.18 标准库中,这就是 net/netip 包,这里可以查看包文档:https://pkg.go.dev/net/netip@master。

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!