登录
首页 >  Golang >  Go问答

在golang中如何创建指向切片的映射

来源:stackoverflow

时间:2024-03-07 13:39:26 239浏览 收藏

对于一个Golang开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《在golang中如何创建指向切片的映射》,主要介绍了,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!

问题内容

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

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

我基本上有一堆拥有整数人口的网站。我使用地图来跟踪有多少个站点具有给定人口 N。我的程序中的瓶颈似乎是runtime.memmove,我猜测它来自于地图指向的切片的不断调整大小。


解决方案


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

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 值:

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

工作demo

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

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?
}

您对问题的描述含糊不清,并且您没有提供代码来说明您的问题。

如果地图切片容量等于 0,则将其设置为 nmax。例如,

package main

import "fmt"

func main() {
    nmax := 42

    m := make(map[int][]int, nmax)

    k, e := 7, 11
    v := m[k]
    if cap(v) == 0 {
        v = make([]int, 0, nmax)
    }
    m[k] = append(v, e)

    v = m[k]
    fmt.println(k, len(v), cap(v), v)

    fmt.println(m)
}

演示:https://play.golang.org/p/csoUCUvVDAp

输出:

7 1 42 [11]
map[7:[11]]

本篇关于《在golang中如何创建指向切片的映射》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>