news 2026/10/4 1:42:54

Go 语言赋值实战:复制语义、多重赋值与交换技巧(learngo 练习全解)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Go 语言赋值实战:复制语义、多重赋值与交换技巧(learngo 练习全解)
  • 示例工程
  • 教程

【免费下载链接】learngo

❤️ 1000+ Hand-Crafted Go Examples, Exercises, and Quizzes. 🚀 Learn Go by fixing 1000+ tiny programs.

项目地址:https://gitcode.com/gh_mirrors/le/learngo
点击查看免费下载

赋值(Assignment)是 Go 语言中每个变量操作的基础动作。本篇以 learngo 仓库中《06-变量 / 04-赋值》练习集为核心,通过 10 个由浅入深的迷你程序,系统讲解 Go 的赋值语义(赋值即"复制值")、表达式赋值、多重赋值、变量交换与空白标识符丢弃返回值等核心技巧。学完本篇,你将能准确区分声明与赋值、熟练写出可运行的赋值代码,并理解path.Split、多返回值函数等标准库用法背后的赋值原理。

一、赋值的本质:一切皆为复制

在 Go 中,赋值意味着"复制"值。当你执行a = b时,b中的值被复制一份写入a,此后二者互不影响。这一点在后续学习切片、结构体等复合类型时同样成立(复制的是整个值),是理解 Go 内存模型的第一块基石。

先看一段演示赋值的教学源码 06-variables/04-assignment/01-overview/main.go:

