了解命名返回类型的内存分配

时间:2016-05-30 04:02:53

标签: go

在下面的代码示例中,我可以假设我不需要分配返回的值吗?编译器是否总是会分配任何函数的命名返回值?

package main

import "fmt"

type Point struct {
    X, Y int
}

func MakePoint(x, y int) (pt Point) {
    pt.X = x
    pt.Y = y
    return
}

func main() {
    fmt.Printf("%v\n", MakePoint(1, 2))
}

另外,为什么我需要在函数末尾添加return语句?这是编译器的错误吗?

如果我决定返回一个指针:

func MakePoint(x, y int) (pt *Point) {

代码将编译但我收到运行时错误!为什么编译器让我相信不需要使用诸如pt = new(Point)之类的语句进行分配?这是编译器的另一个错误吗?很明显,我在Go中遗漏了关于内存分配的重要内容。

2 个答案:

答案 0 :(得分:1)

  

编译器是否总是会分配任何名为返回值的函数?

是的,绝对。

  

另外,为什么我需要在函数末尾添加return语句?这是编译器的错误吗?

因为返回值的函数必须以return语句结束。那就是语言规范所要求的,编译器强制执行。

  

为什么编译器让我相信不需要使用诸如pt = new(Point)之类的语句进行分配?

编译器为指针分配空间(即你返回的内容),但他不知道实际Point的内存应该在哪里。这是你的工作。

  

这是编译器的另一个错误吗?

没有。这样的东西是根本的。你在这种明显的代码中发现这样一个错误的几率基本上是零。

答案 1 :(得分:1)

  

在下面的代码示例中,我可以假设我不需要分配返回的值吗?编译器是否总是会分配任何函数的命名返回值?

我认为通过分配你并不意味着像这样分配:

a := func(1,2)

在这种情况下,编译器会将来自func的任何内容分配给。

但我认为你的意思是分配函数结果变量。

1. Yes, in this case you don't need to allocate as this is just a value.

2. Nope. It depends whether value is a pointer or a concrete type. In concrete type, you don't need to allocate in any case.
  

另外,为什么我需要在函数末尾添加return语句?这是编译器的错误吗?

现在按照标准返回部分:

  

如果函数的签名声明了结果参数,则函数体的语句列表必须以终止语句结束。

这个结果可以命名或不命名。

  

代码将编译但我收到运行时错误!为什么是   编译器让我相信一个语句如pt的分配   =新(点)是不是需要?这是编译器的另一个错误吗?

这不是一个错误。它正在发生,因为编译器并不关心指针指向哪种具体类型。它创建一个零值为零的指针。你需要照顾它。否则,你得到nil指针取消引用,因为你仍然没有将它指向任何具体类型。