Go语言基础之指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。

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

Go语言中的指针

任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

比如,“永远不要高估自己”这句话是我的座右铭,我想把它写入程序中,程序一启动这句话是要加载到内存(假设内存地址0x123456),我在程序中把这段话赋值给变量A,把内存地址赋值给变量B。这时候变量B就是一个指针变量。通过变量A和变量B都能找到我的座右铭。

Go语言中的指针不能进行偏移和运算,因此Go语言中的指针操作非常简单,我们只需要记住两个符号:&(取地址)和*(根据地址取值)。

指针地址和指针类型

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:*int、*int64、*string等。

取变量指针的语法如下:

ptr := &v    // v的类型为T

其中:

  • v:代表被取地址的变量,类型为T
  • ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。

举个例子:

func main() {a := 10b := &afmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*intfmt.Println(&b)                    // 0xc00000e018
}

我们来看一下b := &a的图示:
在这里插入图片描述

指针取值

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

func main() {//指针取值a := 10b := &a // 取变量a的地址,将指针保存到b中fmt.Printf("type of b:%T\n", b)c := *b // 指针取值(根据指针去内存取值)fmt.Printf("type of c:%T\n", c)fmt.Printf("value of c:%v\n", c)
}

输出如下:

type of b:*int
type of c:int
value of c:10

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

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

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

指针传值示例:

func modify1(x int) {x = 100
}func modify2(x *int) {*x = 100
}func main() {a := 10modify1(a)fmt.Println(a) // 10modify2(&a)fmt.Println(a) // 100
}

new和make

我们先来看一个例子:

func main() {var a *int*a = 100fmt.Println(*a)var b map[string]intb["沙河娜扎"] = 100fmt.Println(b)
}

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

new

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

func new(Type) *Type

其中,

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

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

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
}	

本节开始的示例代码中var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。应该按照如下方式使用内置的new函数对a进行初始化之后就可以正常对其赋值了:

func main() {var a *inta = new(int)*a = 10fmt.Println(*a)
}
make

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

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

make函数是无可替代的,我们在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。这个我们在上一章中都有说明,关于channel我们会在后续的章节详细说明。

本节开始的示例中var b map[string]int只是声明变量b是一个map类型的变量,需要像下面的示例代码一样使用make函数进行初始化操作之后,才能对其进行键值对赋值:

func main() {var b map[string]intb = make(map[string]int, 10)b["沙河娜扎"] = 100fmt.Println(b)
}
new与make的区别
  1. 二者都是用来做内存分配的。
  2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
  3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

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

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

相关文章

微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介: uniapp开发的小程序中使用 本来使用websocket,后端同事使用了stomp协议,导致前端也需要对应修改。 如何使用 在static/js中新建stomp.js和websocket.js,然后在需要使用的页面引入监听代码发送代码即可 代码如下&#x…

腾讯云-对象存储服务(COS)的使用总结

简介 对象存储(Cloud Object Storage,COS)是腾讯云提供的一种存储海量文件的分布式存储服务,具有高扩展性、低成本、可靠安全等优点。通过控制台、API、SDK 和工具等多样化方式,用户可简单、快速地接入 COS&#xff0…

论文笔记:从不平衡数据流中学习的综述: 分类、挑战、实证研究和可重复的实验框架

0 摘要 论文:A survey on learning from imbalanced data streams: taxonomy, challenges, empirical study, and reproducible experimental framework 发表:2023年发表在Machine Learning上。 源代码:https://github.com/canoalberto/imba…

Python Qt(七)Listview

源代码: # -*- coding: utf-8 -*-# Form implementation generated from reading ui file qt_listview.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not…

Docker之私有仓库 RegistryHarbor

目录 一、Docker私有仓库(Registry) 1.1 Registry的介绍 二、搭建本地私有仓库 2.1首先下载 registry 镜像 2.2在 daemon.json 文件中添加私有镜像仓库地址 2.3运行 registry 容器 2.4Docker容器的重启策略 2.5为镜像打标签 2.6上传到私有仓库 2…

jvm的内存区域

JVM 内存分为线程私有区和线程共享区,其中方法区和堆是线程共享区,虚拟机栈、本地方法栈和程序计数器是线程隔离的数据区。 1)程序计数器 程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块…

基于Echarts的大数据可视化模板:大数据医疗服务平台

目录 引言大数据在医疗领域的应用ECharts在医疗服务中的作用医疗大数据的应用方向临床决策支持药物研发与安全性监测健康管理与预防流行病监测与公共卫生基因组学与个性化医疗医疗保险与费用管理Echarts与大数据可视化Echarts库以及其在大数据可视化领域的应用优势开发过程和所…

