值类型与引用类型,值传递与引用传递

云玩家
• 阅读 521

值传递和引用传递


Go语言参数传递是传值还是传引用

一文整得明明白白~

Go全部都是值传递,不存在引用传递

值传递 是原始值copy出一份副本,然后传递; 引用传递 是直接传原始值的指针;

值传递并非不能修改原始值,当原始值是引用类型时(指针、map、slice、chan等这些),值传递就可以修改原始值 (值传递传的指针是原始值指针的副本,但两个指针都指向同一个地址)




值类型和引用类型


slice,map,channel,interface,func这5种数据类型 是引用类型,都(或者至少某个字段)是指针 (引用类型可以看作是对指针的封装)

(使用make函数创建的map,channel 其实都是一个指针,slice是其结构体SliceHeader的Data字段是指针)

// SliceHeader is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

int、float、bool、array、sturct 是值类型


string比较有争议,感觉是值类型,但有种说法也是引用类型


几种说法


说法1: “引用类型保存在堆上,值类型保存在栈上”?

这种说法是不准确的

首先不要纠结字面意思,Java中(byte、short、int、long、float、double)、字符型(char)、布尔型(boolean)这些基本类型数据直接保存在栈中,而类、接口、数组数据是保存在堆中,栈只是保存一个指向堆内存的指针。


一文理清 Go 引用的常见疑惑




浅拷贝与深拷贝


讨论值传递和引用传递时,其实就是看值类型变量和引用类型变量作为函数参数时,修改形参是否会影响到实参

在Go语言中除了五个引用类型,其他都是值类型:

  • slice
  • map
  • channel
  • interface
  • func()


引用类型作为参数时,称为浅拷贝,形参改变,实参数跟随变化.因为传递的是地址,形参和实参都指向同一块地址

值类型作为参数时,称为深拷贝,形参改变,实参不变,因为传递的是值的副本,形参会新开辟一块空间,与实参指向不同

如果希望值类型数据在修改形参时实参跟随变化,可以把参数设置为指针类型


Golang基础(闭包、值传递与引用传递)


需要注意的是,在 Go 语言中,闭包内部引用外部变量时,实际上是引用了外部变量的地址。因此,闭包的行为类似于引用传递,而不是像一般的函数参数那样的值传递。

一般认为这种类型才是真正意义上的闭包(即不传参数进去)

package main

func main() {
    i := 1
    func() {
        i = 2
        print(i)
    }()

    print(i)
}

实际上,我把这种情况也认为是闭包:

package main

func main() {
    i := 1
    func(i int) {
        i = 2
        print(i)
    }(i)

    print(i)
}

即传参进去,那里面的改动就不会影响外面,外面的改动也不会影响里面(在传进去那一刻就定住了~)


当然如果这样,里面的改动还是会改变外面的值

package main

func main() {
    i := 1
    func(k int) {
        i = 2
        print(i)
    }(i)

    print(i)
}

本文由mdnice多平台发布

点赞
收藏
评论区
推荐文章
九旬 九旬
2年前
函数参数传递
函数参数传递在JavaScript中函数传参,分为两种:基础类型(Number、String、Boolean..)引用类型(Object、Array、Funcion..)基础类型传参看下面的例子:js
Wesley13 Wesley13
3年前
Java对象的浅拷贝和深拷贝&&String类型的赋值
Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、方法传参或返回值时,会有值传递和引用(地址)传递的差别。浅拷贝(ShallowCopy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,
Wesley13 Wesley13
3年前
Java里的按值传递与引用传递
按值传递还是按引用传递这个在Java里面是经常被提起的问题,也有一些争论,似乎最后还有一个所谓的结论:“在Java里面参数传递都是按值传递”。事实上,这很容易让人迷惑,下面先分别看看什么是按值传递,什么是按引用传递,只要能正确理解,至于称作按什么传递就不是个大问题了。1:按值传递是什么指的是在方法调用时,传递的参
Wesley13 Wesley13
3年前
Java到底是引用传递还是值传递
前言前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢?public void test(){   String str  "hello";   change(str);   System.out.println(str);}private void change(String str){  
Wesley13 Wesley13
3年前
GO值类型与引用类型
值类型值类型包括基本数据类型,int,float,bool,string,以及数组和结构体(struct)。值类型变量声明后,不管是否已经赋值,编译器为其分配内存,此时该值存储于栈上。值类型的默认值:varaint//int类型默认值为0varbstring//string类型默认值为n
Stella981 Stella981
3年前
26 函数形参值回传问题——C++解决多个return的一般方法
0引言在使用数组和vector作为函数的参数进行参数传递并希望得到值的回传时,由于不知道怎么写数组函数形参的引用形式,一直采用vector的引用形式。但是,刚刚测试了一下,发现数组作为参数本身就是指针,根本不需要采用引用形式把值回传啊,把测试结果写下来。1 关于数组作为函数参数的值传递问题——数组和容器的对比  数组直接作为
Wesley13 Wesley13
3年前
Java只有值传递(Java值传递还是引用传递?)
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10830521.html(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fygj0930%2Fp%2F10830521.html)一:区分Java数据类型、变
Wesley13 Wesley13
3年前
Java面试中的值传递与引用传递
一、前言Java是值传递的,对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。对于对象型变量而言的,传递的是该对象地址的一个副本,,并不是原对象本身,这里也有人说是引用传递。由于副本的地址和原对象地址一致,因此对副本的值进行操作时,会同步改变原对象值。_但是一旦副本的地址被改变,副本的值的操作则不会影响原对象地址。(
Easter79 Easter79
3年前
Swift3.0 类和结构体的选择
结构体实例总是通过值传递,类实例总是通过引用传递先说说值类型和引用类型的区别值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝在Swift中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。引用类型在被赋予到一个变量、常
九路 九路
2年前
C++之值传递&指针传递&引用传递详解
C之值传递&指针传递&引用传递详解目录C之值传递&指针传递&引用传递详解(about:blankc%E4%B9%8B%E5%80%BC%E4%BC%A0%E9%80%92%E6%8C
小万哥 小万哥
1年前
灵活配置 Spring 集合:List、Set、Map、Properties 详解
使用标签的value属性配置原始数据类型和ref属性配置对象引用的方式来定义Bean配置文件。这两种情况都涉及将单一值传递给Bean。那么如果您想传递多个值,例如Java集合类型,如List、Set、Map和Properties怎么办?为了处理这种情况,S