当前位置: 首页 > 科技观察

Go1.18新特性:引入新的Netip网络库

时间:2023-03-13 07:48:20 科技观察

大家好,我是建宇。写这篇文章的时候正值大年初一,本来想说Go1.18这个月发布。但是,好家伙,Go1.18beta2已经发布了,官方通知社区Go1.18要推迟到3月份,咕咕……如下图:所以我们还是要继续学习新的features,今天炸鱼会结合BradFitzpatrick撰文《netaddr.IP: a new IP address type for Go[1]》给大家看Go1.18新网库n??et/netip的来由。后台大佬留下了原本在Go开发组的BradFitzpatrick。2010年到2020年在Go团队工作,2021年换了公司。推特消息如下:离职原因是:做同样的事情太久了,有点无聊,而且我不想陷入舒适的困境。现在好像转用Tailscale做WireGuard相关的工作,经常要和网络库打交道。大榭公司写的Tailscale本质上是一个网络应用。对网络的处理,是用Go写的,会涉及到标准库net:在单一IP类型上使用net.IP。在网络表示上使用net.IPNet。示例代码:import("fmt""net")funcmain(){fmt.Println(net.IPv4(8,8,8,8))}输出结果:8.8.8.8BradFitzpatrick在实际编写和使用时,我发现net标准库的类型有很多问题,使用起来非常困难。现在是什么问题?BradFitzpatrick在文章中直接列出了标准库net.IP存在的问题,论证充分。总共7个大问题:它是可变的。net.IP的底层类型是[]byte,这意味着你传递给它的任何东西都可能改变它。这是不可比的。因为Go中的切片是不可比较的,这意味着net.IP不支持Go的==操作符的比较,不能作为mapkey。它有两种类型的IP地址,在net.IP或net.IPAddr之间进行选择可能会很烦人。它超大。Go的net.IP包含2部分,分别是24字节的切片头和4/6字节的IP地址。在net.IPAddr的情况下,它还将包含一个Zone字段。它在堆上分配内存。Go的netpackage到处分配,把更多的工作放在GC上。它不可解析。Go的IP类型在从字符串形式解析IP时无法区分IPv4映射的IPv6地址和IPv4地址。它是透明类型,net.IP的定义是:typeIP[]byte,这是它的公共API的一部分,不能改变。Brad还提到,有些是早期设计的,当时没有经验,也没有考虑好。现在受限于Go1兼容性承诺,无法更改(兼容性保证双刃剑?)。这是“吃自己的狗粮”的真实版本,所以在Tailscale他重新创建了一个wheelinetaf/netaddr[2],并想贡献它并将其插入标准库。以后想要什么的对照表如下:老方案net.IP和新方案不变?,slice?可比?,slice?占空间小?,28~56bytes?,固定的堆上不分配24个字节??支持IPv4和IPv6??区分IPv4和IPv6??支持IPv6区域??不透明类型??与标准库互操作?