golang 函数 传入返回 slice/map/struct 本质

Go语言中所有的传参都是值传递(传值),都是一个副本,一个拷贝。且传参和赋值(=)的操作本质是一样的。

拷贝的内容分为  非引用类型 和 引用类型 两种类型

非引用类型:int、string、struct、array  这样就不能修改原内容数据。

引用类型:指针、map、slice、chan ,这样就可以修改原内容数据。

实例:

slice

package main

import (
	"fmt"
)


func test(input []int) []int{
	// input: 0x40c110->{address, 4, 4}
	fmt.Printf("Slice inside address: %p\n", &input)
	// input: 0x40c110->{address, 4, 4},但对address的修改影响到了val:0x40c0e0->{address, 4, 4}
	input[0] = -1
	input = append(input, 5)
	// input: 0x40c110->{address, 5, 8},但val仍然为0x40c0e0->{address, 4, 4}
	fmt.Println(input, len(input), cap(input))
	return input
}

func main() {
	// val:0x40c0e0->{address, 4, 4}
	val := []int{1, 2, 3, 4}
	fmt.Printf("Slice outside address: %p\n", &val)
	fmt.Println(val, len(val), cap(val))
	copyVal := test(val)
	fmt.Printf("Slice outside address: %p\n", &val)
	fmt.Println(val, len(val), cap(val))
	fmt.Printf("CopySlice address: %p\n", &copyVal)
	fmt.Println(copyVal, len(copyVal), cap(copyVal))
}

结果:

Slice outside address: 0x40c0e0
[1 2 3 4] 4 4
Slice inside address: 0x40c110
[-1 2 3 4 5] 5 8
Slice outside address: 0x40c0e0
[-1 2 3 4] 4 4
CopySlice address: 0x40c100
[-1 2 3 4 5] 5 8

结论:
传入的是slice三元组的值拷贝,返回的slice三元组值拷贝给外部变量

 

map

map的原理跟slice类似

package main

import "fmt"

func ChangeMap(input map[int]string) {
	input[2] = "changed"
	input[3] = "itsname"
	delete(input, 1)
	fmt.Printf("Inside input address: %p | %v\n", &input, input)
}

func main() {
	tmpmap := make(map[int]string)
	tmpmap[1] = "myname"
	tmpmap[2] = "yourname"
	fmt.Printf("Before change input address: %p | %v\n", &tmpmap, tmpmap)
	ChangeMap(tmpmap)
	fmt.Printf("After change input address: %p | %v\n", &tmpmap, tmpmap)
}

结果:

Before change input address: 0x40e128 | map[2:yourname 1:myname]
Inside input address: 0x40e148 | map[2:changed 3:itsname]
After change input address: 0x40e128 | map[2:changed 3:itsname]

 

struct

struct跟slice和map不同,它是非引用类型

package main

import "fmt"

func main() {
	p:=Person{"张三"}
	fmt.Printf("Before change p address: %p | %v\n", &p, p)
	modify(p)
	fmt.Printf("After change p address: %p | %v\n", &p, p)
}

type Person struct {
	Name string
}

 func modify(p Person) {
	 p.Name = "李四"
	fmt.Printf("Inside change p address: %p | %v\n", &p, p)
 }

结果:

Before change p address: 0xc000010200 | {张三}
Inside change p address: 0xc000010220 | {李四}
After change p address: 0xc000010200 | {张三}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值