【问题标题】:Golang how to create map to pointer to slice using makeGolang如何使用make创建指向切片指针的映射
【发布时间】:2021-09-01 11:23:10
【问题描述】:

我想创建一个动态初始化的位图数据结构。我正在尝试为此使用 golang 地图:

type Register map[bool]*[]bool

我初始化地图的方式是:

register := make(Register)
register[true] := make(*[]bool, len(arr))  // arr is the array for which i want to create the bitmap

这显然会产生错误的编译问题:

error: cannot make type *[]bool

我也尝试过使用指针语法:

register[true] = &(make([]bool, len(arr)))

这给了我错误:

cannot take the address of make([]bool, len(arr))

我希望地图值为*[]bool 的原因是为了使回写到地图的内容保持正常和原位。

虽然 go 不会抱怨 map[bool]*[]bool 因此它是一个有效的类型。
如果它是有效的,那么以我想要的方式使用它的惯用方式是什么。如果不是,那另一种方法是什么?

【问题讨论】:

  • 我不清楚为什么你首先想要一个指向切片的指针;你能澄清一下吗?切片已经是引用类型,想要一个指向它的指针是很奇怪的——确切的用例是什么?
  • 除非你正在做一些高并发和序列化对地图的访问,否则指向切片的指针可能不会比切片提供任何好处。
  • 这听起来像XY problem。你想代表什么?正如其他人所指出的,指向 slice 的指针似乎是多余的——因为空 slice 可以用 nil 值表示——除非你想表示一个未初始化的状态。同样,如果我们对您的数据模型有清晰的了解,我们可以提供更好的帮助。
  • 没错,但您为什么不想重新分配给地图呢?请注意,切片标题相当小,因此 m[key] = append(m[key], ...) 很好
  • @IshanKhare 不。我认为对 append 的工作方式存在一些误解。见,tour.golang.org/moretypes/15。即使您使用指向切片的指针,也可能发生容量不足以容纳数据的情况,然后 append 可能会分配一个更大的数组来存储它,并且返回的切片将指向新的后备数组。

标签: go pointers hashmap


【解决方案1】:

使用以下代码创建指向切片的指针:

register := make(Register)
s := make([]bool, len(arr)) // create addressable slice value s.
register[true] = &s

你可以使用new来消除变量声明,但是这种做法并没有减少代码行数,而是增加了另一个map索引操作。

register := make(Register)
register[true] = new([]bool)
*register[true] = make([]bool, len(arr))

声明一个函数以将赋值移动到一行:

func makeSlice(n int) *[]bool {
    s := make([]bool, len(arr))
    return &s
}

...

register := Register{true: makeSlice(len(arr))}

因为映射键有两个可能的值,true 和 false,您可以通过使用结构而不是映射来简化代码:

type Register struct {
    t, f []bool
}

register := Register{t: make([]bool, len(arr))}

register 中的结构体字段是可寻址的,因此您可以使用&register.t 来获取*[]bool。

这个主题的一个变体是使用一个数组:

type Register [2][]bool
register := Register{1: make([]bool, len(arr))}

如果只修改切片元素而不修改切片值,则无需使用指向切片的指针。

type Register map[bool][]bool
register := make(Register)
register[true] := make([]bool, len(arr))

如果您确实修改了切片值,map[bool][]bool 可能会更高效且更易于使用。当切片值被修改时,应用程序需要重新分配给映射,但您消除了间接。

【讨论】:

  • 我当然可以这样做,但是如果我不想使用像 s 这样的辅助变量,有什么解决方法吗?
  • 你能详细说明一下 slice 'header' 和 'elements' 是什么意思吗?
  • 我明白你现在的意思了@Penelope,但如果我做一个像追加这样的操作,那么我必须将新切片重新分配回地图。指向切片的指针不会出现这种情况。
  • @IshanKhare:如果你 append 那么你必须在 somewhere 写入切片值,指针不会神奇地让它消失,在大多数情况下它只是一个不必要的间接。
【解决方案2】:

另一种选择是使用new 函数:

package main
import "fmt"

func main() {
   type Register map[bool]*[]bool
   register := make(Register)
   register[true] = new([]bool)
   // main.Register{true:(*[]bool)(0xc000004078)}
   fmt.Printf("%#v\n", register)
}

https://golang.org/pkg/builtin#new

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-11
    • 2021-09-15
    • 2019-03-07
    • 1970-01-01
    • 2019-07-18
    • 2020-05-10
    • 2015-05-01
    • 1970-01-01
    相关资源
    最近更新 更多