当前位置: 首页 > news >正文

golang的引用和非引用总结

目录

概述

一、基本概念

指针类型(Pointer type)

非引用类型(值类型)

引用类型(Reference Types)

解引用(dereference)

二、引用类型和非引用类型的区别

三、golang数据类型系统里的引用类型和非引用类型

值类型(Value Types)

引用类型(Reference Types)

四、golang数据类型系统里的零值

五、Methods and pointer indirection

情况1:函数的形参是值类型,实参是值类型的处理情况

情况2:函数的形参是值类型,实参是指针类型的处理情况

情况3:函数的形参是指针类型,实参是值类型的处理情况

情况4:函数的形参是指针类型,实参是指针类型的处理情况

情况5:方法的接收者是值类型,方法的调用者是值类型的处理情况

情况6:方法的接收者是值类型,方法的调用者是指针类型的处理情况

情况7:方法的调用者是指针类型,方法的调用者是值类型的处理情况

情况8:方法的调用者是指针类型,方法的调用者是指针的处理情况

总结


概述

        本文主要介绍引用类型和非引用类型的基本概念,golang的数据类型系统里有哪些是引用类型和非引用类型,以及引用类型和非引用的区别,他们的优缺点,尤其重点介绍了golang的“Methods and pointer indirection”的含义,指针类型和值类型在函数参数传递和方法调用方面的区别。

一、基本概念

        编程语言中,引用类型和非引用类型(有时也被称为值类型)是两种主要的数据类型分类方式,它们主要区别在于数据在内存中的存储和传递方式。

指针类型(Pointer type)

        指针类型是指能够存储变量地址的数据类型。在 Go 中,使用 *T 表示指向 T 类型的指针,其中 T 是任意类型。指针类型允许我们直接操作变量的内存地址,可以用来传递变量的引用,以及在需要时间接访问变量的值。例如,*int 表示指向整数类型的指针。

非引用类型(值类型)

        非引用类型,也称为值类型,在创建变量时,会在内存中分配一个新的存储空间来存储该变量的值。每个值类型的变量都有自己独立的存储空间,并且变量的值会被直接复制。当你将一个值类型的变量赋值给另一个变量时,实际上是创建了这个值的一个副本。对副本所做的任何修改都不会影响原始变量。因此,值类型的变量在函数参数传递时也是按值传递的。在Go语言中,基本数据类型(如int、float64、bool、string等)和数组都是值类型。