package main import "fmt" func main() { var counter int fmt.Println("counter's name : counter") fmt.Println("counter's value:", counter) fmt.Printf("counter's type : %T\n", counter) counter = 10 // OK // counter = "ten" // NOT OK fmt.Println("counter's value:", counter) counter++ fmt.Println("counter's value:", counter) }

这段代码揭示了赋值三条基本规则:

  1. 赋值必须类型匹配:counter是int,只能赋整数;注释中的counter = "ten"会编译报错(Go 是强类型语言,赋值不做隐式类型转换);
  2. 赋值改变变量的值:counter = 10把原来的零值0覆盖为10;
  3. 赋值后变量可继续参与运算:counter++等价于counter = counter + 1,输出最终为11。

二、练习 1:让它变蓝(Make It Blue)—— 最朴素的赋值

第一个练习只要求修改一个字符串变量的值。挑战文件在 translation/chinese/06-变量/04-赋值/练习/01-make-it-blue/main.go,它给了你一个注释掉的声明:

// color := "green" // 在下面写上你的代码: // ?

去掉注释并补上赋值,参考解法见 01-make-it-blue/solution/main.go:

package main import "fmt" func main() { color := "green" color = "blue" fmt.Println(color) }

要点:

  • color := "green"是短变量声明(声明 + 初始化合一步);
  • color = "blue"是纯赋值:变量已存在,只需用=覆盖旧值,不能再写:=;
  • 程序输出blue,证明赋值确实把内存里的值替换掉了。

三、练习 2:变量到变量(Vars to Vars)—— 在赋值表达式中引用变量

第二个练习故意设置限制:不允许直接写color = "dark green",而必须"用变量自己给自己赋值"。挑战见 02-vars-to-vars/main.go,解法在 02-vars-to-vars/solution/main.go:

package main import "fmt" func main() { color := "green" // `"dark " + color` 是一个表达式 color = "dark " + color fmt.Println(color) }

这里的关键是赋值语句右侧的表达式先求值,再写入左侧变量:

  1. 计算"dark " + color:字符串拼接操作符+把"dark "与color当前值"green"串联成"dark green";
  2. 把新值复制给color;
  3. 输出dark green。

由于赋值右侧先于左侧更新求值,用变量自身参与运算(累加、拼接、自增)是安全的,这是 Go 中常见的惯用法。

四、练习 3:用表达式赋值(Assign with Expressions)—— 让结果来自计算

第三个练习演示如何把一段算术表达式的计算结果赋给变量。挑战文件 03-assign-with-expressions/main.go 预先声明了一个float64变量:

// 声明一个新的 float64 变量 // 0. 代表 0.0 n := 0.

解法见 03-assign-with-expressions/solution/main.go:

package main import "fmt" func main() { n := 0. n = 3.14 * 2 fmt.Println(n) }

输出6.28。两个细节值得注意:

  • 3.14 * 2是乘法表达式,运算结果6.28(浮点数)被整体复制给n;
  • 字面量0.表示浮点数0.0,Go 允许省略小数点后的0。

五、练习 4:求矩形周长(Find the Rectangle's Perimeter)—— 分组声明后赋值

这个练习引入了var分组声明,要求先算后赋。挑战见 04-find-the-rectangle-perimeter/main.go,其模板为:

var ( perimeter int width, height = 5, 6 )

解法在 04-find-the-rectangle-perimeter/solution/main.go:

package main import "fmt" func main() { var ( perimeter int width, height = 5, 6 ) // 首先计算: (宽 + 高) // 然后: 用 2 与它相乘 perimeter = 2 * (width + height) fmt.Println(perimeter) }

要点:

  • 周长公式2 × (宽 + 高)中,括号优先级与数学一致,先加后乘,结果为22;
  • perimeter声明时只给类型int(零值0),随后用赋值语句填充计算结果;
  • width, height = 5, 6是分组声明里的多变量初始化,一次为两个变量赋值,与后面要讲的多重赋值一脉相承。

六、练习 5 与 6:多重赋值(Multi Assign)—— 一次赋值多个变量

Go 支持一条语句同时给多个变量赋值。练习 5 挑战见 05-multi-assign/main.go,解法在 05-multi-assign/solution/main.go:

package main import "fmt" func main() { var ( lang string version int ) lang, version = "go", 2 fmt.Println(lang, "version", version) }

练习 6 更进一步,一次赋三种不同类型的值,解法见 06-multi-assign-2/solution/main.go:

package main import "fmt" func main() { var ( planet string isTrue bool temp float64 ) planet, isTrue, temp = "Mars", true, 19.5 fmt.Println("Air is good on", planet) fmt.Println("It's", isTrue) fmt.Println("It is", temp, "degrees") }

多重赋值的规则:

  • 左侧变量与右侧值一一对应、位置匹配:planet得"Mars"、isTrue得true、temp得19.5;
  • 左右两侧数量必须一致,否则编译报错;
  • 不同变量可以拥有不同静态类型,Go 会在编译期逐一检查类型匹配。

这也呼应了教学示例 06-variables/04-assignment/05-multiple-assignment/main.go 中的用法——speed, now = 100, time.Now()同时赋一个int和一个time.Time。

七、练习 7:多重简短函数(Multi Short Func)—— 多返回值与空白标识符

函数可以返回多个值,配合简短赋值一次性接收。挑战见 07-multi-short-func/main.go,解法在 07-multi-short-func/solution/main.go:

package main import "fmt" func main() { _, b := multi() fmt.Println(b) } func multi() (int, int) { return 5, 4 }

核心知识点:

  • multi()声明了两个返回值(int, int),调用时返回5, 4;
  • _, b := multi()用空白标识符_丢弃第一个返回值5,把第二个值4赋给b;
  • 输出4。

这是 Go 处理"只关心部分返回值"的标准姿势,也是下面练习 10 的前置铺垫。

八、练习 8 与 9:交换器(Swapper)—— 零临时变量交换

多重赋值最大的价值之一:无需临时变量即可交换两个变量的值。

练习 8 要求先赋值再交换为新值,解法见 08-swapper/solution/main.go:

package main import "fmt" func main() { color, color2 := "red", "blue" color, color2 = "orange", "green" fmt.Println(color, color2) }

练习 9 则要求真正交换red与blue的当前值,解法在 09-swapper-2/solution/main.go:

package main import "fmt" func main() { red, blue := "red", "blue" red, blue = blue, red fmt.Println(red, blue) }

red, blue = blue, red是整篇练习的"点睛之笔":Go 保证多重赋值先并行求值右侧全部表达式,再统一写入左侧变量,因此右侧的blue与red读到的都是交换前的旧值,执行后两个变量完成互换,无需任何中间变量。输出为blue red。

同样的模式也出现在教学示例 06-variables/04-assignment/06-swapping/main.go 中:

speed, prevSpeed = prevSpeed, speed

九、练习 10:丢弃文件(Discard the File)—— 结合标准库path.Split

最后一个练习把赋值、多返回值与空白标识符合在一起实战。挑战见 10-discard-the-file/main.go,解法在 10-discard-the-file/solution/main.go:

package main import ( "fmt" "path" ) func main() { dir, _ := path.Split("secret/file.txt") fmt.Println(dir) }

说明:

  • 标准库path包的Split函数返回(dir, file)两个字符串,把路径拆成目录与文件名两部分;
  • dir, _ := path.Split(...)用_丢弃文件名部分,只保留目录"secret/";
  • 程序输出secret/。

教学示例 06-variables/04-assignment/08-path-project-discarding/main.go 演示了反向需求——丢弃目录、保留文件名:

var file string _, file = path.Split("css/main.css") fmt.Println("file:", file) // 输出: main.css

若两个返回值都需要,也可以全部接收:

dir, file := path.Split("css/main.css")

见 06-variables/04-assignment/09-path-project-shortdecl/main.go。这里还应注意=与:=的区别:变量已声明(var file string)时用=赋值;全新变量则用:=声明并赋值。

十、练习总览与运行方式

下表汇总全部 10 个练习及其相对仓库根目录的路径:

序号练习主题挑战文件参考解法
1让它变蓝基本字符串赋值01-make-it-blue/main.gosolution
2变量到变量表达式中复用变量02-vars-to-vars/main.gosolution
3用表达式赋值算术表达式赋值03-assign-with-expressions/main.gosolution
4求矩形周长分组声明后赋值04-find-the-rectangle-perimeter/main.gosolution
5多重赋值一次赋值两个变量05-multi-assign/main.gosolution
6多重赋值 #2一次赋值三类变量06-multi-assign-2/main.gosolution
7多重简短函数多返回值 + 空白标识符07-multi-short-func/main.gosolution
8交换器多重赋值改写值08-swapper/main.gosolution
9交换器 #2无临时变量交换09-swapper-2/main.gosolution
10丢弃文件path.Split+ 丢弃返回值10-discard-the-file/main.gosolution

每个练习目录内都包含一个带 TODO 注释的main.go(挑战版)与solution/main.go(完整解法)。运行方式:进入任一练习目录后执行go run main.go或go run solution/main.go,即可对照期望输出验证结果。

十一、小结:赋值的五条实战法则

回顾全部练习,可提炼出 Go 赋值最实用的五条法则:

  1. 赋值即复制:=把右侧的值复制进左侧变量,类型必须匹配;
  2. 先求值后写入:右侧表达式(包括引用变量自身)总是先完整计算,再更新左侧;
  3. 多重赋值并行:a, b = x, y一一对应赋值,是交换两个变量(a, b = b, a)的最简方式;
  4. 多返回值天生配对:函数多返回值可直接用多重赋值接收,_用于丢弃不需要的值;
  5. =与:=分工明确:新变量用:=声明并赋值,已有变量只能用=。

如果你想继续深挖变量声明的更多细节,可以接着学习同一章节的声明与短声明练习;若想验证自己对多重赋值、强类型转换的理解,还可以尝试仓库根目录下对应的英文练习集(10 个练习一一对应)。赋值是通往 Go 一切编程能力的起点——吃透"复制、并行、丢弃"这三个关键词,后续的切片、结构体与函数参数传递都会事半功倍。

  • 示例工程
  • 教程

【免费下载链接】learngo

❤️ 1000+ Hand-Crafted Go Examples, Exercises, and Quizzes. 🚀 Learn Go by fixing 1000+ tiny programs.

项目地址:https://gitcode.com/gh_mirrors/le/learngo
点击查看免费下载

相关推荐

上一篇:推荐文章:深度解析PostgreSQL查询计划的利器 —— Postgres Explain Visualizer(pev)
下一篇:探索未来浏览方式:Neko虚拟浏览器项目深度解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 1:39:35

PHP 核心机制解析:FastCGI 与 PHP-FPM

在深入探讨 FastCGI 与 PHP-FPM 之前,需要先梳理 PHP 的运行环境及其与 Web 服务器的交互原理, 本文参考了关于 mod_php、mod_fastcgi 与 php-fpm 的对比分析,以及 Nginx 实战配置等相关资料,旨在系统性地解析这些核心概念 1.Web 服务器与 PH…

作者头像 李华
网站建设 2026/10/4 1:39:01

AOCV签核实战:物理变异建模与三维时序修正技术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华