美文网首页
一个Go函数返回值的拷贝问题

一个Go函数返回值的拷贝问题

作者: 自由编程 | 来源:发表于2020-02-26 07:51 被阅读0次

From - 自由编程


先提一个问题:一下两段函数,外部调用的时候,返回值会发生值拷贝么?
代码1

func r1() (rr1 []mnode) {
    rr1 = append(rr1, mnode{"h1", 1})
    rr1 = append(rr1, mnode{"h2", 2})
    return
}

代码2

func r2() (rr2 []*mnode) {
    rr2 = append(rr2, &mnode{"h1", 1})
    rr2 = append(rr2, &mnode{"h2", 2})
    return
}

用过C语言的同学,可能对代码1多少有点儿疑问,首先这个返回值是分配在堆上还是栈上?返回的时候,会拷贝整个数组么?
那么我们来分析一下。
大家都知道,C语言中,临时变量分配在栈中,而通过“new”动作分配出来的变量,则分配在堆中。而Go不同,Go编译器会自动把有必要的临时变量分配在堆中,这个把临时变量分配在堆中的过程,叫做“内存逃逸”。
下面我们来分析一下函数r1的逃逸过程,首先看test.go文件内容如下:

package main

import (
    "fmt"
)

type mnode struct {
    name string
    id   int
}

func r1() (rr1 []mnode) {
    rr1 = append(rr1, mnode{"h1", 1})
    rr1 = append(rr1, mnode{"h2", 2})
    return
}

func main() {
    mr1 := r1()
    fmt.Println(mr1)
}

我们通过下面的命令行来进行整个程序的逃逸分析。

go build -gcflags '-m -l' test.go 

输出

# command-line-arguments
./test.go:20:13: main ... argument does not escape
./test.go:20:13: mr1 escapes to heap

这里可以看出,变量mr1已经分配在堆上了
简单分析一下现在mr1和rr1内存分配情况,把rr1和mr1的地址打印出来看一下

package main

import (
    "fmt"
)

type mnode struct {
    name string
    id   int
}

func r1() (rr1 []mnode) {
    rr1 = append(rr1, mnode{"h1", 1})
    rr1 = append(rr1, mnode{"h2", 2})
    fmt.Printf("ptr-rr1: %p \n", &rr1)
    fmt.Printf("ptr-rr1[1]: %p \n", &(rr1[1]))

    return
}

func main() {
    mr1 := r1()
    fmt.Println("---------")
    fmt.Printf("ptr-mr1: %p \n", &mr1)
    fmt.Printf("ptr-mr1[1]: %p \n", &(mr1[1]))
}

然后执行 go run test.go,得到如下结果

$ go run test.go
ptr-rr1: 0xc00000c0a0 
ptr-rr1[1]: 0xc000064198 
---------
ptr-mr1: 0xc00000c080 
ptr-mr1[1]: 0xc000064198 

可以看到rr1和mr1的地址确实不同,但里面元素的地址

相关文章

  • C++ RVO

    刷知乎的时候看到这个问题,C++函数返回值拷贝问题?,觉得有趣,因此写了这篇博客。 函数如何返回值 函数返回值的传...

  • 一个Go函数返回值的拷贝问题

    From - 自由编程 先提一个问题:一下两段函数,外部调用的时候,返回值会发生值拷贝么?代码1 代码2 用过C语...

  • Go语言函数

    GO语言函数 GO语言是由函数组成的 没有返回值没有形参的函数 有返回值没有形参的函数 没有返回值有形参的函数 有...

  • 09-Go语言函数

    函数 Go语言函数格式func 函数名称(形参列表)(返回值列表){函数语句} Go语言函数的类型没有返回值没有形...

  • 第02天(函数、工程管理)_02

    06_多个返回值.go 07_有参有返回值.go 08_普通函数的调用流程.go 09_函数递归调用的流程.go ...

  • go 语言函数

    go 语言函数 函数定义格式: 不同形式的函数定义: 无返回值 有一个返回值 有多个返回值 参数传递, 传递一个函...

  • Go基础编程---函数

    函数(无返回值) 函数(有返回值) 函数(有参有返回值) 函数类型 Go中函数也是一种类型,可以通过type 定义...

  • go 语言基础--函数

    1、函数 和C语言类型,Go语言也有函数的概念,语法如下: 2 参数和返回值 2.1 返回值 go 语言可以返回零...

  • (二十四)拷贝构造函数

    定义 拷贝构造函数是一种特殊的构造函数 函数名是类名,没有返回值,没有返回值,参数形式固定 以一个对象b为蓝本,创...

  • 01 深入理解函数作用域&闭包

    演示代码 函数定义式优先于对象直接量 函数返回变量值拷贝 函数返回值的本质 当函数返回值为非函数时,返回的为简单对...

网友评论

      本文标题:一个Go函数返回值的拷贝问题

      本文链接:https://www.haomeiwen.com/subject/lvfxchtx.html