为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
隔江千里 2022-09-12 20:38:00
我知道使用golang包是不安全的,但我这样做只是为了教育目的。unsafe这个想法是复制结构的切片字段,用反射包和不安全的指针复制它,修改并用新的切片替换原始切片。看起来新切片已创建并具有正确的容量/长度,并且它包含类型的实例。但该实例的所有字段(名称、价格和 Qnty)都有错误的值。所以我想我在指针和获取加勒巴德数据方面做错了什么:GoodForSalepackage 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,    }    //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
查看完整描述

2 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

问题出在:


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.SliceHeader


copyHeader := *(*reflect.SliceHeader)(unsafe.Pointer(&lead.Items))


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

但是在这一点上,我们基本上只是做了一个复杂而“不安全”的版本:


items := lead.Items


查看完整回答
反对 回复 2022-09-12
?
噜噜哒

TA贡献1784条经验 获得超7个赞

基于来自“迪斯科赞美诗”的输入,通过向指针提供切片元素而不是整个切片来修改代码。


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,

    }


    

    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)


}

输出:


0xc00000c080

Iphone 6


查看完整回答
反对 回复 2022-09-12
  • 2 回答
  • 0 关注
  • 72 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号