在Go语言中,函数参数的传递方式有两种:传值(pass-by-value)和传引用(pass-by-reference)。理解这两种方式的区别及其适用场景,是成为Go语言开发高手的必备技能。本文将深入探讨Go语言中传值与传引用的区别,并提供一些选择传值或传引用的实际建议。

传值的情况:

  • 基本类型(int、bool、string等)
  • 小结构体(几个字段)
  • 不需要修改原值
  • 保证数据安全

传指针的情况:

  • 大结构体(避免拷贝开销)
  • 需要修改原值
  • 避免重复拷贝大对象
  • slice、map、channel本身就是引用类型

性能考虑:

  • 结构体超过几十字节建议传指针
  • 频繁调用的函数优先考虑指针
  • 但不要过度优化,先保证正确性

实际经验:

  • 小对象传值,大对象传指针
  • 需要修改就传指针
  • 不确定时可以都用指针,性能通常更好

### 一、传值与传引用的基本概念

#### 1. 传值(Pass-by-Value)

传值意味着当函数接收一个参数时,函数得到的是该参数的副本。换句话说,函数内部对参数的任何修改都不会影响到原始变量。Go语言中的所有基本数据类型(如int、float64、bool、string等)都默认采用传值方式传递。

例如:

```go
package main

import "fmt"

func modifyValue(x int) {
x = 10
fmt.Println("Inside function:", x)
}

func main() {
a := 5
modifyValue(a)
fmt.Println("Outside function:", a)
}
```

输出:

```
Inside function: 10
Outside function: 5
```

在这个例子中,尽管函数内修改了`x`的值,但`a`的值在函数外部没有发生改变。这是因为`x`只是`a`的一个副本,修改副本不会影响原始数据。

#### 2. 传引用(Pass-by-Reference)

传引用意味着函数接收到的是原始数据的地址,而不是数据的副本。因此,函数内部对参数的修改会直接影响到原始数据。在Go语言中,传引用通常通过指针实现。

例如:

```go
package main

import "fmt"

func modifyReference(x *int) {
*x = 10
fmt.Println("Inside function:", *x)
}

func main() {
a := 5
modifyReference(&a)
fmt.Println("Outside function:", a)
}
```

输出:

```
Inside function: 10
Outside function: 10
```

这里,`x`是`a`的指针。通过`*x`修改指向的值,会直接修改`a`的值。

### 二、传值与传引用的区别

| **特点**           | **传值**                                    | **传引用**                                    |
|-------------------|---------------------------------------------|---------------------------------------------|
| **数据传递**      | 传递数据的副本。                           | 传递数据的内存地址。                         |
| **函数内部修改**  | 函数内部修改不影响外部变量。               | 函数内部修改会影响外部变量。                 |
| **性能**          | 对于大数据结构,传值会消耗更多内存和时间。 | 传引用避免了复制大数据结构,性能较优。       |
| **默认行为**      | Go中默认是传值。                           | 通过指针显式传递引用。                       |
| **安全性**        | 数据副本修改较为安全。                     | 修改原始数据可能带来潜在的副作用,需小心。   |

### 三、如何选择传值还是传引用

选择传值还是传引用取决于多个因素,包括性能需求、数据大小、函数设计和代码安全性。以下是一些具体的选择建议:

#### 1. **选择传值:**

- **小型数据类型:** 对于简单的数据类型(如`int`、`float`、`string`),传值通常没有性能问题,因为复制这些类型的值开销较小。此时可以选择传值,代码更加简洁和安全。
- **数据不需要修改:** 如果你不希望函数内修改外部变量的值,可以选择传值。传值会创建副本,避免了不小心修改原始数据的风险。
- **避免副作用:** 传值可以避免副作用,因为每个函数都有自己独立的变量副本,不会影响其他函数或外部代码的行为。

#### 2. **选择传引用:**

- **大型数据结构:** 对于结构体(struct)和数组(array)等较大的数据结构,传值会带来显著的性能开销。此时使用传引用(指针)可以避免复制大量数据,提高性能。
- **需要修改原始数据:** 如果函数需要修改传入的值,传引用是合适的选择。通过指针,你可以直接修改原始数据而不是副本。
- **避免复制复杂对象:** 结构体、切片、映射等较为复杂的对象在传值时会进行复制,导致内存使用量大。使用指针传递引用可以显著减少内存的占用和复制的开销。

### 四、传值与传引用的选择场景分析

