go语言的参数传递

暮雨 · · 2876 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

对于一门语言,在函数传参时,存在两种方式,一种是值传递,一种是引用传递,那么go语言是怎么进行参数传递的
值传递是传递的变量的副本,引用传递指的是传递该变量的地址,在值传递过程中,函数对函数形参数的修改,不会导致实参的修改,而引用传参,对形参的修改,会导致该实参的修改,这是过去我们在其它语言中的一些认知,那么go语言会颠覆我们过去的认知,使用了一种新的方式.

  • demo1
package main

import (
    "fmt"
)

func main() {
    a := 10
    fmt.Println("实参的地址",&a)
    update(a)
    fmt.Println(a)
}

func update(b int) {
    b = 1
    fmt.Println("形参的地址",&b)
}
// 运行结果
实参的地址 0x10414020
形参的地址 0x10414024
10

由该demo,我们可以得出,在值传递时,形参是实参的一个copy

  • demo2
package main

import (
    "fmt"
)

func main() {
    a := 10
    p := &a
    fmt.Println("指针的地址",&p)
    fmt.Println("实参的地址",&a)
    update(p)
    fmt.Println(a)
}

func update(b *int) {
    *b = 1
    fmt.Println("形参的指针地址",&b)
    fmt.Println("形参的地址",b)
}

// 运行结果
指针的地址 0x1040c128
实参的地址 0x10414020
形参的指针地址 0x1040c138
形参的地址 0x10414020
1

发现在指针传递时,实参和形参的指针地址不一值,但其指向地址是一样的,由此可以得出,在指针传递时,go语言,传递的是指针的copy,是一种值传递的方式

  • demo3

再来看一个复杂的,结构体

package main

import (
    "fmt"
)

type Person struct {
    Name string
}

func main() {
    p := Person{"zhang san"}
    fmt.Printf("实参的地址:%p\n", &p)
    update(p)
    fmt.Println(p)
}

func update(p Person) {
    p.Name = "li si"
    fmt.Printf("形参的地址:%p\n", &p)
}
// 输出结果
实参的地址:0x1040c128
形参的地址:0x1040c138
{zhang san}
  • demo4

指针传递

package main

import (
    "fmt"
)

type Person struct {
    Name string
}

func main() {
    p := Person{"zhang san"}
    pr := &p
    fmt.Printf("实参的指针地址:%p\n", &pr)
    fmt.Printf("实参的地址:%p\n", &p)
    update(pr)
    fmt.Println(p)
}

func update(p *Person) {
    p.Name = "li si"
    fmt.Printf("形参的指针地址:%p\n", &p)
    fmt.Printf("形参的地址:%p\n", p)
}

// 运行结果
实参的指针地址:0x1040c130
实参的地址:0x1040c128
形参的指针地址:0x1040c140
形参的地址:0x1040c128
{li si}

由demo3和demo4的对比,分析可以得到,在值传递时,传递的是值的实参的副本,指针传递时,传递的是指针的副本,其都指向实参的地址

通过以上实验,可以得出,无论是值传递和指针传递,都传递的是对应的一个副本.在go语言中,只有一个值传递.

  • demo5
package main

import (
    "fmt"
)

type Person struct {
    Name string
}

func main() {
    persons:=make(map[string]int)
    persons["张三"]=19

    //mp:=&persons

    fmt.Printf("原始map的内存地址是:%p\n",&persons)
    update(persons)
    fmt.Println("map值被修改了,新值为:",persons)
}

func update(p map[string]int) {
    fmt.Printf("函数里接收到map的内存地址是:%p\n",&p)
    p["张三"]=20
}
// 运行结果
原始map的内存地址是:0x1040c128
函数里接收到map的内存地址是:0x1040c138
map值被修改了,新值为: map[张三:20]

该demo运行结果和我们前面的推论结果不一致,在代码中有一个特殊的make,因此我们有理由怀疑,make得到的结果是一个指针类型,这样才符合我们前边的推论.


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:暮雨

查看原文:go语言的参数传递

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2876 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传