Golang - 指针与引用

? Golang有指针 , 那么一切数据都是值传递吗 ? 都需要用户进行指针传递吗, 其实不然, 对于Go语言, 虽然有指针, 但是其也有引用传递. 是不是很绕, 因为引用传递就是指针传递哇 . 我们继续解释.

概念

在Go语言中,对于布尔变量数值类型字符串类型数组 以及struct都是按照值传递的:值在传递给函数或者方法时会被复制一份,然后方法或函数使用的是复制的这份值,也就不会对原值产生什么影响。一般情况下,对于布尔变量或数值类型或字符串类型的按值传递是非常廉价的,Go语言编译器会在传递过程中进行安全优化。

对于大字符串是这样,对于数组进行值传递也是如此。为了解决可能产生的巨大代价,Go语言使用数组切片来代替数组的使用。传递一个切片的代价跟传递字符串差不多,无论该切片的长度或容量是多大。对切片进行复制修改操作也不会像字符串那样需要创建新的切片,因为切片是可变的,属于引用类型

因此以下就是重点 :

语言中的值传递类型有:基本数据类型,数组 , struct

特点:变量直接存储值,内存通常在栈中分配,栈在函数调用完会被释放 , 在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 , 所以他最大的好处就是不怕多线程安全性问题. 但是浪费内存

Go语言中的引用类型有:映射(map),数组切片(slice),通道(chan),接口(interface) 与 函数(func)。

他的变量默认就是指针变量, 所以不需要做&取地址. 你要是花里胡哨我也无语.

特点:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配,通过GC回收。所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。引用注定多个线程中共享一个, 容易出现多线程问题,

就以引用传递和值传递区分 , 切记别被下面带绕了,这种话分析层面不同就不一样

其实在go语言中,只存在值传递,本质上,我们可以理解函数的传递都是值传递,只不过引用类型传递的是一个指向底层数据的指针,所以我们在操作的时候,可以修改共享的底层数据的值,进而影响到所有引用到这个共享底层数据的变量。

两大操作符

操作符& : 是返回该变量的内存地址。
操作符* :是返回该指针指向的变量的值,其实就是解除变量的指针引用,返回该变量的值.

空指针 :

当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

认识指针

指针这个玩意, Java里没有,其实Java里确实有指针,我们无时无刻在使用,下面我举一个例子

type People struct {
    name string
    sex  string
    age  int
}

func main() {

    var pp *People

    // 1. 返回一个对象
    person1 := People{"zhangsan", "man", 25}

    fmt.Println(person1)

    pp=&person1

    // 2. 直接实例化一个空对象 , 返回一个指针对象
    person2 := new(People)

    //
    pp=person2
    fmt.Println(*pp)

    // 2.返回一个指针对象
    person3 := &People{"wangwu", "man", 25}

    pp=person3

    fmt.Println(*person3)

    fmt.Println(*pp)
}

输出

{zhangsan man 25}
{  0}
{wangwu man 25}
{wangwu man 25}

这里告诉大家一个技巧就是 fmt.Println() 输出中如果首位是 & ,那么它一定是一个指针类型的数据 . 但是对于默认的引用对象,不一定了,,,

函数传参是值传递 - 但是引用类型是指针传递, 不需要用户写*申明指针类型

举个例子 我们拿数组为例子 , 举例指针的用处

func main() {

    // 申明数组类型
    arr := [3]int{1, 2, 3}

    // 原数组
    fmt.Printf("指针 : %p , 数据 : %v\n", &arr,arr)

    // 地址传递
    printSlice(&arr)

    // 值传递
    printSlices(arr)

    // 原数组
    fmt.Printf("指针 : %p , 数据 : %v\n", &arr,arr)

}

func printSlice(arr *[3]int) {
    // 修改数据
    arr[0] = 5
    fmt.Printf("指针 : %p , 数据 : %v\n", arr, *arr)
}
func printSlices(arr [3]int) {
    // 修改数据
    arr[0] = 4
    fmt.Printf("指针 : %p , 数据 : %v\n", &arr, arr)
}

输出

指针 : 0xc000052140 , 数据 : [1 2 3]
指针 : 0xc000052140 , 数据 : [5 2 3]
指针 : 0xc0000521c0 , 数据 : [4 2 3]
指针 : 0xc000052140 , 数据 : [5 2 3]

参考 https://www.cnblogs.com/52php/p/6727082.html

原文地址:https://www.cnblogs.com/anthony-dong/p/12249394.html

时间: 2024-10-17 10:20:58

Golang - 指针与引用的相关文章

Golang指针

