我发现切片图功能和通道经常一起作为 参考类型 提及。但是我注意到,切片的东西不会表现出参考行为,就像它们会过时一样:
var s []int
//must update slice value
s = append(s, ...)
要么
//must use pointer if we want to expose the change
func foo(s *[]int) error
//or change the function signature to return it like _append_
func foo(s []int) (r slice, err error)
通常,我会通过牢记切片描述符实现的内部组件来理解这一点:切片值可以视为len,cap和data指针的结构。
但是地图值永远不需要像
m := make(map[string]int)
...
// don't know how to express with insertion, but you know what i mean.
m = delete(m, "well")
为什么?映射值仅仅是指向映射描述符的指针吗?如果是这样,为什么还不这样做呢?
在Go中,没有像C ++中那样的引用类型。在Go中,一切都是通过价值传递的。当在Go中使用术语“引用类型”时,它表示引用它们应表示的数据的类型(通过指针)。
切片是小型的,类似于结构的数据结构,由类型表示reflect.SliceHeader
:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
它包含一个指向基础数组(SliceHeader.Data
字段)中切片的第一个元素的指针。该结构很小,可以作为值有效传递,而无需传递其地址(并取消引用以间接访问其任何字段)。切片的元素不存储在切片头中,而是存储在头的存储区域之外的数组中。这意味着修改“指向”元素将修改原始切片的元素。
当您将(大于0)个元素追加到切片时,Len
标头中的字段必须更改,因此描述带有其他元素的切片的新切片必须不同于追加之前的切片,这就是为什么您需要分配内置append()
函数的返回值。(其他值也可能会更改,但Len
一定要更改。)
映射被实现为指向该runtime.hmap
结构的指针:
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
如您所见,这是一个比切片头复杂得多的数据结构,并且要大得多,将其作为值传递将是无效的。
从映射添加/删除元素(键-值对)存储在此结构的字段所引用的存储桶中,但是由于映射在后台作为指针处理,因此您无需分配此类操作的结果。
为了完整起见,通道也被实现为指针,指向runtime
包的hchan
类型:
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}
这又是一个“胖”结构,其处理方式类似于地图值。
我发现切片映射函数和通道经常作为引用类型一起提到。然而,我注意到有些东西表现出非引用行为,就像它们会过时一样: 或 通常我是通过记住slice描述器实现的内部组件来理解这一点的:slice值可以被看作len、cap和数据指针的结构。 但是地图值永远不需要像 为什么?映射值只是映射描述符的指针吗?如果是这样,为什么不这样做呢?
问题内容: 在非官方指南中有一个占位符答案,带有指向(对我而言)似乎无关的文章的链接。 我使用XJC生成我的JAXB类,尽管它们大多数按预期相互映射,但有些元素被映射到。这对于带有循环的图最令人讨厌,其中有时Foo元素的父节点将是,而它本身没有父属性,从而中断了循环。 我可以想到各种解决方法,但是如果有人可以向我解释这种行为,那就更好了。为什么JAXB有时将元素映射到而不是Foo? 问题答案: 在
我只想用hadoop mapreduce来排序我的日志行。我将该行的所有字段作为输出键,并将输出值设置为null。但是当运行时,在第行出现空指针异常 所以为什么hadoop映射的输出值不能为空?为什么hadoop reduce的输出值可以(我测试过)?
问题内容: 在玩Go代码时,我发现映射值不可寻址。例如, 产生错误 mapaddressable.go:7:无法获取mymap [1]的地址 而代码, 工作完美。 为什么会这样呢?为什么Go开发人员选择使某些值无法解决?这是语言的缺点还是功能? 编辑 :来自C ++背景,我不习惯于这种流行趋势。例如,以下代码可以正常工作: 如果有人可以指出为什么在Go中无法实现(或故意没有实现)相同的 寻址 能力
多值映射不存在的原因是什么?会不会是什么过滤?对于未知数量的参数,有什么可供选择的? 更新是由于泽西+Spring的一个特殊性。在这个答案中可以找到解决方法。
我想通过数组映射,但我得到一个错误:TypeError: locationAddress.map不是一个函数 我是新来的反应和反应钩。我一直试图简化数组,但运气不好。知道为什么这不起作用吗? 编辑:到目前为止,我尝试了答案中的所有更改,但错误仍然存在。我包括了更多的代码和包。json文件。我尝试停用一些函数,如useEffect,现在只有在我尝试键入要映射的输入字段时才会显示错误。 找到解决方案: