如何分配内存以映射指向golang中的切片 [英] How to allocate memory to map pointing to slice in golang

查看:68
本文介绍了如何分配内存以映射指向golang中的切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种方法来分配映射的内存,该内存最多具有Nmax个键,该键指向最大长度为Nmax的切片?

Is there a way to allocate the memory of a map, which has at most Nmax keys, that points to a slice of maximum length Nmax?

我目前只是通过make(map[int][]int,Nmax)指定最大键数,但是我不确定如何告诉Go每个切片的最大长度为Nmax,因为我不知道键会是什么是先天的.

I'm currently just specifying the max number of keys via make(map[int][]int,Nmax), but I'm not sure how to tell Go that each slice will be of maximum length Nmax because I don't know what the keys will be apriori.

我基本上有一堆人口为整数的网站.我使用地图跟踪给定人口N的站点数.我程序中的瓶颈似乎是runtime.memmove,我猜这是由于不断调整地图指向的切片的大小而引起的.

I essentially have a bunch of sites with an integer population. I use the map to keep track of how many sites have a given population N. The bottleneck in my program appears to be runtime.memmove, which I'm guessing comes from constant resizing of the slice the map points to.

推荐答案

因此,鉴于您对问题的描述确实相当模糊,我将首先说一下如何管理"地图.为简单起见,我将所有逻辑包装在接收器函数中,因此将地图包装在自定义类型中:

So given that your description of the problem is really rather vague, I'll just start by saying how I'd go about "managing" the map. To keep things simple, I'm going to wrap all the logic up in receiver functions, so wrapping the map up in a custom type:

type dataMap struct {
    data map[int][]int
    nmax int
}

func New(Nmax int) *dataMap {
    return &dataMap{
        data: make(map[int][]int, Nmax),
        nmax: Nmax,
    }
}

// Get - return slice for given key
func (d dataMap) Get(k int) []int {
    s, ok := d.data[k]
    if !ok {
        return nil // optionally return error
    }
    return s
}

// Set - set/append values to a given key - this is not safe for concurrent use
// if that's needed, add a RWMutex to the type
func (d *dataMap) Set(k int, vals ...int) error {
    s, ok := d.data[k]
    if !ok {
        s = make([]int, 0, d.nmax) // allocate slice of given length
    }
    // optionally check for nil-values + ensure we're not exceeding the nmax
    checked := make([]int, 0, len(vals))
    for i := range vals {
        if vals[i] != 0 {
            checked = append(checked, vals[i])
        }
    }
    if len(s) + len(checked) > d.nmax {
        return errors.New("max capacity exceeded")
    }
    s = append(s, checked...) // append values
    d.data[k] = s // update map
    return nil
}

这减少了不必要的内存(重新)分配调用.它还确保了我可以通过O(1)操作获得映射中任何切片的长度,而不必担心nil值:

This cuts down on needless memory (re-)allocation calls. It also ensures that I can get the length of any slice in the map in an O(1) operation, without having to worry about nil values:

myData := New(10)
fmt.Println(myData.Set(4, 1, 2, 3, 4))
fmt.Println(len(myData.Get(4))) // 4
fmt.Println(cap(myData.Get(4))) // 10
// nil-values are filtered out
myData.Set(4, 5, 6, 7, 0, 0, 0, 0)
fmt.Println(len(myData.Get(4))) // 7
fmt.Println(cap(myData.Get(4))) // 10
// exceeding capacity of 10
fmt.Println(myData.Set(4, 8, 9, 10, 11)) // max capacity exceeded

正在工作演示


可以使用数组而不是切片来管理容量,但这确实需要您手动跟踪要开始附加值的索引/偏移量.一般来说,在非常特殊的情况下,请勿在golang中使用数组.在这种情况下,我只想选择一个带帽的切片.这样做的好处是,例如,您可以具有不同长度的切片.结果也很容易测试,因为这样的类型非常适合用接口类型替换它

working demo


You could manage the capacity by using an array instead of a slice, but that does require you to manually keep track of the index/offset at which you want to start appending values. Generally speaking, you don't use arrays in golang lest in very, very specific cases. In this case, I'd just opt for a slice with a set cap. The advantage of this is that you could, for example have slices of different lengths. The result is very easy to test, too, because a type like this lends itself quite well to replacing it with an interface type

type DataContainer interface {
    Get(k int) []int
    Set(k int, vals ...int) error
    Declare(k, capacity int) error // error if k is already in use?
}

这篇关于如何分配内存以映射指向golang中的切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