我是Go的新手,几天前正在寻找关于表单的教程,现在我已经熟悉了一点,我试图创建自己的错误处理程序,我可以使用我的所有结构,有点像抽象类,但我从我看到的教程中得到的例子让我有点难过。
这是我用来测试make
函数正在做什么的一个小例子。我有点想通过修补来解决这个问题,但我不明白实际做什么,以及为什么有必要。
type ErrorHandler struct {
Errors map[string]string
}
type Form struct {
ErrorHandler
}
func main() {
form := &Form{}
if true {
fmt.Printf("%p\n", &form.Errors)
} else {
form.Errors = make(map[string]string)
fmt.Printf("%p\n", &form.Errors)
}
}
在上面的示例中,我尝试将if语句从true更改为false,以查看内存地址是否根据是否使用make
函数而更改,并且两种情况都保持不变。我读了答案here,他说它的一个用途是“创建一个预先分配空间的地图” - 这对我来说并不重要,因为我是新手指针而且所有这些,但是“创建一个地图”部分让我觉得这就像在ErrorHandler结构中重新初始化Errors映射一样,它会将它分配给一个新的内存地址,是吗?但不,他们保持不变。
所以我尝试在地图中创建一个值,一旦没有 make函数,一次 with make函数。 if
条件给出了一个错误assignment to entry in nil map
和goroutine [running]
,else
语句打印出“haha”,这就是我设置的内容:
type ErrorHandler struct {
Errors map[string]string
}
type Form struct {
ErrorHandler
}
func main() {
form := &Form{}
if true {
form.Errors["blah"] = "haha"
fmt.Printf(form.Errors["blah"])
} else {
form.Errors = make(map[string]string)
form.Errors["blah"] = "haha"
fmt.Printf(form.Errors["blah"])
}
}
所以我看看make函数在做什么,但不完全正确。据我所知,如果我要将项目“推”到该地图中,我需要使用make
函数,但我不明白为什么它是必要的。为什么map[string]string
在我的结构中设置为nil,因为当我将其打印出来时,我看到“map []”而不是“nil”...这令人困惑。
有人可以解释一下吗?这个goroutine
怎么用?也许这就是我正在寻找的答案..之前从未使用过。
此外,由于我必须使用make
,是否有办法让它自动发生而不必将其放在每个方法的顶部?
例如,在我的ErrorHandler结构中,我有一个如下所示的方法:
func (this *ErrorHandler) HandleErr(err string) {
this.Errors = make(map[string]string)
this.Errors["Error"] = err
}
并在我的Form结构中我还有另一个方法来验证表单,但也使用方法顶部的`this.Errors = make(map [string] string)...感觉非干我
非常感谢任何帮助。
答案 0 :(得分:1)
将地图视为包含指向底层地图结构和大小的指针的结构(可能还有其他东西,不确定)。
例如,将其视为:
struct Map {
data *Entries
size int
}
make,根据传递给make的大小(如果有的话)分配条目的初始值
当你说:
form.Errors = make(map[string]string)
它说:
form.Errors = struct { data : malloc(sizeof(Entries)*capacity), size : 0 }
复制"数据"和"尺寸"表单中的变量。错误
实际字段" form.Errors"在内存中仍然是相同的位置,form的内部值。错误已经改变以匹配返回的内容。
因此,当您查看& form.Errors
时,地址不会改变至于推送到地图时的nil错误,你没有make
......
非女仆地图没有"数据"段,所以你得到一个零指针错误。
与做:
不同var i *int
*i = 5
也导致零错误
希望所有这些都有意义,并有助于解决混乱问题。
答案 1 :(得分:1)
首先,回答你的问题:
来自https://golang.org/pkg/builtin/#make
make内置函数分配并初始化slice,map或chan类型的对象(仅限)[...]
地图:初始分配是根据大小而不是 结果映射的长度为0.在这种情况下,可以省略大小 分配一个小的起始大小。
其次,您发布的代码中没有goroutines。
第三,让初始化地图,你可能不应该在每个HandleErr
调用中使用它,因为它会替换你当前的地图。我认为您想要的可能是NewErrorHandler
或NewForm
等初始化函数。这是你的结构的一种制作方式。例如:
func NewErrorHandler() ErrorHandler {
return ErrorHandler{make(map[string]string)}
}
最后为什么无法自动初始化地图?如果确实如此,您将无法控制地图的初始大小。如果您拥有关键任务代码并且希望它是快速或低内存并且知道大小,则可能很重要。
PS。还有另一种初始化地图的方法。如果要初始化空地图,可以写:map[string]string{}
。如果要创建具有初始值的地图:
map[string]string{
"a": "b",
"c": "d",
}
所以你可以写NewErrorHandler函数,如:
func NewErrorHandler() ErrorHandler {
return ErrorHandler{map[string]string{}}
}