Golang指针详解

要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。

指针介绍

我们知道变量是用来存储数据的,变量的本质是给存储数据的内存地址起了一个好记的别名。比如我们定义了一个变量 a := 10 ,这个时候可以直接通过 a 这个变量来读取内存中保存的 10 这个值。
在计算机底层 a 这个变量其实对应了一个内存地址。
指针也是一个变量,但它是一种特殊的变量,它存储的数据不是一个普通的值,而是另
一个变量的内存地址。

 

Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而无须拷贝数据。类型指针不能进行偏移和运算。

Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)*(根据地址取值)

指针地址和指针类型

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。
Go 语言中使用&字符放在变量前面对变量进行取地址操作。
Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:*int、*int64、*string等。
取变量指针的语法如下:
 ptr := &v    // v的类型为T
 v:代表被取地址的变量,类型为Tptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。

 

package mainimport "fmt"func main() {//在计算机底层 a 这个变量其实对应了一个内存地址var a int = 1fmt.Printf("a的值为%v a的类型为%T a的内存地址为%v\n",a,a,&a)// 指针也是一个变量,但它是一种特殊的变量,它存储的数据不是一个普通的值,而是另一个变量的内存地址var b int = 10c := &b //c指针变量   c的类型 *int(指针类型)fmt.Printf("b的值为%v b的类型为%T b的内存地址为%v\n",b,b,&b)fmt.Printf("c的值 %v c的类型%T ", c, c)//每一个变量都有自己的内存地址var f int = 20d := &ffmt.Printf("f的值 %v f的类型%T f的地址%p\n", f, f, &f)fmt.Printf("d的值 %v d的类型%T d的地址%p", d, d, &d)}

b := &a的图示: 

 指针取值

在对普通变量使用&操作符取地址后会获得这个变量的指针,然后可以对指针使用*操作,也就是指针取值,代码如下。

package mainimport "fmt"func main() {var e int = 30var d *int = &e// d := &e// *d :表示取出d这个变量对应的内存地址的值fmt.Println(d)fmt.Println(&e)fmt.Println(*d)  *d = 40			//改变d这个变量对应的内存地址的值(之前所赋的是e的内存地址的值)fmt.Println(e)}

总结: 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址
指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

   1.对变量进行取地址(&)操作,可以获得这个变量的指针变量。2.指针变量的值是指针地址。3.对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

指针传值示例

package mainimport "fmt"func fn1(x int) {x = 10// fmt.Println(x)
}func fn2(x *int) {*x = 40// fmt.Println(*x)
}func main() {var a = 5fn1(a)fmt.Println(a) //5;方法内的值并未改变a的内存地址,其原本的值所以没有变化fn2(&a)fmt.Println(a) //40 ;方法内传入的是指针类型,传入a改变了指针对应的内存地址,导致取指针的值变化了}

 new和make

在 Go 语言中 对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间 ,否
则我们的值就没办法存储。(触发panic)
而对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已
经默认分配好了内存空间。要分配内存,就引出来今天的 new 和 make。
Go 语言中 new 和 make 是内建的两个函数,主要用来分配内存。

make

make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。make函数的函数签名如下:

func make(t Type, size ...IntegerType) Type

make函数是无可替代的,我们在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。

 

package mainimport "fmt"func main() {// var teseDemo map[string]string  错误// teseDemo["卫宫士郎"] = "sabar"// fmt.Println(teseDemo)var teseDemo = make(map[string]string)teseDemo["远坂应"] = "archer"fmt.Println(teseDemo)var demo []intdemo = append(demo,1 ) // qppend是可以实现的,但是如果是直接demo[0] = 1fmt.Println(demo[0])// var demo1 []int// demo1[0] = 2 // 如果是直接demo[0] = 1,会因为没有分配内存而panic// fmt.Println(demo[0])var demo1 = make([]int, 4,4)demo1[1] = 12fmt.Print(demo1)//指针也是引用数据类型 不分配内存空间也会报错  错误// var a *int // *a = 100// fmt.Println(*a)
}

new

new是一个内置的函数,它的函数签名如下:

    func new(Type) *Type

其中,

    1.Type表示类型,new函数只接受一个参数,这个参数是一个类型2.*Type表示类型指针,new函数返回一个指向该类型内存地址的指针。

new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。举个例子:

	var a *inta = new(int)*a = 10fmt.Println(*a) //0var b = new(bool)fmt.Println(*b) //false

package mainimport "fmt"func main() {a := new(int)b := new(bool)fmt.Printf("%T\n", a) // *intfmt.Printf("%T\n", b) // *boolfmt.Println(*a)       // 0fmt.Println(*b)       // false
}

 

new与make的区别 

   1.二者都是用来做内存分配的。2.make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;3.而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/9034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在centos 7系统docker上构建mysql 5.7

一、VM上已经安装centos 7.9,且已完成docker的构建 二、安装mysql5.7 安装镜像:[rootlocalhost lll]# docker pull mysql:5.7 查看镜像[rootlocalhost lll]# docker images 根据镜像id构建mysql容器,且分配端口号[rootlocalhost lll]# dock…

JVM(Java Virtual Machine)

哥几个来学 JVM 啦~~ 目录 🌲一、JVM 执行流程( JVM 是如何运行的?) 🌳二、JVM 运行时数据区 🍦1. 堆(线程共享) 🍧2. Java 虚拟机栈(线程私有&#xff0…

LangChain||什么是LangChain? LangChain有什么用?

从Auto-GPT说起: Auto-GPT可以调用本地电脑工具处理复杂信息;Auto-GPT可以围绕目标查阅资 料、“独立思考”、及时反馈、并 及时调整下一步操作…Auto-GPT的诞生,创造了大家 对“将LLM作为智慧大脑来高效 处理综合复杂任务”的想象;首次尝试串联大语言模…

auto的相关知识

auto的相关知识 1、auto的概念介绍2、auto的用法2.1 与范围for搭配进行 遍历或修改数组2.2 当类型比较长时(写着麻烦),用auto替换 1、auto的概念介绍 int TestAuto() {return 10; }int main() {int a 10;auto b a; //auto用于 自动推导类…

关于我组件家庭服务器,挑选硬件设备的经历

目录 起因 升级——玩客云 原因 折腾日记 又升级——d2550工控主机 原因 折腾日记 又双升级——itx主机 原因 折腾日记 又双叒升级(目前再用的机器)——i9级x99平台e5v3主机 原因 折腾日记 心得 起因 起因大概在今年三月底四月初的时候&…

DuckDB全面挑战SQLite

概要 当我们想要在具有嵌入式数据库的本地环境中工作时,我们倾向于默认使用 SQLite。虽然大多数情况下这都很好,但这就像骑自行车去 100 公里之外:可能不是最好的选择。 这篇文章中将讨论以下要点: • DuckDB 简介:它…

uniapp WIFI上下班打卡

大纲 🥙 uniapp官网:uni-app官网 🥙 WIFI功能模块: 1、下载 wifi 插件 uni-WiFi 2、在 manifest.json 中 App权限配置中 配置权限 1. ACCESS_WIFI_STATE (访问权限状态) 2. CHANGE_WIFI_STATE&#xff…

SpringBoot整合ActiveMQ

ActiveMQ简单使用 JMS ActiveMQ 下载安装 https://activemq.apache.org/components/classic/download/解压缩文件。进入win64目录,双击运行activemq.bat文件,运行服务 将下面的网址输入到浏览器,用户名和密码都是admin SpringBoot整合Act…

外贸行业企业邮箱选择:安全好用的邮箱服务

随着全球化的发展,外贸行业在全球经济中越来越重要。作为一家从事对外贸易的企业,可靠、安全、易用的邮箱系统对于成功的国际交易至关重要。为您的企业选择正确的邮箱解决方案可能是一个挑战。为了使选择过程更加简化,我们在这里提供了一些提…

异构线程池的c++实现方案

概要 通常线程池是同质的,每个线程都可以执行任意的task(每个线程中的task顺序执行),如下图所示: 但本文所介绍的线程和task之间有绑定关系,如A task只能跑在A thread上(因此称为异构线程池&am…

2023云曦期中复现

目录 SIGNIN 新猫和老鼠 baby_sql SIGNIN 签到抓包 新猫和老鼠 看到反序列化 来分析一下 <?php //flag is in flag.php highlight_file(__FILE__); error_reporting(0);class mouse { public $v;public function __toString(){echo "Good. You caught the mouse:&…

Apache pulsar 技术系列-- 消息重推的几种方式

导语 Apache Pulsar 是一个多租户、高性能的服务间消息传输解决方案&#xff0c;支持多租户、低延时、读写分离、跨地域复制&#xff08;GEO replication&#xff09;、快速扩容、灵活容错等特性。在很多场景下&#xff0c;用户需要通过 MQ 实现消息的重新推送能力&#xff0c…

【算法】求欧拉函数(包括完整的证明以及代码模板,建议收藏)

求欧拉函数 前置知识 互质&#xff1a;互质是公约数只有1的两个整数&#xff0c;叫做互质整数。 欧拉函数定义 1 ∼ N − 1 1∼N-1 1∼N−1中与N互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ ( N ) \phi(N) ϕ(N)。 若在算数基本定理中&#xff0c; N p 1 a 1 p 2 a 2 .…

Clion开发STM32之OLED屏(软件i2c测试)

前言 本篇内容需要参考之前的文章: Clion开发stm32之微妙延迟(采用nop指令实现)Clion开发STM32之日志模块(参考RT-Thread)Clion开发STM32之I2C驱动(参考RT-Thread)Clion开发STM32之HAL库硬件I2C驱动OLED 使用的是0.96寸OLED屏 测试文件 /**********************************…

Python+Playwright自动化测试--标签页操作(tab)

1.简介 标签操作其实也是基于浏览器上下文&#xff08;BrowserContext&#xff09;进行操作的&#xff0c;而且宏哥在之前的BrowserContext也有提到过&#xff0c;但是有的童鞋或者小伙伴还是不清楚怎么操作&#xff0c;或者思路有点模糊&#xff0c;因此今天单独来对其进行讲…

nvidia-smi输出的结果代表什么

nvidia-smi(NVIDIA System Management Interface) 是基于nvml的gpu的系统管理接口,主要用于显卡的管理和状态监控。 nvidia-smi简称NVSMI&#xff0c;提供监控GPU使用情况和更改GPU状态的功能&#xff0c;是一个跨平台工具&#xff0c;支持所有标准的NVIDIA驱动程序支持的Linu…

【RS】基于规则的面向对象分类

ENVI使用最多的工具就是分类&#xff0c;这也是很多卫星影像的用途。在ENVI中有很多分类工具&#xff0c;如最基础的监督分类&#xff08;最大似然法、最小距离、支持向量机、随机森林&#xff09;、非监督分类&#xff08;K-means、IsoData&#xff09;&#xff0c;还有面向对…

13、PHP面向对象2(方法的访问控制、子类继承、常量)

1、类中的方法可以被定义为公有&#xff0c;私有或受保护。如果没有设置这些关键字&#xff0c;则该方法默认为公有。 public定义的方法&#xff0c;可以在类外使用。 protected定义的方法&#xff0c;只能在本类或子类的定义内使用。 private定义的方法&#xff0c;只能在本…

php学习当中遇到过哪些问题

PHP是一种流行的服务器端脚本语言&#xff0c;广泛用于Web应用程序和网站的开发。虽然PHP相对容易学习&#xff0c;但它仍然可能会给初学者带来一些问题和挑战。本文将探讨一些PHP初学者可能会遇到的常见问题&#xff0c;并提供一些解决方案。 理解PHP的基本语法和语义 PHP的语…

17网商品详情API:使用与数据解析方法

17网是一家知名的电商平台&#xff0c;提供了大量的商品选择。开发者可以通过17网的商品详情API来快速获取和展示商品的详细信息。 17网商品详情API简介 介绍17网商品详情API的作用和目的&#xff0c;解释为何使用该API可以实现丰富的商品详情展示功能。 获取API访问权限 说…