#### 1. **传值的适用场景:**

- **简单数据类型:** 如`int`、`float64`、`bool`等,传值的性能开销较小,适用于这些简单类型。
- **函数内部不修改原数据:** 如果函数只是读取数据而不修改它,传值可以避免潜在的副作用,使代码更易理解。
- **函数设计简单:** 如果函数比较简单,且不涉及复杂的数据修改,使用传值能够提高代码的可维护性和可读性。

#### 2. **传引用的适用场景:**

- **修改原数据:** 如果需要修改传入的数据或在多个函数之间共享数据,传引用更为合适。这样可以避免返回值传递或重复修改副本的麻烦。
- **性能敏感:** 当涉及到大型结构体、数组或切片等对象时,传引用能避免复制整个对象,减少内存占用和性能消耗。
- **复杂对象传递:** 对于结构体或切片这类较为复杂的数据类型,传引用是常见的选择。它能够减少不必要的内存分配和复制,提高效率。

### 五、总结

在Go语言中,传值和传引用各有其优缺点和使用场景。选择传值还是传引用,应该根据具体情况决定:

- **传值**:适用于简单数据类型,数据不需要修改,能够避免副作用。
- **传引用**:适用于修改数据、提高性能或传递较大数据结构时。

通过深入理解这些区别,并结合实际需求,你能够在Go语言编程中做出更合理的选择,提高程序的性能和可维护性。

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

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

相关文章

数据无言,网关有声 耐达讯自动化RS485转Profinet让千年液位数据“开口说话”

在能源行业的数字化转型浪潮中,你是否曾面临这样的困境: 现场大量采用RS485接口的液位计,数据孤立如信息孤岛,无法接入Profinet高速网络? 模拟信号传输距离受限,抗干扰能力弱,导致液位测量误差…

出口退税新政大提速:企业如何抓住政策红利,提升最高13%纯利?

近年来,出口退税政策的优化与升级,正在成为外贸企业提升资金周转率和利润率的关键。国家税务总局发布的 2022年第9号公告(简称“9号公告”)落地执行已两年,外贸行业普遍感受到退税速度显著加快,平均退税周期…

使用pytorch创建/训练/推理OCR模型

一、任务描述 从手写数字图像中自动识别出对应的数字(0-9)” 的问题,属于单标签图像分类任务(每张图像仅对应一个类别,即 0-9 中的一个数字) 1、任务的核心定义:输入与输出 输入:28…

新启航开启深孔测量新纪元:激光频率梳技术攻克光学遮挡,达 130mm 深度 2μm 精度

摘要:本文聚焦于深孔测量领域,介绍了一种创新的激光频率梳技术。该技术成功攻克传统测量中的光学遮挡难题,在深孔测量深度达 130mm 时,可实现 2μm 的高精度测量,为深孔测量开启了新的发展篇章。关键词:激光…

GEO优化推荐:AI搜索新纪元下的品牌内容权威构建

引言:AI搜索引擎崛起与GEO策略的战略重心转移2025年,以ChatGPT、百度文心一言、DeepSeek为代表的AI搜索引擎已深入成为公众信息获取的核心渠道。这标志着品牌营销策略的重心,正从传统的搜索引擎优化(SEO)加速向生成式引…

uniapp的上拉加载H5和小程序

