简体   繁体   English

获取切片中值的指针

[英]Get pointers for values in the slice

Is there any way to get pointers to the actual value in slice?有没有办法获得指向切片中实际值的指针? I have a tree of offers in the maps:我在地图上有一棵报价树:

map[uint64]map[uint16][]offer

For fast access by id (which from 1 to n) I need a slice of pointers:为了通过 id(从 1 到 n)快速访问,我需要一片指针:

[]*offer

Actual offers lies in the first tree, in the slice should be pointers to the that actual.实际报价位于第一棵树中,切片中应该是指向实际报价的指针。

I can't traverse tree and collect pointers of actual values because with range of this slice gives me a copies, but I have more than billions of this structs in total and copies will lead to waste of my memory: 40 bytes for one struct lead to the 100+ gb and much more in the future.我无法遍历树并收集实际值的指针,因为这个切片的range给了我一个副本,但我总共有超过数十亿个这样的结构,副本会导致我的内存浪费:一个结构导致 40 字节到 100+ GB 以及未来更多。 I also need to store slice of values in the tree to contiguous in order to fact lookup of offers.我还需要将树中的值片段存储为连续的,以便实际查找要约。

May be there are some way to use unsafe or reflect package to get these pointers?可能有什么方法可以使用unsafereflect包来获取这些指针?

Index of pointers build only one time and both structs are immutable and only used to lookup offers.指针索引仅构建一次,并且两个结构都是不可变的,仅用于查找报价。

Update: I was totally wrong.更新:我完全错了。 There is no problem to get pointer to element in the slice.获取切片中元素的指针没有问题。 My code was:我的代码是:

        var offers []offer // actually there was about 50gb of offers
        for i := range offers {
            currentOffer := offers[i]
            s.Relations[currentOffer.Id] = &currentOffer
        }

After this snippet overall amount of ram consumed by the app became 100+gb.在此片段之后,应用程序消耗的 ram 总量变为 100+gb。 I immediately thought that take element from slice of values give me a copy of that value, but it is wrong.我立即认为从值的切片中获取元素会给我一个该值的副本,但这是错误的。 I just copied original value to the currentOffer variable by myself.我只是自己将原始值复制到currentOffer变量中。 Little mistake took 50gb of ram away.一个小错误带走了 50GB 的内存。

Actually this snippet is work fine as expected:实际上,此代码段按预期工作正常:

    for i := range offers {
        s.Relations[offers[i].Id] = &offers[i]
    }

After some investigation I came to the following code:经过一番调查,我得出了以下代码:

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type offer struct {
    id uint64
}

func main() {

    sl := []offer{{1}, {id: 2}}

    size := unsafe.Sizeof(offer{})
    header := (*reflect.SliceHeader)(unsafe.Pointer(&sl))
    for i := 0; i < len(sl); i++ {
        offset := uintptr(i) * size
        ptr := header.Data + offset

        o := (*offer)(unsafe.Pointer(ptr))
        o.id = 5
        fmt.Println(o)
    }

    for _, o := range sl {
        fmt.Println(o.id)
    }
}

Playground: https://play.golang.org/p/OM3i84cKAB_7游乐场: https : //play.golang.org/p/OM3i84cKAB_7

Output:输出:

&{5}
&{5}
5
5

This snippet of code illustrate access to the actual data in the slice, not copied one.这段代码说明了对切片中实际数据的访问,而不是复制的数据。

Update: Take pointers via unsafe pointer give the same effect as take regular pointer from the slice by index.更新:通过不安全指针获取指针与按索引从切片中获取常规指针具有相同的效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM