Так что, учитывая, что ваше описание проблемы действительно довольно расплывчато, я просто начну с того, как мне нужно «управлять» картой.Для простоты я собираюсь обернуть всю логику в функции приемника, поэтому оборачиваем карту в пользовательский тип:
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
работает демо
Вы могли бы управлять емкостью, используя массив вместо среза, но для этого необходимо вручную отслеживать индекс / смещение, с которого вы хотите начать добавление значений.Вообще говоря, вы не используете массивы в 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?
}