Golang Go语言中一个快速拷贝被类型转换为 interface 的 struct 的方法
Golang Go语言中一个快速拷贝被类型转换为 interface 的 struct 的方法
方法是 从 interface 获取 struct 的地址, 然后将 struct 转成 []byte, 拷贝后再将 []byte 转成 struct
package main_test
import (
"fmt"
"reflect"
"testing"
"unsafe"
)
type beCopy struct {
value int
}
type emptyInterface struct {
typ *struct{}
word unsafe.Pointer
}
type slice struct {
array unsafe.Pointer
len int
cap int
}
func Copy(v interface{}) interface{} {
// 传进来的是一个 struct, 但是类型转换为了 interface
// 目的是拷贝这个 struct
// 因为 interface 本质是一个携带了原来类型信息的指针
// 所以直接 值传递 拷贝是不行的, 值传递拷贝只能再得到一个这样的指针
var t = reflect.TypeOf(v)
var length = int(t.Size())
var vslice = []byte{}
// 所以这里将 struct 的地址替换到 slice 的地址位, 使 vslice 指向的一串内存就是 struct 的内存
(*slice)(unsafe.Pointer(&vslice)).array = (*emptyInterface)(unsafe.Pointer(&v)).word
(*slice)(unsafe.Pointer(&vslice)).len = length
(*slice)(unsafe.Pointer(&vslice)).cap = length
vvslice := make([]byte, length) // 再创建一个 slice
copy(vvslice, vslice) // 将 struct 的内存拷贝到新的 slice
vv := v // 拷贝一个 interface 指针
((*emptyInterface)(unsafe.Pointer(&vv))).word = (*slice)(unsafe.Pointer(&vvslice)).array // 将 新 slice 的内存地址 替换为结构体指针指向的地址
return vv // 返回深拷贝后的 interface 指针
// 大致意思就是,将 struct 转成 []byte, 拷贝后再将 []byte 转成 struct
}
func TestCopy(t *testing.T){
b := beCopy{value: 3}
d := Copy(b)
b.value++
e := Copy(b)
fmt.Println(b,d,e)
}
func BenchmarkCopy(b *testing.B) {
c := beCopy{value: 3}
for i := 0; i < b.N; i++ {
Copy(c)
}
}
更多关于Golang Go语言中一个快速拷贝被类型转换为 interface 的 struct 的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这代码明显有 bug 。可能运气好没有挂掉。
中间 copy 那一步,是没有带 write barrier 的。要搞也要用 typedmemmove 。
更多关于Golang Go语言中一个快速拷贝被类型转换为 interface 的 struct 的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我自己也感觉会有 GC 的问题 … typedmemmove 这些我去看一下
零抽象
只是浅拷贝吧?结构内的指针对象还是引用的同一个?
ValueOf 然后再 Copy ?
在Go语言中,当你有一个结构体(struct)被类型转换为interface{}
类型后,直接进行拷贝可能会变得不那么直观,因为interface{}
是一个空接口,可以表示任意类型。然而,你仍然可以通过一些技巧来实现快速拷贝。
一种常见的方法是使用类型断言(type assertion)将interface{}
转换回原始的结构体类型,然后再进行拷贝。例如:
package main
import (
"fmt"
)
type MyStruct struct {
Field1 int
Field2 string
}
func main() {
original := MyStruct{Field1: 1, Field2: "hello"}
var i interface{} = original
// 类型断言
if copied, ok := i.(MyStruct); ok {
// 现在copied是MyStruct类型的一个拷贝(实际上是值传递)
fmt.Printf("Copied: %+v\n", copied)
} else {
fmt.Println("Type assertion failed")
}
}```
在这个例子中,我们首先将`MyStruct`类型的变量。`注意original,`这里的赋值拷贝给一个实际上是`值interface传递{}直接,`类型即类型的断言`变量更copied`慢`i且是`更复杂`。。original然后通过