据我所知,Golang中的类型slice和map方式在很多方面都很相似.它们都是reference(或container)类型.就抽象数据类型而言,它们分别表示数组和关联数组.
但是,他们的行为却截然不同.
var s []int
var m map[int]int
Run Code Online (Sandbox Code Playgroud)
虽然我们可以立即使用声明的切片(追加新项目或重新绑定它),但我们无法对新声明的地图执行任何操作.我们必须调用make函数并显式初始化一个映射.因此,如果某个struct包含一个map,我们必须为struct编写一个构造函数.
所以,问题是为什么在声明地图时不可能添加一些合成糖并分配和初始化内存.
我做了谷歌的问题,学会了一个新的词"avtovivification",但仍然没有看到原因.
补充:我不是在讨论struct literal.是的,您可以通过提供诸如的值来显式初始化地图m := map[int]int{1: 1}.但是,如果你有一些结构:
package main
import (
"fmt"
)
type SomeStruct struct {
someField map[int]int
someField2 []int
}
func main() {
s := SomeStruct{}
s.someField2 = append(s.someField2, -1) // OK
s.someField[0] = -1 // panic: assignment to entry in nil map
fmt.Println(s)
}
Run Code Online (Sandbox Code Playgroud)
不能立即使用结构(所有字段都使用默认值).必须创建一个构造函数SomeStruct,必须显式初始化一个映射.
我发现切片图功能和通道经常一起作为参考类型提及。但是我注意到,切片的东西不会表现出任何参考行为,因为它们可能会过时:
var s []int
//must update slice value
s = append(s, ...)
Run Code Online (Sandbox Code Playgroud)
要么
//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)
Run Code Online (Sandbox Code Playgroud)
通常,我通过牢记切片描述符实现的内部组件来理解这一点:切片值可以视为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")
Run Code Online (Sandbox Code Playgroud)
为什么?映射值仅仅是指向映射描述符的指针吗?如果是这样,为什么还不这样做呢?
我想知道是否可以sync.Pool与数组或切片一起使用?例如,sync.Pool每秒处理数万个请求时是否可以加快以下速度?这个例子只是为了更好地理解 Go。
// Handler that uses GenerateArray
func ok(w http.ResponseWriter, r *http.Request) {
var res [100000]uint64
fibonacci.GenerateArray(&res)
fmt.Fprintf(w, "OK")
}
func GenerateArray(data *[100000]uint64) {
var start uint16 = 1000
var counter uint32
for start >= 1 {
var num = 90
var n1, n2, temp uint64 = 0, 1, 0
for num >= 1 {
temp = n2
n1, n2 = temp, n1+n2
data[counter] = n2
counter++
num--
}
start--
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:这是 Icza 建议的切片版本。希望我在学习时做得对。 …
func main() {
slice := make([]int, 10, 10)
slice[0] = 0
slice[1] = 1
slice1 := slice
slice1[0] = 10000
fmt.Println(slice)
slice1 = append(slice1, 100)
slice1[0] = 20000
fmt.Println(slice)
}
Run Code Online (Sandbox Code Playgroud)
结果:
[10000 1 0 0 0 0 0 0 0 0]
[10000 1 0 0 0 0 0 0 0 0]
在我的理解中,slice是一个指针,slice1并slice指向同一个数组,第一个输出也证明了这一点.但是slice,在追加行动改变后,为什么价值保持不变slice1?
需要重新审视,因为我做的某件事在这里出错了。我尝试将状态附加到切片,但不起作用
我也尝试使用取消引用
type ServerStatuses []ServerStatus
statuses := new(ServerStatuses)
status := &ServerStatus{
time: time,
available: available,
url: url,
}
statuses = append(statuses, *status)
Run Code Online (Sandbox Code Playgroud)
append在这种情况下将不起作用,尽管状态是一个切片。
我不明白最后一步结果,我认为“复制”使用值。如果您能解释一下,我将不胜感激。
type Vertex struct {
X []int
Y []int
}
func main() {
var v Vertex
x := []int{1, 2}
y := []int{3, 4}
v.X = x
v.Y = y
fmt.Println(v)
x[0] = 5
fmt.Println(v)
copy(v.X, x)
copy(v.Y, y)
fmt.Println(v)
x[0] = 6
fmt.Println(v)
}
Run Code Online (Sandbox Code Playgroud)
结果:
{[1 2] [3 4]}
{[5 2] [3 4]}
{[5 2] [3 4]}
{[6 2] [3 4]}
Run Code Online (Sandbox Code Playgroud)