学过C语言的老司机都知道,指针就是一个变量,用于存储另一个变量的内存地址. 那么什么是变量呢?在现代计算机体系结构中所有的需要执行的信息代码都需要存储在内存中,为了管理存储在内存的数据,内存是划分为不同的区域的,不同区域都用内存地址来标识.一个典型的内存地址是个16进制的8位数(一个字节)比如0xAFFFF(这是一个内存地址的十六进制表示). 要访问数据,我们需要知道它的存储地址.我们可以跟踪存储与我们的程序相关的数据的所有内存地址.但是要记住这些内存地址,非常费劲,怎么办呢? 于是我们引入了变

从Java到C++——指针与引用

C++即有指针又有引用,而且很多时候具有相似的功能,常常容易让人混淆,着实让人头痛.用两句通俗的话说明两者本质的含意:引用就是一个变量或对象的别名(引用的本质是一个对象):指针是一个段内存空间的地址(指向存储一个变量值的空间或一个对象的空间):如下图所示:     C++中的引用与指针 引用 引用是为变量或对象起的另外一个别名,定义形式:T& v;  T为类型,v为变量名.使用引用时,注意以下几点: 1.引用在创建的时候必须被初始化(指针可以在任何时候赋值) 2.一旦引用初始化后,就不能改变引用

C++指针参数引用

粘个代码占位置,以后有时间把指针函数,函数指针都补上 #include <iostream>using namespace std;void freePtr1(int* p1){    /*未释放内存前 ->  p1 Address : 0012FDDC  p1 value : 003429B8,     在这里,p1它也是一个变量,既然是一个变量,     那么它将会以值的传递,把外部变量p1传到栈内,在栈内产生一个地址:0012FDDC,     当然,它的值不会变仍然是指向堆地址:

c++指针与引用问题

本来是回答问题的,到这里做个笔记 *&L是指针的引用,实参是个指针.所以L是实参指针的别名,对别名L的修改,等于对实参的修改.*L是传值,你无法改变传过来的实参指针变量的值程序代码: #include<iostream>using namespace std;void foo(int*p);int main(){    int a=5;    int *b=&a;    printf("%d %d\n",b,*b);    foo(b);    printf

(C/C++)区别:数组与指针,指针与引用

1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存.指针远比数组灵活,但也更危险. 数组和指针特点的简单比较: 数组 指针 保存数据 保存地址 直接访问数据 间接访问数据,先取得指针的内容,然后以它为地址取得数据 用于存储数目固定且类型相同的数据 通常用于动态数据结构 编译器自动分配和删除

指针与引用同与不同

一.指针与引用的定义及特性 A.引用(reference):为一个已经存在的对象另起一个名字.它有以下特性: 1.必须初始化 2.始终指向同一个对象,不能更改其所指向的对象 3.自身只是一个别名,不占内存,对其取地址是其指向对象的地址 4.常量引用的意义在于不能通过引用来修改其所指向对象的值,其所指对象可以不是常量 int tempA = 2; const int ctempA = 2; /*1.正常使用*/ int &refA = tempA; const int &crefA = ct

[C/C++基础--笔试突击] 7.指针与引用

概述: 比较抽象的但又很有用的东西 0.0 void*指针:可以保存任何类型对象的地址. 指向指针的指针 函数指针 7.1 指针 一个有效的指针必然是一下三种状态之一: 1)保存一个特定对象的地址: 2)指向某个对象后面的另一个对象 3)0值. 若指针保存0值,表明它不指向任何对象.未初始化的指针是无效的,直到给该指针赋值后,才可使用. 注:*p++和(*p)++不等价,单目运算符*的优先级比++高,故*p++先完成取值操作,然后对指针地址执行++操作,而(*p)++是首先执行屈指操作,然后对该

指针和引用的区别(More Effective c++ )

指针与引用看上去完全不同(指针用操作符"*"和"->",引用使用操作符". " ),但 是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候 使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能使用指向空值的引用.一个引用必须总是 指向某些 对象 .因此如果你使用一个变量并让它指向一个对象, 但是该变量在某些时候也可能不指向 任何 对象,这时你应该把变量声明为指针,因为这样 你可以赋空值给该变量.相

指针与引用的区别

相同点: 1.     指针与引用都是地址的概念.指针指向一块内存,指针的内容是所指向内存的地址:而引用则是某块内存的别名. 2.     引用在语言内部用指针实现. 3.     一般把引用理解为指针,不会犯严重语义错误.引用操作可以看做是受限的指针(仅允许取内容操作). 不同点: 1.     指针逻辑上是独立的,可以改变指针的内容,也可以改变指针指向的内存中的内容:而引用只是一个别名,在逻辑上不上独立的,它的存在具有依附性,必须在声明时就初始化,而且引用的对象在整个生命周期中时不能被改变的