猿问

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

我是 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) ......对我来说感觉不干。


任何帮助是极大的赞赏。


互换的青春
浏览 208回答 2
2回答

慕容708150

将映射视为包含指向底层映射结构的指针和大小的结构(可能还有其他东西,不确定)。例如,把它想象成: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 错误希望这一切都是有道理的,并有助于对混乱有所了解。

回首忆惘然

首先,回答你的问题:来自https://golang.org/pkg/builtin/#makemake 内置函数分配和初始化 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{}}}
随时随地看视频慕课网APP

相关分类

Go
我要回答