写这篇文章时是大年初一,原本想说这个月就要发布 Go1.18 了。但是,好家伙,Go1.18 beta2 发布了,官方告知社区 Go1.18 要拖更到 3 月份了,咕咕咕...
按需定制开发可以根据自己的需求进行定制,网站制作、成都网站制作构思过程中功能建设理应排到主要部位公司网站制作、成都网站制作的运用实际效果公司网站制作网站建立与制做的实际意义
如下图:
所以还是得继续学习新特性,今天煎鱼将结合 Brad Fitzpatrick 写的《netaddr.IP: a new IP address type for Go[1]》带大家了解 Go1.18 的新网络库 net/netip 的缘由。
原本 Go 开发团队中的 Brad Fitzpatrick,在 2010~2020 年都在 Go 团队工作,在 2021 年起换公司了。
如下推特的消息:
离职的原因是:做了同样的东西太久了,有些厌烦,不想陷在一个舒适的困境中。
现在来看是换到了 Tailscale,做 WireGuard 相关工作,要经常与网络库打交道。
大佬公司写的 Tailscale,本质上是一个网络应用程序,要与网络打交道,又是用 Go 写的,就会涉及到标准库 net:
示例代码:
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.IPv4(8, 8, 8, 8))
}
输出结果:
8.8.8.8
Brad Fitzpatrick 在实际编写和使用时,发现 net 标准库的类型有很多问题,很不好用。
Brad Fitzpatrick 对于标准库 net.IP 的问题,直接在文章中列举了出来,论据十足。
共 7 个大问题:
Brad 也有提到有些是当年早期的设计,当时经验不足,或是没有考虑好。
现在受限于 Go1 兼容性承诺,已经无法改变了(兼容性保障的双刃剑?)。
这是个真实版 “Eating your own dog food”,所以在 Tailscale 他又重新造了一个轮子inetaf/netaddr[2],想贡献出来,塞进标准库里。
对比表格如下:
特性 |
老方案 net.IP |
新方案 |
不变的 |
, slice |
|
可比的 |
, slice |
|
占用空间小 |
,28~56 字节 |
,固定 24 字节 |
不在堆上分配 |
||
支持 IPv4 和 IPv6 |
||
区分 IPv4 和 IPv6 |
||
支持 IPv6 区域 |
||
不透明的类型 |
||
与标准库互通 |
????,需适配方法 |
想要的样子,其实是 Brad 业务实战出来的诉求,就是要支持前面提到的 7 点。
实现的结果,也就是新方案做出来了,他就是inetaf/netaddr[3] 这个库(当然,也不排除是结果倒推理论)。并且在 Go issues 中发起 issues 和 proposal。
https://pkg.go.dev/inet.af/netaddr
Russ Cox 发起了新提案的讨论《proposal: net/netaddr: add new IP address type, netaddr package (discussion)[4]》,并被接纳,进入了 Go1.18 的新特性当中。
新的 net/netip 库的每一个考量点,Brad 都在文章中有所详细讲解。
受限于篇幅,我们拿其中两点来分享,有兴趣的小伙伴可以阅读原文的剖析部分。
在可比较这事上,Go 的接口(interface)其实是支持比较的,也就是可以作为 map 的 key 进行 == 运算符的比较。
实现了如下的第一版方案,设计了新的netaddr.IP 类型:
type IP struct {
ipImpl
}
type ipImpl interface {
is4() bool
is6() bool
String() string
}
type v4Addr [4]byte
type v6Addr [16]byte
type v6AddrZone struct {
v6Addr
zone string
}
上述代码,在 IP 结构体中增加了 ipImpl 接口,既能支持比较,还可以不对外暴露(不透明类型),且可以支持 IPv6。
新的问题在于,虽然比原生 net 小了,但还是没达到目标,还是有在堆上分配的缺点。
如果继续使用接口,是无法解决根本目标(Brad 的目标是 24 字节)的。
因为接口(interface)占用 16 字节,剩余 8 个字节可以用,要放如下东西:
还要能比较,显然接口是无法实现的,因为地址+zone 信息算一下字节数,显示是不够用的。
正规显式的没办法,Brad 想到了用打包的方式:
type IP struct {
addr [16]byte
zoneAndFamily uint64
}
但这么做,就意味着 zoneAndFamily 字段中需要计算位数,再对应的推入相应的值,但也未必太折腾了。
最终 Brad 想到了,可以使用指针的方式:
type IP struct {
addr [16]byte
zoneAndFamily *T
}
再定义 3 个对应哨位值的来应用:
var (
z0 *intern.Value // 表示零值。
z4 = new(intern.Value) // 表示 IPv4 的哨位值
z6noz = new(intern.Value) // 表示 IPv6 的哨位值(没有 zone)。
)
这样就可以把 IP 类型固定在 24 字节。
这个网络地址库,一般都用的比较少。但是 Brad Fitzpatrick 在此投入了大量的精力和研究,达到了最终的目标。
除去库的功能外,有许多技术优化点值得我们学习和参考,有兴趣深入优化部分的,可以阅读:https://tailscale.com/blog/netaddr-new-ip-type-for-go/[5]
本文介绍的新 net/netip 库将会在 Go1.18 中作为新特性出现,欢迎大家一起学习交流:)
参考资料
[1]netaddr.IP: a new IP address type for Go: https://tailscale.com/blog/netaddr-new-ip-type-for-go/
[2]inetaf/netaddr: https://github.com/inetaf/netaddr
[3]inetaf/netaddr: https://github.com/inetaf/netaddr
[4]proposal: net/netaddr: add new IP address type, netaddr package): https://github.com/golang/go/discussions/47323
[5]https://tailscale.com/blog/netaddr-new-ip-type-for-go/: https://tailscale.com/blog/netaddr-new-ip-type-for-go/#wgcfg
分享文章:Go1.18新特性:引入新的Netip网络库
标题链接:http://www.shufengxianlan.com/qtweb/news1/90151.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联