引用类型(Reference Types

        引用类型在创建变量时,并不会在内存中直接存储数据本身,而是存储一个指向数据的引用(或指针)。这个引用是一个地址,指向在堆内存中存储的实际数据。多个引用类型的变量可以指向同一个数据。当你将一个引用类型的变量赋值给另一个变量时,你其实是在复制这个引用,而不是数据本身。因此,所有指向同一个数据的引用类型变量都会共享这个数据

解引用(dereference)

      解引用是指通过指针获取其所指向的值。换句话说,解引用是一种操作,允许我们通过指针变量访问和修改变量或对象的值。通过使用*操作符,我们可以对指针变量进行解引用操作,获取其所指向的值。

        解引用不仅适用于基础数据类型,也适用于结构体等复合类型。例如,我们可以解引用一个指向结构体的指针,以访问或修改结构体的字段。

需要注意的是golang对未初始化的引用类型,进行解引用操作会引发运行时错误(panic)。这是因为未初始化的引用类型变量在内存中没有有效的值或地址,尝试解引用这样的变量将导致未定义的行为

二、引用类型和非引用类型的区别

三、golang数据类型系统里的引用类型和非引用类型

        在 Go 语言中,类型可以分为值类型和引用类型。这两种类型的主要区别在于它们在内存中的存储方式和赋值操作的行为

值类型(Value Types)

值类型包括:

  1. 基本数据类型:如 intfloat64boolstringcomplex64complex128rune(即 int32 的别名,用于表示 Unicode 码点)等。

  2. 数组:数组是固定长度的序列,每个元素都是相同类型的值。例如 [5]int

  3. 结构体:结构体是由一组字段组成的值类型。字段可以具有不同的类型。

对于值类型的变量,赋值操作会创建该值的副本。这意味着如果你修改了一个值类型变量的值,它不会影响其他使用该类型值的变量。

引用类型(Reference Types)

引用类型包括:

  1. 切片:切片是对数组的抽象,它提供了动态长度的、灵活且可变的序列。切片底层引用了数组的一部分或全部,但它本身是一个独立的类型。

  2. 映射:映射是键值对的集合。Go 语言中的映射类型使用 map 关键字定义,例如 map[string]int

  3. 通道:通道用于在 Go 语言的并发程序中传递数据。它们用于实现协程之间的通信。

  4. 接口:接口定义了一组方法的集合,任何实现这些方法的具体类型都被认为实现了该接口。接口本身不存储数据,但可以作为引用类型传递。

  5. 函数:在 Go 语言中,函数也可以被视为值,可以赋值给变量,也可以作为参数传递给其他函数。尽管函数在内存中的表示与常规的值类型略有不同,但在许多上下文中,它们的行为类似于引用类型。

四、golang数据类型系统里的零值

        在 Go 语言中,当声明一个变量但未对其进行赋值时,该变量会被赋予其对应类型的零值。零值是指变量在未被显式赋值时的默认值。下面是 Go 语言中常见类型的零值: 

 

五、Methods and pointer indirection

        前面的铺垫其实我们为了更好地理解“Methods and pointer indirection”。什么是“Methods and pointer indirection”

  • functions with a pointer argument must take a pointer
  • while methods with pointer receivers take either a value or a pointer as the receiver when they are called

为了更好地理解上面这段话,我将问题进行了拓展,即值类型和引用类型在函数传递和方法调用的不同情况下golang编译器的处理方式,分别从参数传递机制,拷贝机制,是否更改原值方面将问题拆分了8种以下情况,并用简单的代码示例来探究解释。

情况1:函数的形参是值类型,实参是值类型的处理情况

package mainimport "fmt"func modifyValue(val int) {val = 100
}func main() {x := 10modifyValue(x)fmt.Println(x) // Output: 10 (原始值未被修改)
}

  • 参数传递机制:当函数形参是值类型,实参也是值类型时,编译器在函数调用时,会复制实参的副本传递给函数,编译器会在栈上分配内存空间,将参数的值复制到栈上的内存位置,然后将栈的内存地址传递给函数
  • 是否修改原始值:不会修改原始值,因为修改只影响参数的副本

情况2:函数的形参是值类型,实参是指针类型的处理情况

package mainimport "fmt"func modifyValue(val int) {val = 100
}func main() {x := 10modifyValue(&x)fmt.Println(x) // cannot use &x (value of type *int) as int value in argument to modifyValue
}

函数的形参是值类型,传递给函数逇也必须是值类型,类型匹配原则 ,类型不匹配编译报错

情况3:函数的形参是指针类型,实参是值类型的处理情况

package mainimport "fmt"func modifyValue(val *int) {*val = 100
}func main() {x := 10modifyValue(x)fmt.Println(x) // cannot use x (variable of type int) as *int value in argument to modifyValue
}

 函数的形参是指针类型,传递给函数的也必须是指针类型,类型匹配原则 ,类型不匹配编译报错

情况4:函数的形参是指针类型,实参是指针类型的处理情况

package mainimport "fmt"func modifyValue(val *int) {*val = 100
}func main() {x := 10modifyValue(&x)fmt.Println(x) // output 100 更改原值
}
  • 参数传递机制:当函数形参是指针类型时,实参也是指针类型时,编译器在函数调用时,会复制实参的地址传递给函数,编译器会在栈上分配空间,将参数的地址复制到栈的内存位置,然后将栈的内存地址传递给函数
  • 是否修改原始值:通过指针可以间接地修改原始值

情况5:方法的接收者是值类型,方法的调用者是值类型的处理情况

package mainimport "fmt"type Myint intfunc (m Myint) modify() {m = 10
}func main() {x := Myint(5)x.modify()fmt.Println(x) //output 5
}
  • 参数传递机制:在栈上为调用者分配内存空间,调用方法时,会将调用者的值复制一份,传递给方法的接收者。
  • 是否修改原始值:不会修改原始值,因为修改的只是调用者的副本

情况6:方法的接收者是值类型,方法的调用者是指针类型的处理情况

package mainimport "fmt"type Myint intfunc (m Myint) modify() {m = 10
}func main() {x := Myint(5)(&x).modify()fmt.Println(x) //output 5
}
  • 参数传递机制:编译器会将调用者指针解引用为值,然后在解引用后的对象上调用方法,在栈上分配内存空间,并将指针解引用后的值复制到分配的内存位置。编译器将指针解引用,然后解引用后的对象上调用方法
  • 是否修改原始值:不会修改原始值,因为调用者是指针类型,接收者是值类型,调用者后的对象是调用者的副本。

情况7:方法的调用者是指针类型,方法的调用者是值类型的处理情况

package mainimport "fmt"type Myint intfunc (m *Myint) modify() {*m = 10
}func main() {x := Myint(5)x.modify()fmt.Println(x) //output 10
}
  • 参数传递机制:调用方法时,编译器会隐式地取调用者的地址,传递给方法的接收者
  • 是否修改原始值:调用地址的副本间接修改原始值

情况8:方法的调用者是指针类型,方法的调用者是指针的处理情况

package mainimport "fmt"type Myint intfunc (m *Myint) modify() {*m = 10
}func main() {x := Myint(5)(&x).modify()fmt.Println(x) //output 10
}
  • 参数传递机制:调用方法时,直接将调用者的地址传递给方法的接收者
  • 是否修改原始值:直接修改原始值

总结

        对于函数的形参和实参,参数的类型必须匹配。如果函数的形参是值类型,则传递给它的实参必须是值类型;如果形参是指针类型,则传递给它的实参必须是指针类型。

        而对于方法的接收者和调用者,Go 允许方法的接收者是值类型,这意味着可以直接使用值类型的实例调用该方法;也可以是指针类型,这意味着可以使用指针类型的实例调用该方法。

这种灵活性使得在设计和使用方法时更加方便,可以根据具体的需求和场景选择适合的方法接收者类型。

  • 对于函数(即不附属于任何类型的函数),如果函数的参数是指针类型,那么调用该函数时必须传递一个指针作为参数。这是因为函数是独立存在的,没有与之关联的接收者对象,因此无法通过隐式的方法接收者来自动解引用指针。
  • 对于方法(即附属于某个类型的函数),如果方法的接收者是指针类型,那么在调用该方法时,可以选择传递一个值类型的接收者或者一个指针类型的接收者。如果传递的是值类型的接收者,Go 语言会在内部将其自动解引用为指针类型。这是因为方法是与类型相关联的,可以通过类型的值或指针来调用方法,而不需要显式地进行解引用。

简而言之,函数需要显式地传递指针作为参数,而方法可以接受值类型或指针类型的接收者,并在需要时进行自动解引用。这就是“Methods and pointer indirection”的含义所在

相关文章:

golang的引用和非引用总结

目录 概述 一、基本概念 指针类型(Pointer type) 非引用类型(值类型) 引用类型(Reference Types) 解引用(dereference) 二、引用类型和非引用类型的区别 三、golang数据类型…...

2024认证杯数学建模B题思路模型代码

目录 2024认证杯数学建模B题思路模型代码:4.11开赛后第一时间更新,获取见文末名片 第十三届“认证杯”数学中国数学建模比赛赛后体会 2024认证杯数学建模B题思路模型代码:4.11开赛后第一时间更新,获取见文末名片 第十三届“认证杯”数学中国数学建模比…...

一种快速移植 OpenHarmony Linux 内核的方法

移植概述 本文面向希望将 OpenHarmony 移植到三方芯片平台硬件的开发者,介绍一种借助三方芯片平台自带 Linux 内核的现有能力,快速移植 OpenHarmony 到三方芯片平台的方法。 移植到三方芯片平台的整体思路 内核态层和用户态层 为了更好的解释整个内核…...

java的jar包jakarta.jakartaee-web-api和jakarta.servlet-api有什么区别

jakarta.jakartaee-web-api和jakarta.servlet-api都是Java EE(现在是 Jakarta EE)中的一部分,用于开发基于Java EE平台的Web应用程序。它们之间的区别在于以下几点: 命名空间: jakarta.servlet-api是Java EE 8之前版本…...

QT_day2

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt4版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为…...

Advanced RAG 02:揭开 PDF 文档解析的神秘面纱

编者按: 自 2023 年以来,RAG 已成为基于 LLM 的人工智能系统中应用最为广泛的架构之一。由于诸多产品的关键功能(如:领域智能问答、知识库构建等)严重依赖RAG,优化其性能、提高检索效率和准确性迫在眉睫&am…...

Spring面试题pro版-1

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。 Spring是什么…...

6 Reverse Linked List

分数 20 作者 陈越 单位 浙江大学 Write a nonrecursive procedure to reverse a singly linked list in O(N) time using constant extra space. Format of functions: List Reverse( List L ); where List is defined as the following: typedef struct Node *PtrToNo…...

【随笔】Git 高级篇 -- 相对引用2 HEAD~n(十三)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…...

2024免费Mac电脑用户的系统清理和优化软件CleanMyMac

作为产品营销专家,对于各类产品的特性与优势有着深入的了解。CleanMyMac是一款针对Mac电脑用户的系统清理和优化软件,旨在帮助用户轻松管理、优化和保护Mac电脑。以下是关于CleanMyMac的详细介绍: CleanMyMac X2024全新版下载如下: https://…...

Centos7源码方式安装Elasticsearch 7.10.2单机版

版本选择参考:Elasticsearch如何选择版本-CSDN博客 下载 任选一种方式下载 官网7.10.2版本下载地址: https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-linux-x86_64.tar.gz 网盘下载链接 链接:https://pan…...

mysql的安装和部署

##官网下载mysql 我下载的是一个mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz 可以通过xshell 或者xftp传送 xshell则是先下载一个lrzsz 执行以下的命令 yum install lrzsz -y #安装好我下面有个一键安装的脚本 #!/bin/bash#解决软件的依赖关系 yum install cmake ncurses…...

大数据基本名词

目录[-] 1.1. 1. Hadoop1.2. 2. Hive1.3. 3. Impala1.4. 4. Hbase1.5. 5.hadoop hive impala hbase关系1.6. 6. Spark1.7. 7. Flink1.8. 8. Spark 和 Flink 的应用场景 1. Hadoop 开源官网:https://hadoop.apache.org/ Hadoop是一个由Apache基金会所开发的分…...

网站网页客服、微信公众号客服、H5客服、开源源码与高效部署的完美结合

随着互联网技术的飞速发展,企业与客户之间的沟通方式也在持续变革。在线客服系统作为一种新兴的沟通工具,已经成为提升企业服务质量、增强客户满意度的重要手段。本文将详细介绍在线客服系统的优势、功能以及如何高效部署,特别是推荐一款名为…...

1、Qt UI控件 -- qucsdk

前言:Qt编写的自定义控件插件的sdk集合,包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库,都是一些编译好的控件,可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…...

Sora是什么?Sora怎么使用?Sora最新案例视频以及常见问题答疑

Sora 是什么? 2024年2月16日,OpenAI 在其官网上面正式宣布推出文本生成视频的大模型Sora 这样说吧给你一段话, 让你写一篇800字的论文,你的理解很可能都有偏差,那么作为OpenAi要做文生视频到底有多难,下面…...

如何在Ubuntu系统使用docker部署DbGate容器并发布至公网可访问

文章目录 1. 安装Docker2. 使用Docker拉取DbGate镜像3. 创建并启动DbGate容器4. 本地连接测试5. 公网远程访问本地DbGate容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Linux Ubuntu系统中使用Docker部署DbGate数据库管理工…...

解决 VSCode 编辑器点击【在集成终端中打开】出现新的弹框

1、问题描述 在 VSCode 的项目下,鼠标右键,点击【在集成终端中打开】,出现新的一个弹框。新版的 VSCode 会有这个问题,一般来说我们都希望终端是在 VSCode 的控制台中打开的,那么如何关闭这个弹框呢? 2、解…...

从零开始:构建、打包并上传个人前端组件库至私有npm仓库的完整指南

文章目录 一、写组件1、注册全局组件方法2、组件13、组件2 二、测试三、发布1、配置package.json2、生成库包3、配置发布信息4、发布 四、使用1、安装2、使用 五、维护1、维护和更新2、注意事项 一、写组件 确定组件库的需求和功能:在开始构建组件库之前&#xff0c…...

Ant Design Vue 表单验证手机号的正则

代码&#xff1a; pattern: /^1[3456789]\d{9}$/ 1. <a-form-item label"原手机号" v-bind"validateInfos.contactTel"><a-inputstyle"width: 600px"allow-clear:maxlength"20"placeholder"请输入原手机号"v-mo…...

NaViL-9B多模态能力详解:从API调用到温度参数优化的完整指南

NaViL-9B多模态能力详解&#xff1a;从API调用到温度参数优化的完整指南 1. 平台概述与核心能力 NaViL-9B是一款原生多模态大语言模型&#xff0c;由专业研究机构开发。它同时具备文本理解和图像分析能力&#xff0c;能够处理纯文本问答和图片内容理解任务。这种双模态能力使…...

通义千问1.5-1.8B-Chat-GPTQ-Int4在MySQL数据库中的智能应用

通义千问1.5-1.8B-Chat-GPTQ-Int4在MySQL数据库中的智能应用 让数据库听懂人话&#xff0c;让查询像聊天一样简单 你有没有遇到过这样的情况&#xff1a;面对复杂的业务数据&#xff0c;明明知道想要什么结果&#xff0c;却不知道怎么写SQL语句&#xff1f;或者看着慢查询日志头…...

Android Studio 高版本兼容低版本项目配置

AndroidStudio开发工具高版本兼容低版本项目配置&#xff1a;1、 JDK 配置&#xff1a;gradle.properties 文件中指定jdk 版本&#xff1a;org.gradle.java.homeD\:\\ProgramFiles\\JDK\\jdk-11.0.262 配置Gradle 编译版本&#xff1a;3. 显示所有Gradle task 列表设置完成后&a…...

Scrcpy:重新定义安卓设备跨平台交互体验

Scrcpy&#xff1a;重新定义安卓设备跨平台交互体验 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/gh_mirrors/sc/scrcpy 一、跨设备交互的现实困境&#xff1a;发现问题本质 在数字化办公与移动开发的日常场景中&a…...

别再自己造轮子了!用Qt的QModbusTcpClient库5分钟搞定Modbus TCP通讯

别再重复造轮子&#xff01;用Qt的QModbusTcpClient库5分钟实现工业级Modbus TCP通信 在工业自动化领域&#xff0c;Modbus TCP协议因其简单可靠的特点&#xff0c;已成为PLC与上位机通信的事实标准。许多Qt开发者面对Modbus通信需求时&#xff0c;第一反应往往是手动封装协议栈…...

多任务学习进阶:从MMoE到PLE的模型演进与实战解析

1. 多任务学习基础与核心挑战 多任务学习&#xff08;Multi-Task Learning, MTL&#xff09;是机器学习领域的一个重要分支&#xff0c;它让单个模型同时学习多个相关任务。想象一下&#xff0c;你正在教一个学生同时学习数学和物理。如果这两个学科有共同的基础概念&#xff0…...

pandas API on Spark 与 pandas / PySpark 互转指南

1. 为什么会有互转需求 pandas API on Spark 的定位很特殊&#xff1a;它既想保留 pandas 的使用体验&#xff0c;又建立在 Spark 的分布式执行之上。因此开发时常见的场景有三种&#xff1a; 已经有 pandas 代码&#xff0c;想迁移到分布式环境已经在用 PySpark DataFrame&…...

nRF52与RFX2401C的PA+LNA优化方案:基于SoftDevice的高效驱动实现

1. 为什么需要PA和LNA优化方案 如果你正在用nRF52开发BLE设备&#xff0c;可能会遇到这样的困扰&#xff1a;明明参数配置没问题&#xff0c;但通信距离就是达不到预期。这时候就该请出我们今天的主角——RFX2401C这颗PA/LNA芯片了。我去年做智能牧场项⽬时就踩过这个坑&#…...

Leather Dress Collection 企业级参数调优指南:平衡响应速度与生成质量

Leather Dress Collection 企业级参数调优指南&#xff1a;平衡响应速度与生成质量 如果你正在考虑把Leather Dress Collection这类大模型服务搬到公司的生产环境里&#xff0c;那你肯定遇到过这样的纠结&#xff1a;调快了&#xff0c;生成的内容质量好像会打折扣&#xff1b…...

告别付费IP!手把手教你用ZCU102 PS端DP接口点亮显示器(附参数调试心得)

解锁ZCU102 PS端DisplayPort潜力&#xff1a;零成本实现高效显示输出的实战指南 在嵌入式视觉系统开发中&#xff0c;显示输出往往是项目落地的最后一道关卡。当我在多个Zynq UltraScale MPSoC项目中反复遭遇HDMI IP核的授权困扰和PL端实现的复杂性后&#xff0c;意外发现PS端集…...