只考一门数据结构,计算机学硕复录比1:1的山东双非学校考情分析

青岛理工大学 考研难度(☆) 内容:23考情概况(拟录取和复试分析)、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1420字,预计阅读:3分钟 2023考情概况 青岛理工…

redis缓存雪崩、穿透、击穿解决方案

redis缓存雪崩、穿透、击穿解决方案 背景缓存雪崩缓存击穿缓存穿透总结背景 关于缓存异常,我们常见的有三个问题:缓存雪崩、缓存击穿、缓存穿透。这三个问题一旦发生,会导致大量请求直接落到数据库层面。如果请求的并发量很大,会影响数据库的运行,严重的会导致数据库宕机…

openGauss学习笔记-54 openGauss 高级特性-MOT

文章目录 openGauss学习笔记-54 openGauss 高级特性-MOT54.1 MOT特性及价值54.2 MOT关键技术54.3 MOT应用场景54.4 不支持的数据类型54.5 使用MOT54.6 将磁盘表转换为MOT openGauss学习笔记-54 openGauss 高级特性-MOT openGauss引入了MOT(Memory-Optimized Table&…

如何高效地设计测试用例并评审

编写出好的测试用例是每一个测试工程师的职责,但在实际工作中大家写的测试用例往往需要不断地修改才能使用,这不仅浪费了时间,还容易让测试工程师产生自我否定的情绪,甚至在团队中产生各种矛盾。 那如何高效地设计测试用例呢&…

可直接运营的餐饮外卖点餐自提单多门店小程序开发演示

适合鲜花店、蛋糕店、奶茶店、餐饮店、便利店等门店商家的小程序。 小程序系统支持外卖和自提两种模式,帮助商家打造自己的私域流量池,减少对美团和饿了么的依赖,提升用户点餐、就餐体验。 支持会员签到获取积分的功能,积分可用…

jwt安全问题

文章目录 jwt安全问题jwt简介jwt组成headerpayloadsignature 潜在漏洞空加密算法web346 密钥爆破web348 敏感信息泄露web349 **修改算法RS256为HS256**web350 jwt安全问题 jwt简介 JWT的全称是Json Web Token,遵循JSON格式,跨域认证解决方案&#xff0…

【93】PCI Expansion ROM

1、Expansion ROM PCIe、PCI设备可以提供Expansion ROM,Expansion ROM中存在设备初始化或者system boot的code。SystemBIOS在POST(Power-on Self Test)阶段,会枚举PCI设备,并判断有设备是否支持Expansion ROM&#xff…

Python爬虫武汉市二手房价格数据采集分析:Linear Regression、XGBoost和LightGBM|代码分享...

全文链接:http://tecdat.cn/?p31958 分析师:Yan Liu 我国有大量的资金都流入了房地产行业,同时与其他行业有着千丝万缕的联系,可以说房地产行业对推动我国深化改革、经济发展、工业化和城市化具有不可磨灭的作用(点击…

WebSocket详解以及应用

😜作 者:是江迪呀✒️本文关键词:websocket、网络、长连接、前端☀️每日 一言:任何一个你不喜欢而又离不开的地方,任何一种你不喜欢而又无法摆脱的生活,都是监狱! 一、前言 我们在…

基于Spring Gateway路由判断器实现各种灰度发布场景

文章目录 1、灰度发布实现1.1 按随机用户的流量百分比实现灰度1.2 按人群划分实现的灰度1.2.1 通过Header信息实现灰度1.2.2 通过Query信息实现灰度1.2.3 通过RemoteAdd判断来源IP实现灰度 2、路由判断器2.1. After2.2. Before2.3. Between2.4. Cookie2.5. Header2.6. Host2.7.…

GEE/PIE遥感大数据处理与典型案例丨数据整合Reduce、云端数据可视化、数据导入导出及资产管理、机器学习算法等

目录 ​专题一:初识GEE和PIE遥感云平台 专题二:GEE和PIE影像大数据处理基础 专题三:数据整合Reduce 专题四:云端数据可视化 专题五:数据导入导出及资产管理 专题六:机器学习算法 专题七:…

2023-8-30 Dijkstra 求最短路(一)

题目链接&#xff1a;Dijkstra求最短路 I #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 510;int n, m; int g[N][N]; int dist[N]; bool st[N];int dijkstra() {memset(dist, 0x3f, sizeof dist);dist[1…

Leetcode每日一题:1448. 统计二叉树中好节点的数目

原题 给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,3,null,1,5] 输出&#xff1a;4 解…