Go语言中的参数传递问题

一: 传递参数知识点汇总

  • 1: Go语言中函数之间的传递, 全部是值传递。
  • 2: Go语言中,普通的值传递, 将会重新拷贝一份内容, 传递到函数中。如果是指针传递, 会创建一个新的指针, 但是新的指针还是指向原来的内存空间。
  • 3: 如何选择变量传递还是指针传递
    • 不想变量被修改, 选择变量传递。想要被修改, 选择指针传递。
    • 变量特别大,考虑到节约空间, 选择指针传递。
  • 4: 什么时间触发创建副本?
    • 赋值的时候就会创建对象副本。
  • 5: 数组, 切片, 字典,在初始化的时候,如果有其他的变量, 全部拷贝一份新的变量副本。
  • 6: 循环遍历出来的变量也是原来变量的副本。
  • 7: 管道中发送对象, 这个对象也是副本。

二:传参测试

2.1: 测试Go语言的传参都是值传递(副本传递)

  • Go语言所有的值在赋值的时候, 都是先拷贝一份, 然后将拷贝的内容赋值给新的函数参数变量。
package main

import "fmt"

type People struct {
	Name string
	Age  int8
}

func passTest(p People) {
	fmt.Printf("传递到函数中的地址: %p\n", &p)
	// 传递到函数中的地址: 0xc000118018
}

func main() {
	myName := People{Name: "renshanwen", Age: 18}
	fmt.Printf("主函数初始化的变量地址: %p\n", &myName)
	// 主函数初始化的变量地址: 0xc000118000
	passTest(myName)
	fmt.Printf("不会影响到主函数的变量: %p\n", &myName)
	//不会影响到主函数的变量: 0xc000118000
}

2.2: 传递指针类型,也是复制指针, 只不过复制后的指针和之前的指针指向相同的内存空间

package main

import "fmt"

type People struct {
	Name string
	Age  int8
}

func passTest(p *People) {
	fmt.Printf("传递到函数中的指针变量的内存地址: %p,指针变量指向的内存地址:%p\n", &p, p)
	//传递到函数中的指针变量的内存地址: 0xc000012038,指针变量指向的内存地址:0xc000010030
	p.Name = "chengcheng" // 修改名字
}

func main() {
	myName := &People{Name: "renshanwen", Age: 18}
	fmt.Printf("主函数初始化指针变量的内存地址: %p, 指针变量指向的内存地址:%p\n", &myName, myName)
	//主函数初始化指针变量的内存地址: 0xc000012028, 指针变量指向的内存地址:0xc000010030
	passTest(myName)
	fmt.Printf("被修改后的名字: %s\n", myName.Name)
	//被修改后的名字: chengcheng
	fmt.Printf("主函数被影响后指针变量的内存地址: %p, 指针变量指向的内存地址:%p\n", &myName, myName)
	//主函数被影响后指针变量的内存地址: 0xc000012028, 指针变量指向的内存地址:0xc000010030

2.3:所有的赋值操作都会触发创建副本

package main

import "fmt"

func main() {
	myName := "renshanwen"
	var myName2 = myName
	fmt.Printf("myName的地址是%p\n", &myName)
	// myName的地址是0xc000096210
	fmt.Printf("myName2的地址是%p\n", &myName2)
	// myName2的地址是0xc000096220
}

2.4: 数组,切片,字典,在初始化的时候,如果有其他的变量, 全部拷贝一份新的变量副本

  • 数组测试
package main

import "fmt"

type people struct {
	Name string
	Age  int8
}

func main() {
	var myName = people{Name: "shanwen", Age: 23}
	fmt.Printf("myName的内存地址是%p\n", &myName)
	//myName的内存地址是0xc000010030
	testArray := [1]people{myName}
	fmt.Printf("数组内myName的内存地址是%p\n", &testArray[0])
	//数组内myName的内存地址是0xc000010048
}

2.5: 循环遍历出来的变量也是原来变量的副本

package main

import "fmt"

type People struct {
	Name string
	Age  int8
}

var thisPeople = People{Name: "renshanwen", Age: 35}

func main() {
	array := [...]People{thisPeople, thisPeople, thisPeople}
	fmt.Printf("数组中的首个变量所在内存中的地址是: %p, \n", &array[0])
	//数组中的首个变量所在内存中的地址是: 0xc0000b6000
	for i, item := range array {
		if i == 0 {
			fmt.Printf("遍历出的变量的内存地址是: %p, \n", &item)
			//遍历出的变量的内存地址是: 0xc0000a0018
		}
	}
}

2.6: 函数类型本质也是指针类型

package main

import "fmt"

func main() {
	f1 := func(i int) {}
	fmt.Printf("f1:\t\t %+v, \t\t内存地址:%p\n", f1, &f1)
	f2 := f1
	fmt.Printf("f2:\t\t %+v, \t\t内存地址:%p\n", f2, &f2)
}
// f1:              0x108e680,             内存地址:0xc000100018
// f2:              0x108e680,             内存地址:0xc000100028

2.7: 管道中发送对象, 这个对象也是副本

package main

import "fmt"

type Bird struct {
	Age  int
	Name string
}

var parrot1 = Bird{Age: 1, Name: "Blue"}

func main() {
	ch := make(chan Bird, 3)
	fmt.Printf("parrot1:\t\t %+v, \t\t内存地址:%p\n", parrot1, &parrot1)
	//parrot1:                 {Age:1 Name:Blue},             内存地址:0x1139250
	ch <- parrot1
	parrot1.Age = 2
	p := <-ch
	fmt.Printf("parrot%d:\t\t %+v, \t\t内存地址:%p\n", 2, p, &p)
	//parrot2:                 {Age:1 Name:Blue},             内存地址:0xc000010048
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奈何碎银没有几两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值