跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

为什么 *(*string)(unsafe.Pointer(&b)) 不适用于 bufio.Reader

在Go语言中,我们经常会使用类型转换来进行数据类型的转换。例如,将一个[]byte类型的切片转换为 string类 型的字符串。通常情况下,我们可以使用`string()`函数来进行类型转换,但在某些特殊情况下,这种方式会出现问题。在Go语言中,`(string)(unsafe.Pointer(&b))`的方式被称为"魔术指针"方式,用于将一个[]byte类型的切片转换为string类型的字符串。然而,该方式并不适用于bufio.Reader类型。为什么呢?让我们来解答这个问题。 问题内容 我有一个文件。它有一些ip
1.1.1.0/24 1.1.2.0/24 2.2.1.0/24 2.2.2.0/24
我读取此文件进行切片,并使用 *(*string)(unsafe.pointer(&b)) 将 []byte 解析为字符串,但不起作用
func testinitiprangefromfile(t *testing.t) { filepath := "/tmp/test" file, err := os.open(filepath) if err != nil { t.errorf("failed to open ip range file:%s, err:%s", filepath, err) } reader := bufio.newreader(file) ranges := make([]string, 0) for { ip, _, err := reader.readline() if err != nil { if err == io.eof { break } logger.fatalf("failed to read ip range file, err:%s", err) } t.logf("ip:%s", *(*string)(unsafe.pointer(&ip))) ranges = append(ranges, *(*string)(unsafe.pointer(&ip))) } t.logf("%v", ranges) }
结果:
task_test.go:71: ip:1.1.1.0/24 task_test.go:71: ip:1.1.2.0/24 task_test.go:71: ip:2.2.1.0/24 task_test.go:71: ip:2.2.2.0/24 task_test.go:75: [2.2.2.0/24 1.1.2.0/24 2.2.1.0/24 2.2.2.0/24]
为什么 1.1.1.0/24 更改为 2.2.2.0/24 ? 改变 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载
*(*string)(unsafe.Pointer(&ip))
到字符串(ip)它可以工作 解决方法 因此,虽然将切片标头重新解释为字符串标头,但您所做的方式绝对是疯狂的,并且无法保证正常工作,但这只是 间接 导致问题的原因。 p> 真正的问题是,您保留了指向
bufio/Reader.ReadLine()
返回值的指针,但该方法的文档说“返回的缓冲区仅在下次调用 ReadLine 之前有效。”这意味着读者以后可以自由地重用该内存,这就是正在发生的事情。 当您以正确的方式进行转换时,
string(ip)
,Go会将缓冲区的内容复制到新创建的字符串中,该字符串在将来仍然有效。但是,当您将切片键入双关语到字符串中时,您会保留完全相同的指针,一旦读取器重新填充其缓冲区,该指针就会停止工作。 如果您决定使用指针欺骗作为性能黑客以避免复制和分配......那就太糟糕了。无论如何,读取器界面都会强制您复制数据,既然如此,您应该只使用
string()
。

相关文章