type Buffer struct {
buf []byte
off int
lastRead int8
}
//go:nosplit
func BufferReset(b *bytes.Buffer, p []byte) {
buffer := (*Buffer)(unsafe.Pointer(b))
buffer.off = 0
}
1
Thiece 2023-09-20 17:45:30 +08:00
如果你错误地修改了结构体的私有字段,可能会导致数据状态的不一致。例如,可能会影响缓冲区( buffer )的长度和容量,使其不匹配。
bytes.Buffer 的实现在未来版本中发生变化也会出现问题。 |
4
Thiece 2023-09-21 10:13:26 +08:00
```
package main import ( "fmt" "unsafe" ) type MyData struct { length int data int } func main() { data := MyData{ length: 5, data: 100, } fmt.Println("Before:", data) // 获取 MyData 结构体的地址,并转换为通用指针 ptr := unsafe.Pointer(&data) // 模拟不加偏移量的修改操作 *(*int)(ptr) = 200 fmt.Println("After:", data) } ``` |
8
Nazz OP @Thiece 这个例子里面, BufferReset2 比 BufferReset1 多一次 allocs
https://gist.github.com/lxzan/8f491e332a77ea6a049a78074799e9d7 |
9
Thiece 2023-09-21 17:13:14 +08:00 1
@Nazz
Go 语言中的结构体是将 Field 按照声明的顺序进行内存布局。 如果没有使用 unsafe.Offsetof 之类的方法,unsafe.Pointer 获取到的地址就是该结构体的首地址。 结构体的首地址就是其第一个字段的地址,等同于访问该结构体的第一个字段。 BufferReset2 不仅重置了 buf 和 off ,还重置了 lastRead 。 |