为了账号安全,请及时绑定邮箱和手机立即绑定

在这种情况下,“make”函数对地图有什么作用

在这种情况下,“make”函数对地图有什么作用

Go
互换的青春 2021-12-07 15:11:58
我是 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函数而发生变化,并且在两种情况下它都保持不变。我在这里阅读了答案,他说它的一个用途是“创建一个预先分配了空间的地图”——老实说这对我来说意义不大,因为我是指针和所有这些的新手,但是“创建一个地图“部分让我认为这就像在 ErrorHandler 结构中重新初始化 Errors 映射,这会将它分配给一个新的内存地址,是吗?但是不,它们保持不变。所以我尝试在地图中创建一个值,一次没有使用 make 函数,一次使用make 函数。该if条件给了我一个错误说assignment to entry in nil map和goroutine [running],和else语句打印“哈哈”,这是我将它设置为: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) ......对我来说感觉不干。任何帮助是极大的赞赏。
查看完整描述

2 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

将映射视为包含指向底层映射结构的指针和大小的结构(可能还有其他东西,不确定)。


例如,把它想象成:


struct Map {

  data *Entries

  size int

}

make,根据传递给make的大小分配Entries的初始值(如果有的话)


当你说:


form.Errors = make(map[string]string)

就像在说:


form.Errors = struct { data : malloc(sizeof(Entries)*capacity), size : 0 }

它将“数据”和“大小”变量复制到您的表单中。错误


实际字段“form.Errors”仍然在内存中的相同位置,form.Errors 的内部值已更改以匹配 make 返回的内容。


所以,当你查看 &form.Errors 时,地址不会改变


至于推送到地图时的 nil 错误,您没有make...


一个 un-maid map 还没有“数据”段,所以你会得到一个 nil 指针错误。


不像做:


var i *int

*i = 5

也会导致 nil 错误


希望这一切都是有道理的,并有助于对混乱有所了解。


查看完整回答
反对 回复 2021-12-07
?
回首忆惘然

TA贡献1847条经验 获得超11个赞

首先,回答你的问题:


来自https://golang.org/pkg/builtin/#make


make 内置函数分配和初始化 slice、map 或 chan(仅)类型的对象 [...]


映射:根据大小进行初始分配,但结果映射的长度为 0。大小可以省略,在这种情况下,分配的起始大小较小。


其次,您发布的代码中没有 goroutines。


第三,make 会初始化地图,您可能不应该在每次HandleErr调用中都使用它,因为它会替换您当前的地图。我认为你想要的可能是一个初始化函数,比如NewErrorHandleror NewForm。它有点适合您的结构。例如:


func NewErrorHandler() ErrorHandler {

    return ErrorHandler{make(map[string]string)}

}

最后为什么不能自动初始化地图?如果是这样,您将无法控制地图的初始大小。如果您有关键任务代码并且您希望它快速或低内存并且知道大小,这可能很重要。


附注。还有一种初始化地图的替代方法。如果你想初始化一个空的地图,你可以这样写:map[string]string{}。如果要创建具有初始值的地图:


map[string]string{

    "a": "b",

    "c": "d",

}

所以你可以编写你的 NewErrorHandler 函数,如:


func NewErrorHandler() ErrorHandler {

    return ErrorHandler{map[string]string{}}

}


查看完整回答
反对 回复 2021-12-07
  • 2 回答
  • 0 关注
  • 207 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信