Go语言第三章(五谷轮回)

北冥神功(太玄经)

go 复制代码
package main

import "fmt"

type Person struct {
	Name string
	Age  int
	Sex  string
}

func main() {
	person := Person{
		Name: "张三",
		Age:  18,
		Sex:  "男",
	}
	if person.Age >= 18 {
		fmt.Println("成年")
	} else {
		fmt.Println("未成年")
	}
}

我们定义了一个 Person 结构体,包含 NameAgeSex 三个字段。然后创建了一个实例,判断其年龄是否满 18 岁:满 18 岁输出「成年」,否则输出「未成年」。这就是最基本的 if / else 二选一判断。

多条件判断

go 复制代码
package main

import "fmt"

type Person struct {
	Status string
}

func main() {
	person := Person{
		Status: "在线",
	}
	if person.Status == "在线" {
		fmt.Println("在线")
	} else if person.Status == "离线" {
		fmt.Println("离线")
	} else if person.Status == "忙碌" {
		fmt.Println("忙碌")
	} else {
		fmt.Println("未知状态")
	}
}

当需要处理三种及以上 的分支时,可以在 if 后面连续使用 else if,从上到下依次判断,命中第一个为真的分支后就不再往下执行 。最后的 else 用于兜底,处理所有未匹配的情况。

上面示例模拟了用户在线状态:Status 为「在线」「离线」「忙碌」时分别输出对应文字,其他值则输出「未知状态」。

同样的逻辑,用 switch 写会更简洁------把要判断的值写在 switch 后面,每个 case 对应一种取值:

go 复制代码
package main

import "fmt"

type Person struct {
	Status string
}

func main() {
	person := Person{
		Status: "在线",
	}
	switch person.Status {
	case "在线":
		fmt.Println("在线")
	case "离线":
		fmt.Println("离线")
	case "忙碌":
		fmt.Println("忙碌")
	default:
		fmt.Println("未知状态")
	}
}

switch 会拿 person.Status 与每个 case 逐一比较,匹配到就执行对应分支。Go 的 switch 默认不会穿透 到下一个 case(不需要写 break)。所有 case 都不匹配时,执行 default 分支。

写法 适用场景
if / else if 条件各不相同,不好抽成一个表达式
switch 表达式 同一个值匹配多种固定取值(如状态、等级、星期)

逻辑嵌套

go 复制代码
package main

import "fmt"

type Person struct {
	Name string
	Age  int
	Sex  string
}

func main() {
	person := Person{
		Name: "张三",
		Age:  18,
		Sex:  "男",
	}
	if person.Age >= 18 {
		if person.Sex == "男" {
			fmt.Println("成年男性")
		} else {
			fmt.Println("成年女性")
		}
	} else {
		fmt.Println("未成年")
		if person.Sex == "男" {
			fmt.Println("未成年男性")
		} else {
			fmt.Println("未成年女性")
		}
	}
}

多个if条件判断可以嵌套使用,我们首先判断年龄是否等于18,如果等于18,则再判断性别是否等于"男",如果等于"男",则输出"成年男性",否则输出"成年女性"。如果不等于18,则输出"未成年",再判断性别是否等于"男",如果等于"男",则输出"未成年男性",否则输出"未成年女性"。这就是一个基本的逻辑嵌套。当然也不是只能嵌套两层,可以嵌套多层,但是要注意逻辑的正确性。

逻辑运算符

判断条件经常需要组合多个表达式,常用的逻辑运算符如下:

运算符 含义 示例 为真条件
&& 并且 a && b ab 都为真
` ` 或者
! 取反 !a a 为假

