Go语言 函数传递:值传递 和 虚假的 “引用传递”

前言

  • 其实从变量本身来说,go只有值传递,函数内的修改不会影响函数外。
  • 但有一种特例是指针,go可以传指针给函数,指针指向申请出来的实际内存,也就是保存元素的内存,
    这样在函数内的修改,可以影响到函数外。

分类看一下Go的函数传递:

  1. 基本数据类型int
  2. 类的实例
  3. 数组

基本类型(int)

值传递:

/* 引入单测包 */
import ("testing")

func TestSwap(t *testing.T) {
	x := 100
	y := 200
	swap(x, y)
	println("x:", x)
	println("y:", y)
}

/* 定义相互交换值的函数 */
func swap(x, y int) int {
   var temp int

   temp = x /* 保存 x 的值 */
   x = y    /* 将 y 值赋给 x */
   y = temp /* 将 temp 值赋给 y*/

   return temp;
}

结果:
个人理解:传给swap函数的相当于一个值,swap函数会把形参作为一个局部变量新建,局部变量的修改,不影响原值。
在这里插入图片描述

传递指针

func TestSwap(t *testing.T) {
	x := 100
	y := 200
	swapByPoint(&x, &y)
	println("x:", x)
	println("y:", y)
}

func swapByPoint(x, y *int) int {
	var temp int

	temp = *x /* 保存 x 的值 */
	*x = *y    /* 将 y 值赋给 x */
	*y = temp /* 将 temp 值赋给 y*/

	return temp;
}

结果:函数里面的修改,影响了原值
在这里插入图片描述
个人总结:当传递指针给函数时,类似于传递了内存地址给函数,函数会对这块内存做修改,所以会影响原值。

类的实例

值传递

import (
	"testing"
)

type Person struct{
	Name string
}

func TestChangeName(t *testing.T) {
	person := new(Person)
	person.Name = "aaaaaaa"

	changeName(*person)
	println("name:", person.Name)
}

func changeName(person Person) {
	person.Name = "bbbbbb"
}

结果:未改变原值
在这里插入图片描述

传递指针

func TestChangeName(t *testing.T) {
	person := new(Person)
	person.Name = "aaaaaaa"

	changeName(person)
	println("name:", person.Name)
}

func changeName(person *Person) {
	person.Name = "bbbbbb"
}

结果:影响了原值
在这里插入图片描述
小结:传变量只会被当做局部变量,传指针才会影响原值

Slice(切片)

先上结论:

func test1(slice_2 []int) {
	slice_2[1] = 6666               //函数外的slice确实有被修改
	slice_2 = append(slice_2, 8888) //函数外的不变
}

func test2(slice_2 *[]int) {        //这样才能用APPEND修改函数外的slice
	*slice_2 = append(*slice_2, 6666)
}

原因

  • slice(切片)是一个结构体,这个结构体中有一个指针,指向申请出来的实际内存。
  • 传递slice的时候,这个结构体是值传递的,传递完成后,内存中有两个“slice结构体”,它们引用同一块“slice数组”,第一个例子slice_2[1]是修改这个数组内容,所以里面改了外面能看到改动.
  • append这个函数则根据情况不同有两种工作方式,若你slice的cap足够,则直接修改其引用的数组区域并简单将len增加,并返回这个slice本身,即这时候h=append(h,…)之后,h还是引用原来的数组区域,只不过h的len增加了;若cap不够,则重新申请一块数组区域并将原来的数组内容拷贝过去后再进行追加元素操作,这时候append的返回的slice引用的是另一块内存了

来源链接:https://www.zhihu.com/question/47390706/answer/614694546

附上slice的结构:

// Slice结构体
struct    Slice
{    // must not move anything
    byte*    array;        // actual data
    uintgo    len;        // number of elements
    uintgo    cap;        // allocated number of elements
};

打印一下len和cap(容量),和原因中的解释是一样的:
在这里插入图片描述

总结:

  • Go只有值传递,但可以传递指针

参考文档:
https://www.zhihu.com/question/47390706

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值