新闻中心

如何在Golang中理解值拷贝与指针传递

2025-11-04
浏览次数:
返回列表
Go中所有参数传递均为值拷贝,拷贝内容可能是数据本身或指针地址。1. 值拷贝:传基本类型、结构体时复制副本,函数内修改不影响原变量;2. 指针传递:拷贝的是地址,通过指针可修改原始数据;3. 特殊类型如slice、map、channel底层含指针,传递时拷贝的是指向底层数组的指针结构,故能间接修改数据,但重新赋值不影响外部;4. 选择依据:是否需修改原数据、数据大小、方法集一致性与nil安全性。核心是理解拷贝的是值还是指针。

如何在golang中理解值拷贝与指针传递

在Go语言中,理解值拷贝与指针传递对编写高效、正确的程序至关重要。很多人刚接触Go时会对函数参数的传递方式产生误解,认为像切片或map是“引用传递”,其实Go中所有参数传递都是值拷贝,只是有时拷贝的是指针而已。

值拷贝:传递的是数据的副本

当一个变量以值的方式传入函数时,Go会创建该变量的一个副本。函数内部对参数的修改不会影响原始变量。

基本类型如 int、float、bool、string 以及结构体默认都是值拷贝:

type Person struct {
    Name string
    Age  int
}

func modifyPerson(p Person) {
    p.Name = "Alice"
    p.Age = 30
}

func main() {
    person := Person{Name: "Bob", Age: 25}
    modifyPerson(person)
    fmt.Println(person) // 输出 {Bob 25},原值未变
}

上面的例子中,modifyPerson 接收的是 person 的一份拷贝,内部修改不影响原始结构体。

指针传递:拷贝的是地址

要让函数能修改原始变量,需要传递变量的地址(即指针)。虽然这仍是“值拷贝”——拷贝的是指针的值,但由于指针指向同一块内存,因此可以通过它修改原数据。

func modifyPersonPtr(p *Person) {
    p.Name = "Alice"
    p.Age = 30
}

func main() {
    person := Person{Name: "Bob", Age: 25}
    modifyPersonPtr(&person)
    fmt.Println(person) // 输出 {Alice 30},原值被修改
}

这里传递的是 &person,即 person 的地址。函数接收 *Person 类型,通过指针访问并修改原始结构体。

特殊类型的行为:slice、map、channel

虽然 slice、map 和 channel 不是基本类型,但它们底层由指针封装。当你传递这些类型时,拷贝的是包含指针的结构体(如 slice header),所以它们能“间接”修改底层数组或数据结构。

func modifySlice(s []int) {
    s[0] = 999
}

func main() {
    data := []int{1, 2, 3}
    modifySlice(data)
    fmt.Println(data) // 输出 [999 2 3]
}

尽管是值拷贝,但拷贝的 slice 仍指向相同的底层数组,因此修改生效。但若在函数内重新分配 slice,外部不会感知:

func reassignSlice(s []int) {
    s = append(s, 4, 5, 6) // 可能触发扩容,指向新数组
}

// 调用后 data 长度仍为3,不受影响

如何选择:值还是指针?

决定使用值还是指针作为参数类型,主要考虑以下几点:

  • 是否需要修改原数据:需要修改就用指针
  • 数据大小:大结构体拷贝成本高,建议传指针
  • 一致性:如果方法集中有指针接收者,其他方法也建议用指针,避免混淆
  • nil 安全性:值接收者不会因 nil 指针而 panic,指针接收者需注意判空

基本上就这些。记住一句话:Go只有值拷贝,指针传递只是拷贝了地址。关键在于理解拷贝的内容是什么——是数据本身,还是指向数据的指针。

以上就是如何在Golang中理解值拷贝与指针传递的详细内容,更多请关注其它相关文章!


# 当你  # 如何做游戏推广营销号  # 新安县营销型网站建设  # 婚纱摄影全网推广营销  # 高要网站优化软件  # 安徽热点关键词排名  # 随州seo推广策划招聘  # 东阳seo全网营销价格  # 深圳外包营销推广多少钱  # seo网站优化多少钱一年合适  # 广东推广营销参考价格  # 相关文章  # 均为  # go  # 很多人  # 原值  # 移除  # 都是  # 数据结构  # 如何在  # 的是  # ai  # app  # go语言  # golang 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 邮政快递包裹最新位置 邮政快递实时追踪入口  win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】  J*aScript数组对象转换:按指定键分组与值收集  微信网页版登录教程_微信网页版登录入口在哪  如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension  Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录  顺丰快递查单号物流信息 顺丰快递小程序查询入口  J*aScript类型检查_j*ascript代码规范  支付宝碰一碰设备是REDMI手机吗 博主拆机辟谣:处理器、内存都不一样  响应式容器内容自动缩放与宽高比维持教程  包子漫画官方网站在线链接-包子漫画在线阅读平台主页地址  outlook中文官网入口地址 outlook官方中文版直达首页链接  《噬血代码2》新预告片发布 展示游戏剧情  AO3官网镜像链接 Archive of Our Own同人文在线浏览  邮编格式怎么匹配地址_根据邮编格式快速匹配详细地址的技巧  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  怎么去除衣服上的口红印_生活小妙招教你用酒精轻松擦除  QQ邮箱网页版入口页面 QQ邮箱在线登录入口官网  Go语言中动态执行代码字符串的策略与实践  UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】  提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  Discord Slash 命令响应超时问题的异步解决方案  在WordPress中通过REST API获取BasicAuth保护的远程文章  快手赚钱渠道_快手收益来源  c++如何使用std::memory_order控制原子操作顺序_c++ C++11内存模型详解  葱吃多了会怎样 葱吃多了会伤胃吗  怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】  UC浏览器网页版登录入口官网 电脑版网址入口  age动漫网站入口 age动漫官网直接访问入口  精准捕获:如何在页面中监听除特定元素外的所有点击事件  韩小圈电脑版在线入口_网页版免费登录地址  Win11怎么关闭触摸屏_Windows 11禁用HID符合标准触摸屏  4399体育竞技小游戏_4399小游戏赛事入口  在J*a项目里如何构建对象之间的契约_接口约束的实际落地  Go语言中对Map值调用带指针接收者方法:原理与最佳实践  php源码怎么在电脑上测试_电脑测试php源码方法步骤【教程】  品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程  淘宝网网页版登录入口 淘宝官方网页版快捷登录  如何在复杂的电商平台中优雅地管理共享资源并确保正确重定向,使用spryker-shop/resource-share-page模块助你一臂之力  Django模型中自动计算可用余额的实现方法  Android Studio计算器C键功能异常排查与修复教程  mcjs网页版在线存档 mcjs云存档登录入口  腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程  外媒分析《GTA6》定价:卖100美元可以但真没必要!  lar*el怎么安全地存储和获取配置文件中的敏感信息_lar*el敏感信息安全存储方法  PHP表单数据传递:如何通过隐藏输入字段获取动态ID  抓大鹅无需下载版 抓大鹅秒玩版入口  C++ map遍历方法大全_C++ map迭代器使用总结 

搜索