并且(&&

go 复制代码
age := 18
sex := "男"

if age >= 18 && sex == "男" {
	fmt.Println("成年男性")
}

&& 表示并且:左右两边条件都为真,整个表达式才为真。上面只有「年满 18 岁」且「性别为男」时,才会打印「成年男性」。

或者(||

go 复制代码
age := 33

if age == 18 || age == 19 {
	fmt.Println("18 岁或 19 岁")
} else {
	fmt.Println("其他年龄")
}

|| 表示或者 :左右两边只要有一个为真,整个表达式就为真。上面当年龄是 18 19 时走 if 分支,否则走 else

取反(!

go 复制代码
isLogin := false

if !isLogin {
	fmt.Println("请先登录")
}

! 把布尔值反过来!truefalse!falsetrue。常用于「不满足某条件时」的分支判断。

作业

  1. 基础判断 :声明一个 int 类型的分数变量,用 if / else if / else 判断等级:90 分及以上为「优秀」,60~89 为「及格」,60 分以下为「不及格」,并打印结果。
  2. switch 练习 :定义一个 string 变量表示星期几(如 "周一"),用 switch 匹配并打印对应提示;未匹配时走 default,输出「无效的星期」。
  3. 状态判断 :参照文中的 Person 结构体,将 Status 分别设为「在线」「离线」「忙碌」和一个自定义值,分别运行 if / else ifswitch 两个版本,观察输出是否一致。
  4. 逻辑运算符 :声明 agehasTicket 两个变量,用 && 判断「年满 18 岁且已购票」方可入场;再改用 || 判断「会员或年龄大于 60 岁」可享受优惠,分别打印结果。
  5. 综合练习 :定义包含 NameAgeScore 的结构体,结合 if 嵌套判断:年满 18 且分数不低于 60 才输出「合格」,否则输出「不合格」,并带上姓名。

五谷轮回

Go 里只有一种循环关键字:for 。没有 while、也没有 do-while,所有循环形态都靠 for 表达。

普通 for 循环

我们声明了一个切片,用经典的「初始化;条件;步进」写法遍历:

go 复制代码
package main

import "fmt"

func main() {
	var hobbys = []string{"吃饭", "睡觉", "打豆豆"}
	for i := 0; i < len(hobbys); i++ {
		fmt.Println(hobbys[i])
	}
}

for 后面分成三段,用分号隔开:

部分 作用 上面示例
初始化 循环开始前执行一次 i := 0
条件 每次循环前判断,为真才继续 i < len(hobbys)
步进 每次循环体结束后执行 i++

输出依次为:吃饭睡觉打豆豆

三段都可以省略。只留条件时,就相当于其他语言里的 while

go 复制代码
package main

import "fmt"

func main() {
	i := 0
	for i < 3 {
		fmt.Println(i)
		i++
	}
}

条件也省略时,就是无限循环 ,需要靠 break 自己跳出:

go 复制代码
package main

import "fmt"

func main() {
	i := 0
	for {
		fmt.Println(i)
		i++
		if i >= 3 {
			break
		}
	}
}

range 循环

遍历切片、数组、字符串、map、channel 时,更常用 range,写法更简洁:

go 复制代码
package main

import "fmt"

func main() {
	var hobbys = []string{"吃饭", "睡觉", "打豆豆"}
	for index, hobby := range hobbys {
		fmt.Println(index, hobby)
	}
}

range 每次迭代会返回两个值:

  • 第一个是下标(或 map 的 key)
  • 第二个是对应的元素值

输出为:

text 复制代码
0 吃饭
1 睡觉
2 打豆豆

如果只要值、不要下标,用 _ 丢掉第一个返回值:

go 复制代码
for _, hobby := range hobbys {
	fmt.Println(hobby)
}

如果只要下标、不要值,写一个变量即可:

go 复制代码
for index := range hobbys {
	fmt.Println(index)
}

遍历 map

go 复制代码
package main

import "fmt"

func main() {
	person := map[string]string{
		"name": "张三",
		"city": "杭州",
	}
	for key, value := range person {
		fmt.Println(key, value)
	}
}

注意:map 的遍历顺序不固定,每次运行打印顺序可能不同。

遍历字符串

go 复制代码
package main

import "fmt"

func main() {
	text := "你好Go"
	for index, char := range text {
		fmt.Printf("下标 %d,字符 %c\n", index, char)
	}
}

range 遍历字符串时,拿到的是 Unicode 码点(rune),不是单个字节。像「你」「好」这种汉字各占 3 个字节,下标会按字节位置跳着走。

写法 适用场景
for i := 0; i < len(x); i++ 需要精确控制下标、步长,或从中间开始/倒序遍历
for i, v := range x 顺序遍历切片、数组、字符串、map

break 与 continue

循环中经常要「提前结束」或「跳过本次」:

关键字 含义
break 立刻跳出当前循环
continue 跳过本次剩余代码,进入下一次循环

break:跳出循环

go 复制代码
package main

import "fmt"

func main() {
	hobbys := []string{"吃饭", "睡觉", "打豆豆"}
	for _, hobby := range hobbys {
		if hobby == "睡觉" {
			break
		}
		fmt.Println(hobby)
	}
}

遇到「睡觉」就 break,后面的元素不再遍历。输出只有:吃饭

continue:跳过本次

go 复制代码
package main

import "fmt"

func main() {
	hobbys := []string{"吃饭", "睡觉", "打豆豆"}
	for _, hobby := range hobbys {
		if hobby == "睡觉" {
			continue
		}
		fmt.Println(hobby)
	}
}

遇到「睡觉」就 continue,跳过打印,但循环继续。输出为:吃饭打豆豆

带标签的 break

多层循环嵌套时,普通 break 只跳出最内层。若要一次跳出外层,可以给循环加标签

go 复制代码
package main

import "fmt"

func main() {
Outer:
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			if i == 1 && j == 1 {
				break Outer
			}
			fmt.Println(i, j)
		}
	}
}

break Outer 会直接跳出名为 Outer 的那一层循环。continue 也可以配合标签使用,表示跳到指定循环的下一次迭代。

goto

goto 可以跳转到同一函数内的某个标签位置。能用,但可读性往往更差,日常代码里更推荐 break / continue / return

go 复制代码
package main

import "fmt"

func main() {
	i := 0
Loop:
	fmt.Println(i)
	i++
	if i < 3 {
		goto Loop
	}
}

上面用 goto 模拟了一个简单循环:打印 012。实际项目中除非处理错误清理这类特殊场景,否则尽量少用。

作业

  1. 普通 for :声明一个 110 的循环,打印所有偶数。
  2. range 练习 :定义切片 []string{"春", "夏", "秋", "冬"},分别用「只要下标」「只要值」「下标+值」三种 range 写法打印。
  3. break / continue :遍历 120,遇到能被 3 整除的数就 continue 跳过;一旦遇到大于 15 的数就 break 结束。观察最终打印了哪些数。
  4. 类 while :用「只写条件」的 for(不要初始化段和步进段)计算 1 + 2 + ... + 100 的和并打印。
  5. 综合练习 :定义 map[string]int 表示各科分数(如语文、数学、英语),用 range 遍历:低于 60 的科目打印「不及格」,其余打印「及格」,并统计及格科目数量。
相关推荐
霸道流氓气质5 小时前
SpringBoot中通用工具类库(Utils)封装与使用实践
spring boot·后端·python
MemoleCard8 小时前
深度解析Java当中的锁机制
后端
wear工程师9 小时前
ThreadLocal 在线程池里为什么会串数据:别只会答内存泄漏
java·后端
whyfail9 小时前
前端学 Spring Boot(2):一次点击,如何穿过整个后端?
前端·spring boot·后端
程序员cxuan11 小时前
Loop 还没玩明白,Graph Engineering 又火了。
人工智能·后端·程序员
uzong12 小时前
把一面面试总结做成一个 Skill:重复的事,就别每次都重写
后端·面试
程序员海军12 小时前
一个 AI 应用开发程序员的一天,都在屏幕前忙些什么?
前端·后端·程序员
不能放弃治疗12 小时前
MCP
后端