微信搜索【脑补炸鱼】关注这条炸肝炸鱼。本文GitHubgithub.com/eddycjy/blog已收录,附有我的系列文章、资料和开源Go书籍。大家好,我是炸鱼。今天是周末,虽然只有一天。跟大家分享一个关于Go1.17的快讯。每天加一个吸鱼小窍门!在Go中,切片包含对其支持数组的引用,无论该数组作为单独的变量存在于某处,还是只是分配用于支持切片的匿名数组。它的切片的基本结构如下://runtime/slice.gotypeslicestruct{arrayunsafe.Pointer//指向底层数组的指针lenint//lengthcapint//capacity}当前切片支持数组的方法可能会导致Slices发生有趣的内存泄漏或对您的slice进行意外更改。还有一个很重要的一点是,在Go1.16及之前的版本中,并没有安全的方式将slice类型转换为array类型,相当无奈。我们只能通过调用标准库reflect或者unsafe,通过编写不安全的代码:(*[10]byte)(unsafe.Pointer(&b[0]))显然这样并不优雅,官方本身是不推荐的使用不安全。一旦处理错误,可能会导致致命错误,相对不可控。其实早在2009年Go发布后不久(早在Go1.0发布之前),就有人提出了相关质疑,希望解决这个问题:终于在即将到来的Go1.17中,这将成为可能,因为来自commit-更新规范的以id#1c268431f4开头的一系列更改:新规范中的描述很简单:将切片转换为数组指针会产生指向切片底层数组的指针。如果切片的长度小于数组的长度,则会发生运行时恐慌。如果切片比数组长,则意味着您的数组将无法访问原始切片的所有后备数组。此外,规范中还提供了一些新示例。在Go1.17中,我们可以这样使用:s:=make([]byte,2,4)s0:=(*[0]byte)(s)//s0!=nils2:=(*[2]byte)(s)//&s2[0]==&s[0]s4:=(*[4]byte)(s)//恐慌:len([4]byte)>len(s)vart[]stringt0:=(*[0]string)(t)//t0==nilt1:=(*[1]string)(t)//恐慌:len([1]string)>len(s)变量s2的转换:它转换切片底部的数组。这种转换不会(也不能)分配一个新的数组,从而保证了它的效率。变量s0和t0的转换:它将一个非空的slice转换成一个长度为0的数组。虽然你不能对长度为0的数组做任何事情,但你还是要给它一个有效的指针,也就是nil。需要注意的是,没有办法检查他是否会因为越界等类型断言等原因而panic。如果你觉得你的snippet可能太短了,可能会引起panic事件,那你就需要用if来预判了。同时标准库reflect也会更新,支持从切片到数组指针的转换。如果你正在使用reflect做相关的转换工作,建议阅读本次投稿中的注意事项。你对Go语言的类型转换有什么其他的想法和诉求,或者踩过什么坑吗?欢迎大家在评论区留言。如有任何问题,欢迎在评论区反馈交流。最好的关系是相互成就。您的好评是创作炸鱼最大的动力。感谢您的支持。文章持续更新中,微信搜索【脑补炸鱼】即可阅读,回复【000】一线大厂面试算法方案和资料我都准备好了;本文已收录在GitHubgithub.com/eddycjy/blog,欢迎Star提醒。
