猿问

复制具有反射和不安全包的切片

我知道使用golang包是不安全的,但我这样做只是为了教育目的。unsafe


这个想法是复制结构的切片字段,用反射包和不安全的指针复制它,修改并用新的切片替换原始切片。


看起来新切片已创建并具有正确的容量/长度,并且它包含类型的实例。但该实例的所有字段(名称、价格和 Qnty)都有错误的值。所以我想我在指针和获取加勒巴德数据方面做错了什么:GoodForSale


package main


import (

    "fmt"

    "reflect"

    "unsafe"

)


type GoodForSale struct {

    Name string

    Price int

    Qnty int

}


type Lead struct {

    ID int

    Name string

    ContactName string

    Budget int

    Items []GoodForSale

    DateTime string

    Status int

    Win bool

}


func main()  {

    lead := &Lead{

        ID:          41,

        Name:        "Phone",

        ContactName: "John Smith",

        Budget:      30000,

        Items:       []GoodForSale{

            {

                Name:  "Iphone 6",

                Price: 100,

                Qnty:  3,

            },

        },

        DateTime:    "12.08.2020 11:23:10",

        Status: 150,

        Win:         false,

    }



    //Change Items

    pt1 := unsafe.Pointer(&lead.Items)

    copyItems := &reflect.SliceHeader{

        Data: uintptr(pt1),

        Cap: cap(lead.Items),

        Len: len(lead.Items),

    }



    items := *(*[]GoodForSale)(unsafe.Pointer(copyItems))

    fmt.Println(items[0].Name)


}

看起来我在这里错过了一些关于指针如何工作的东西。但是,我怎样才能使这个想法正确运作呢?


这是一个去游乐场网址: https://play.golang.org/p/SKtJWe9RVEU


隔江千里
浏览 73回答 2
2回答

慕侠2389804

问题出在:pt1 := unsafe.Pointer(&lead.Items) // pointer the slice, a.k.a "slice header"copyItems := &reflect.SliceHeader{        Data: uintptr(pt1), // trying to use it as pointer to the actual data.“数据”需要一个指向实际数据起始位置的指针,但您给出的是指向切片本身的指针。这是获取指向切片数据的指针的正确方法:pt1 := unsafe.Pointer(&lead.Items[0]) // pointer to the first element referenced by the slice请注意,如果 .在这种情况下,应使用 。len(lead.Items) == 0unsafe.Pointer(nil)您还可以从原始切片中获取数据指针(以及 len 和 cap),方法是将其转换为如下所示:reflect.SliceHeadercopyHeader := *(*reflect.SliceHeader)(unsafe.Pointer(&lead.Items))items := *(*[]GoodForSale)(unsafe.Pointer(&copyHeader))但是在这一点上,我们基本上只是做了一个复杂而“不安全”的版本:items := lead.Items

噜噜哒

基于来自“迪斯科赞美诗”的输入,通过向指针提供切片元素而不是整个切片来修改代码。package mainimport (    "fmt"    "reflect"    "unsafe")type GoodForSale struct {    Name  string    Price int    Qnty  int}type Lead struct {    ID          int    Name        string    ContactName string    Budget      int    Items       []GoodForSale    DateTime    string    Status      int    Win         bool}func main() {    lead := &Lead{        ID:          41,        Name:        "Phone",        ContactName: "John Smith",        Budget:      30000,        Items: []GoodForSale{            {                Name:  "Iphone 6",                Price: 100,                Qnty:  3,            },        },        DateTime: "12.08.2020 11:23:10",        Status:   150,        Win:      false,    }        pt1 := unsafe.Pointer(&lead.Items[0])    copyHeader := *(*reflect.SliceHeader)(unsafe.Pointer(&lead.Items))    items := *(*[]GoodForSale)(unsafe.Pointer(&copyHeader))    //items := *(*[]GoodForSale)(unsafe.Pointer(copyItems))    fmt.Println(pt1)    fmt.Println(items[0].Name)}输出:0xc00000c080Iphone 6
随时随地看视频慕课网APP

相关分类

Go
我要回答