Go无while/do-while和三元运算符;if与for可省括号但花括号不可省,且if支持初始化语句(如if err:=f(); err!=nil{...}),变量作用域限于对应分支;for是唯一循环结构,有类C、while、无限循环三种形式。

Go 里没有 while、do-while,也不支持三元运算符;if 和 for 的括号可以省,但花括号不能省——这是写错最多的地方。
Go 的 if 语句必须带花括号,且支持初始化语句
常见错误是照搬其他语言习惯,写成 if x > 0 { ... } else { ... } 看似正常,但一旦漏掉花括号(比如只有一行想省略),编译直接报错:syntax error: unexpected else, expecting }。
Go 要求所有分支都必须用花括号包裹,哪怕只有一行。另外,if 后可紧跟初始化语句,变量作用域仅限该 if 块:
if err := someFunc(); err != nil {
log.Fatal(err)
} else if n := len(data); n == 0 {
fmt.Println("empty")
}
- 初始化语句和条件表达式之间用分号隔开,不是逗号
-
err和n在各自分支外不可访问,避免污染外层作用域 - 不支持
if x > 0 ? a : b这类三元写法,得用完整if/else
for 是 Go 唯一的循环结构,三种写法对应不同场景
Go 没有 while 或 do-while,所有循环都靠 for 实现。它有三种合法形式,本质都是同一语法糖的不同展开:
立即学习“go语言免费学习笔记(深入)”;
Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统
// 1. 类 C 风格(带初始化、条件、后置)
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// 2. 类 while 风格(只有条件)
for count < 10 {
count++
}
// 3. 无限循环(等价于 for ;;)
for {
select {
case msg := <-ch:
handle(msg)
case <-done:
break
}
}
- 第二种写法容易被误认为“缺少分号就报错”,其实只要条件表达式存在,就合法
- 第三种常用于 goroutine 中配合
select,但记得用break退出时要加标签才能跳出多层嵌套 - 遍历切片/映射/通道请用
range,不是for i = 0; i ——后者在并发中可能 panic,且无法感知底层变化
switch 默认自动 break,且支持类型断言和条件表达式
Go 的 switch 不会穿透(fallthrough 需显式写出),而且 case 可以是任意可比较类型或布尔表达式:
switch v := x.(type) {
case int:
fmt.Printf("int: %d", v)
case string:
fmt.Printf("string: %s", v)
default:
fmt.Printf("unknown type: %T", v)
}
- 类型开关(
x.(type))只能用于接口类型,且v是具体值,不是类型名 - 普通 switch 也可以写条件:
switch { case x > 0 && y ,此时 case 后是布尔表达式,不需要switch后跟值 - 想穿透必须写
fallthrough,且它必须是 case 最后一条语句,后面不能有 return 或 break
控制流中的常见陷阱:作用域、空分支、defer 执行时机
这些细节不报错,但行为常和预期不符:
-
if或for内部定义的变量,在外部不可见;但若在顶层作用域多次用:=声明同名变量(如循环内),会报no new variables on left side of := - 空分支(如
if cond {} else {})合法,但容易掩盖逻辑缺失,建议用panic或日志占位 -
defer在函数返回前执行,不是块结束时——这意味着for循环里的defer会在整个函数结束才批量触发,不是每次迭代都执行
最易忽略的是 range 遍历时对切片元素取地址:所有迭代共享同一个变量地址,导致最后全指向最后一个元素。要存地址,得在循环内显式拷贝:val := val; ptr := &val。









