- 示例工程
- 教程
【免费下载链接】learngo
❤️ 1000+ Hand-Crafted Go Examples, Exercises, and Quizzes. 🚀 Learn Go by fixing 1000+ tiny programs.
赋值(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) }这段代码揭示了赋值三条基本规则:
- 赋值必须类型匹配:
counter是int,只能赋整数;注释中的counter = "ten"会编译报错(Go 是强类型语言,赋值不做隐式类型转换); - 赋值改变变量的值:
counter = 10把原来的零值0覆盖为10; - 赋值后变量可继续参与运算:
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) }这里的关键是赋值语句右侧的表达式先求值,再写入左侧变量:
- 计算
"dark " + color:字符串拼接操作符+把"dark "与color当前值"green"串联成"dark green"; - 把新值复制给
color; - 输出
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.go | solution |
| 2 | 变量到变量 | 表达式中复用变量 | 02-vars-to-vars/main.go | solution |
| 3 | 用表达式赋值 | 算术表达式赋值 | 03-assign-with-expressions/main.go | solution |
| 4 | 求矩形周长 | 分组声明后赋值 | 04-find-the-rectangle-perimeter/main.go | solution |
| 5 | 多重赋值 | 一次赋值两个变量 | 05-multi-assign/main.go | solution |
| 6 | 多重赋值 #2 | 一次赋值三类变量 | 06-multi-assign-2/main.go | solution |
| 7 | 多重简短函数 | 多返回值 + 空白标识符 | 07-multi-short-func/main.go | solution |
| 8 | 交换器 | 多重赋值改写值 | 08-swapper/main.go | solution |
| 9 | 交换器 #2 | 无临时变量交换 | 09-swapper-2/main.go | solution |
| 10 | 丢弃文件 | path.Split+ 丢弃返回值 | 10-discard-the-file/main.go | solution |
每个练习目录内都包含一个带 TODO 注释的main.go(挑战版)与solution/main.go(完整解法)。运行方式:进入任一练习目录后执行go run main.go或go run solution/main.go,即可对照期望输出验证结果。
十一、小结:赋值的五条实战法则
回顾全部练习,可提炼出 Go 赋值最实用的五条法则:
- 赋值即复制:
=把右侧的值复制进左侧变量,类型必须匹配; - 先求值后写入:右侧表达式(包括引用变量自身)总是先完整计算,再更新左侧;
- 多重赋值并行:
a, b = x, y一一对应赋值,是交换两个变量(a, b = b, a)的最简方式; - 多返回值天生配对:函数多返回值可直接用多重赋值接收,
_用于丢弃不需要的值; =与:=分工明确:新变量用:=声明并赋值,已有变量只能用=。
如果你想继续深挖变量声明的更多细节,可以接着学习同一章节的声明与短声明练习;若想验证自己对多重赋值、强类型转换的理解,还可以尝试仓库根目录下对应的英文练习集(10 个练习一一对应)。赋值是通往 Go 一切编程能力的起点——吃透"复制、并行、丢弃"这三个关键词,后续的切片、结构体与函数参数传递都会事半功倍。
- 示例工程
- 教程
【免费下载链接】learngo
❤️ 1000+ Hand-Crafted Go Examples, Exercises, and Quizzes. 🚀 Learn Go by fixing 1000+ tiny programs.
相关推荐
qiankun 微前端框架快速入门:安装、注册与启动实战指南
qiankun 微前端框架快速入门:安装、注册与启动实战指南 导读 :本文以 qiankun(乾坤)微前端框架的官方快速开始文档为骨架,系统讲解从安装、在主应用
示例工程教程学习 Go 赋值(Assignment):基于 learngo 仓库 10 道实战练习彻底掌握变量赋值
学习 Go 赋值(Assignment):基于 learngo 仓库 10 道实战练习彻底掌握变量赋值 本指南以 06 variables/04 assignm
示例工程教程Go 变量赋值(Assignment)完全指南:基于 learngo 仓库的语法、类型规则与实战练习
Go 变量赋值(Assignment)完全指南:基于 learngo 仓库的语法、类型规则与实战练习 导读 本文以 learngo 仓库中 06 variabl
示例工程教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考