go语言的参数传递

对于一门语言,在函数传参时,存在两种方式,一种是值传递,一种是引用传递,那么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得到的结果是一个指针类型,这样才符合我们前边的推论.

相关推荐