小程序配置{"path": "list/course-list","style": {"navigationBarTitleText": "课程列表","enablePullDownRefresh": true,"onReachBottomDistance": 150}}上拉拉触底钩子onReachBottom() {var that …

【和春笋一起学C++】(四十)抽象数据类型

抽象数据类型(abstract data type, ADT)以通用的方式描述数据类型。C中类的概念非常适合于ADT方法。例如,C程序通过堆栈来管理自动变量,堆栈可由对它执行的操作来描述。可创建空堆栈;可将数据项添加到堆顶(…

大文件断点续传解决方案:基于Vue 2与Spring Boot的完整实现

大文件断点续传解决方案:基于Vue 2与Spring Boot的完整实现 在现代Web应用中,大文件上传是一个常见但具有挑战性的需求。传统的文件上传方式在面对网络不稳定、大文件传输时往往表现不佳。本文将详细介绍如何实现一个支持断点续传的大文件上传功能,结合Vue 2前端和Spring Bo…

LeNet-5:手写数字识别经典CNN

配套讲解视频,点击下方名片获取20 世纪 90 年代,计算机已经能识别文本,但图片识别很困难。比如银行支票的手写数字识别,传统方法需要人工设计规则,费时费力且精度不高。 于是,Yann LeCun 及其团队提出了 Le…

如何在 C# 中将文本转换为 Word 以及将 Word 转换为文本

在现代软件开发中,处理文档内容是一个非常常见的需求。无论是生成报告、存储日志,还是处理用户输入,开发者都可能需要在纯文本与 Word 文档之间进行转换。有时需要将文本转换为 Word,以便生成结构化的 .docx 文件,使内…

Open SWE:重构代码协作的智能范式——从规划到PR的全流程自动化革命

在软件开发的演进史上,工具链的每一次革新都深刻重塑着开发者的工作方式。LangChain AI推出的Open SWE,作为首个开源的异步编程代理,正在重新定义代码协作的边界——它不再仅仅是代码生成工具,而是构建了从代码库分析、方案规划、代码实现到拉取请求创建的端到端自动化工作…

【ARDUINO】通过ESP8266控制电机【待测试】

需求 通过Wi-Fi控制Arduino驱动的3V直流电机。这个方案使用外部6V或9V电源,ESP8266作为Wi-Fi模块,Arduino作为主控制器,L298N作为电机驱动器。 手机/电脑 (Wi-Fi客户端) | | (Wi-Fi) | ESP8266 (Wi-Fi模块, AT指令模式) | | (串口通信) | A…

cuda编程笔记(18)-- 使用im2col + GEMM 实现卷积

我们之前介绍了cudnn调用api直接实现卷积,本文我们探究手动实现。对于直接使用for循环在cpu上的实现方法,就不过多介绍,只要了解卷积的原理,就很容易实现。im2col 的核心思想im2col image to column把输入 feature map 的每个卷积…

Loopback for Mac:一键打造虚拟音频矩阵,实现跨应用音频自由流转

虚拟音频设备创建 模拟物理设备:Loopback允许用户在Mac上创建虚拟音频设备,这些设备可被系统及其他应用程序识别为真实硬件,实现音频的虚拟化传输。多源聚合:支持将麦克风、应用程序(如Skype、Zoom、GarageBand、Logic…

深入解析Django重定向机制

概述 核心是一个基类 HttpResponseRedirectBase,以及两个具体的子类 HttpResponseRedirect(302 临时重定向)和 HttpResponsePermanentRedirect(301 永久重定向)。它们都是 HttpResponse 的子类,专门用于告诉…

【Java实战⑳】从IO到NIO:Java高并发编程的飞跃

目录一、NIO 与 IO 的深度剖析1.1 IO 的局限性1.2 NIO 核心特性1.3 NIO 核心组件1.4 NIO 适用场景二、NIO 核心组件实战2.1 Buffer 缓冲区2.2 Channel 通道2.3 Selector 选择器2.4 NIO 文件操作案例三、NIO2.0 实战3.1 Path 类3.2 Files 类3.3 Files 类高级操作3.4 NIO2.0 实战…

OpenCV 实战:图像模板匹配与旋转处理实现教程

目录 一、功能概述:代码能做什么? 二、环境准备:先搭好运行基础 1. 安装 Python 2. 安装 OpenCV 库 3. 准备图像文件 三、代码逐段解析:从基础到核心 1. 导入 OpenCV 库 2. 读取图像文件 3. 模板图像旋转:处理…

一、cadence的安装及入门教学(反相器的设计与仿真)

一、Cadence的安装 1、安装VMware虚拟机 2、安装带有cadence软件的Linux系统 注:网盘链接 分享链接:https://disk.ningsuan.com.cn/#s/8XaVdtRQ 访问密码:11111 所有文件压缩包及文档密码: Cadence_ic 3、安装tsmc18工艺库…

用ai写了个UE5插件

文章目录实际需求1.头文件2.源文件3.用法小结实际需求 这个需求来源于之前的一个项目,当时用了一个第三方插件,里边有一些绘制线段的代码,c层用的是drawdebugline,当时看底层,觉得应该没问题,不应该在rele…

机器学习从入门到精通 - 强化学习初探:Q-Learning到Deep Q-Network实战

机器学习从入门到精通 - 强化学习初探:从 Q-Learning 到 Deep Q-Network 实战 一、开场白:推开强化学习这扇门 不知道你有没有过这种感觉 —— 盯着一个复杂的系统,既想让它达到某个目标,又苦于无法用传统规则去精确描述每一步该怎…