netaddr.ip:Go的新IP地址类型

2021-03-11 06:11:43

TailScale是一个网络应用程序,所以自然地我们需要使用和经常使用操作IP地址和IP地址集。

几乎完全完全编写,明显的选择将是FortailScale使用Go Standard Library的Net.IP地址类型for Idenderips和net.ipnet类型fornetworks。不幸的是,标准库的类型具有多个问题,因此我们编写了一个新的软件包,Inet.af/netaddr(github),包含新的IP类型等。

当我在全职工作时,我提交了问题#18804以跟踪Go的IP地址不太好的话:

它是可变的。 net.ip的下面的界限只是一个[]字节,这意味着你将它传递到可能会变动。不变的数据结构更安全,更容易理解,并且不需要防御副本。

因为Go的切片没有比较,这意味着它尚未展示Go's ==运算符,并且不能用作地图键。

标准库中有两个IP地址类型:Net.IP for Justa Basic IPv4或IPv6地址,然后也是Net.IPADDR,如果需要支持IPv6区域范围。在标准库中有两种类型意味着您是您确定哪种类型要接受或从代码中返回,或返回两个+变体,这会变得烦人(例如Go的Resolver.Lookupvvs Resolver.LookupIPAddr)

它很大。对于切片标题,Go Slice是3个单词(SO 24字节上总共24个字节),而不为切片标题计算切片指向(背景)的下面的arrayArtay。所以具有Go的Net.ip Istwo部分的IP地址:24字节切片标题,然后也是4或16字节的IP地址。如果您想要IPv6区域,还必须使用Net.IPADDR与16字节字符串标头。

它分配了,#43451。 Go's Net Package在任何地方都充满了分配,在GC上进行了更多的工作,从而为CPU提供了更多的工作。如果您调用net.parseip或接收UDP数据包,则需要在它记录IP地址的情况下分配underingling array,以将该点放入返回的net.ip的标题中。

从其字符串表单解析IP时,Go的IP类型无法在IPv4映射的IPv6AddressesAnd IPv4地址之间无法区分。 Go IP类型不会记录原始地址族。在Go问题中跟踪该问题#37921。

这是一种透明的类型。 net.ip的定义是:类型ip []字节,这意味着它的底层类型是一个字节切片,它是其公共API的一部分和不可改变。相比之下,GO的时间。时间类型是定义的,如类型时间结构{/ *未被驱动* /},因此在不破坏API承诺的情况下可以自由更改。事实上,Go的时间是最近在1.9获得透明单调时间支持时更新的时间。如果类型没有透明,则不会成为可能。一些琐事:在GO之前过去常常是透明的。遗憾的是,我们在IP地址类型的情况下不够努力。

其中一些是当时的设计,前1锁在2012年的兼容性承诺之前,它的兼容性刚刚被认为是嗯或达到足够的经验,并通过去了解哪些模式效果很好,没有。在任何情况下,Go标准库现在无法更改。