Go语言的一些练习题

前言

最近又开始拾起Go语言了,记录一些练习题吧。

先用自己的想法编写好(即优化前的代码),然后通过AI去帮我优化代码,并且指出原代码潜在问题与风险,给出优化后的代码。加深自己的代码技术

这里我用的阿里云的通义灵码以及Claude对代码进行优化。

练习1

要求:

  1. 循环打印输入的月份的天数 【使用continue实现】

  2. 需要判断输入的月份是否错误的语句

  3. 实现效果如下:

优化前的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
"fmt"
"time"
)

func main() {
var year int
var months time.Month
var day int
for {
fmt.Printf("请输入年份:")
fmt.Scanln(&year)
if year < 0 { // 这里假设年份不能为负数,可以根据实际需求修改条件
fmt.Println("输入的年份有误")
continue
}
fmt.Printf("请输入月份:")
fmt.Scanln(&months)
if int(months) > 12 || int(months) < 1{
fmt.Println("输入的月份有误")
continue
}
fmt.Printf("请输入日期:")
fmt.Scanln(&day)
if day > 31 || day < 1{
fmt.Println("输入的日期有误")
continue
}
// 创建日期对象
daysInMonth := time.Date(year, months+1, 0, 0, 0, 0, 0, time.UTC).Day()
// 获取这个月有多少天
fmt.Printf("你输入的是%d年%d月%d日, 这个月有%d天\n", year, months, day, daysInMonth)
break
}
}

优化重构后的代码

  1. 函数抽象与模块化: 将年份有效性检查、月份有效性检查、日期有效性检查分别封装为独立的函数:checkYear、checkMonth和checkDay,这使得代码结构更清晰,易于阅读和维护。
  2. 单独提取获取月份天数的方法: 引入了getDaysInMonth函数,用于获取给定年份和月份的最大天数。这个改进避免了在多个地方重复相同的计算逻辑,提高了代码复用性。
  3. 更精确的输入验证: 在提示用户输入日期时,使用getDaysInMonth动态计算并显示月份的最大天数,确保用户输入的有效性提示更准确。
  4. 简化年份检查: checkYear函数进行了简化,只检查年份是否大于等于0,而不再关心是否为闰年,这是因为本代码片段并不需要处理因闰年带来的日期变化。
  5. 增强用户体验: 当用户输入错误时,提示信息包含了具体的期望输入范围,比如在提示输入日期时明确指出应输入1到指定月份天数之间的整数。
  6. 保持功能不变: 优化后的代码依然保留了原有的核心功能,即接收用户输入的年份、月份和日期,并检查其有效性,最后输出相关信息。在整个过程中,没有改变输入/输出形式和程序内部处理逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main

import (
"fmt"
"time"
)

// 检查年份输入是否有效
func checkYear(year int) bool {
if year >= 0 {
return true
} else {
return false
}
}

// 检查月份是否有效
func checkMonth(month time.Month) bool {
if int(month) > 12 || int(month) < 1 {
return false
} else {
return true
}
}

// 检查日期是否有效
func checkDay(day int, month time.Month) bool {
maxDays := time.Date(2000, month, 0, 0, 0, 0, 0, time.UTC).Day() // 使用给定的年份和月份计算最大天数
return day >= 1 && day <= maxDays
}

// getDaysInMonth 获取给定年份和月份的天数
func getDaysInMonth(year int, month time.Month) int {
return time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()
}


func main() {
var year int
var month time.Month
var day int
for {
fmt.Printf("请输入年份:")
fmt.Scanln(&year)
if !checkYear(year) {
fmt.Println("输入的年份有误")
continue
}

fmt.Printf("请输入月份(1-12):")
var m int
fmt.Scanln(&m)
month = time.Month(m)
if !checkMonth(month) {
fmt.Println("输入的月份有误, 请输入1到12之间的整数")
continue
}
fmt.Printf("请输入日期(1-%d):", getDaysInMonth(year, month))
fmt.Scanln(&day)
if !checkDay(day, month) {
fmt.Println("输入的日期有误, 请输入1到", getDaysInMonth(year, month), "之间的整数")
continue
}
// 输入有效,输出结果
fmt.Printf("你输入的是%d年%d月%d日, 这个月有%d天\n", year, month, day, getDaysInMonth(year, month))
break
}
}

实现效果

练习2

要求:

编写一个函数:

随机猜数游戏:

  1. 随机生成一个1 – 100的整数
  2. 有十次机会如果第一次就猜中,提示“你真是个天才”
  3. 如果第2一一3次猜中,提示“你很聪明,赶上我了”
  4. 如果第4一一9次猜中,提示“一般般”
  5. 如果最后一次猜中,提示“可算猜对啦”
  6. 一次都没猜对,提示“说你点啥好呢”

优化前的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package main

import (
"fmt"
"math/rand"
)

func main() {
//随机生成一个1 - 100的整数
var num int = 0
var yourNum int
for {
num = rand.Intn(100) + 1
if num >= 1 && num <= 100 {
break
}
}
// fmt.Println("随机数为:", num)
fmt.Println("请输入你猜测的数字(共有十次机会哦!):")
fmt.Scanln(&yourNum)
count := 10
for {
if yourNum == num {
if count == 10 {
fmt.Println("你他娘真是个天才!")
}
if count > 7 && count < 10 {
fmt.Println("你很聪明,赶上我了!")
} else if count > 1 && count < 6 {
fmt.Println("一般般!")
} else if count == 1 {
fmt.Println("可算猜对啦!")
}
break
} else if yourNum > num {
fmt.Println("你猜的数字太大了!")
fmt.Println("你还有", count-1, "次机会!")
count--
if count == 0 {
fmt.Println("说你点啥好呢!")
break
}
fmt.Scanln(&yourNum)
} else if yourNum < num {
fmt.Println("你猜的数字太小了!")
fmt.Println("你还有", count-1, "次机会!")
count--
if count == 0 {
fmt.Println("说你点啥好呢!")
break
}
fmt.Scanln(&yourNum)
}
}
}

原代码潜在问题与风险

  1. 代码逻辑: 你的代码逻辑整体上是没有太大问题的,但是存在一些小的逻辑判断可以进行优化,比如当用户猜对数字时,对不同次数的猜测给出了不同的反馈,这个逻辑判断区域可以稍微整理一下,合并一些重复的条件判断会更清晰。
  2. 随机数生成:使用 rand.Intn(100) + 1 生成 1-100 的随机数是正确的,但需要注意的是 rand.Intn 是基于当前时间的种子生成的随机数,如果多次快速执行程序可能会得到相同的随机数序列。虽然在大多数应用场景下这不会成为问题,但如果需要更随机的随机数,可以考虑使用更复杂的随机数生成方式。
  3. 异常处理:当前代码中没有对 fmt.Scanln(&yourNum) 的输入进行校验,理论上用户可以输入非数字的内容,这可能会导致程序崩溃或行为异常。建议增加输入校验的逻辑。
  4. 边界条件处理:虽然你已经处理了猜测次数为0的情况,但没有对用户输入的数字进行边界检查,即用户可以输入超出1-100范围的数字。应该增加对用户输入数字的合法性校验。

优化方向

  1. 性能效率:当前程序性能主要受循环和条件判断影响,对于这个简单的程序来说,性能已经足够。但若想提升性能,可以考虑减少不必要的循环(例如当前随机数生成的循环,其实可以通过更优的方式一次性生成符合要求的随机数)和条件判断。
  2. 可维护性
  • 将魔术数字(如100、10等)定义为常量或变量,这样在需要修改游戏规则时,只需要在一个地方修改,就可以影响整个程序的行为,这会提高代码的可读性和可维护性。
  • 提取重复代码块,例如在用户猜错时,提示还有多少次机会和减少次数的逻辑是重复的,可以将其提取到一个函数中,减少代码冗余。
  • 增加注释,尤其是对一些复杂的逻辑判断或者算法进行解释,方便他人(或未来的你)更快地理解代码的意图。
  1. 代码风格:虽然代码的风格与性能和可维护性直接关系不大,但保持良好的代码风格(如Go语言的代码风格指南)可以让代码更易读、易懂,从而间接影响到代码的维护性和可合作性。

优化重构后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package main

import (
"fmt"
"math/rand"
"time"
)

const (
maxNum = 100 //最大数字
maxAttempts = 10 //最大次数
)

func main() {
// 初始化随机数生成器
rand.Seed(time.Now().UnixNano())
// 随机生成1-100的整数
num := getRandomNum()
fmt.Println("生成的随机数为:", num)
fmt.Println("请输入你猜测的数字(共有", maxAttempts, "次机会哦!):")
// 提示用户输入猜测的数字
yourNum, attempts := readUserInput(), maxAttempts
for attempts > 0 {
result := calculateResult(num, yourNum)
if result {
givePraise(maxAttempts - attempts + 1)
break
}
fmt.Println("你还有", attempts-1, "次机会哦!")
fmt.Println("请再猜一次")
yourNum, attempts = readUserInput(), attempts-1
}
if attempts == 0 {
fmt.Println("说你点啥好呢! 游戏结束!")
}
}

// 生成1-100的随机数
func getRandomNum() int {
return rand.Intn(maxNum) + 1
}

// 读取用户输入的数字,并进行简单的校验
func readUserInput() int {
var yourNum int
fmt.Scanln(&yourNum)
if yourNum < 1 || yourNum > maxNum {
fmt.Println("输入的数字不在1到", maxNum, "之间,请重新输入:")
fmt.Scanln(&yourNum)
}
return yourNum
}

// calculateResult 函数用于判断用户猜测的数字是否与目标数字相等。
// 参数 num 为目标数字,yourNum 为用户猜测的数字。
// 返回值为 bool 类型,当用户猜测的数字与目标数字相等时返回 true,否则返回 false。
func calculateResult(num, yourNum int) bool {
// 比较用户猜测的数字与目标数字的大小
if yourNum > num {
fmt.Println("你猜的数字太大了,请重新输入:")
} else if yourNum < num {
fmt.Println("你猜的数字太小了,请重新输入:")
} else {
return true
}
return false
}

// 根据猜测次数给出不同的赞扬
func givePraise(attempts int) {
switch {
case attempts == 1:
fmt.Println("===============")
fmt.Println("你他娘真是个天才!")
case attempts > 1 && attempts <= 3:
fmt.Println("===============")
fmt.Println("你很聪明,赶上我了!")
case attempts > 3 && attempts <= 7:
fmt.Println("===============")
fmt.Println("一般般!")
case attempts > 7:
fmt.Println("===============")
fmt.Println("可算猜对啦!")
}
}

实现效果

练习3

编写一个函数:输出100以内的所有素数(素数就只能被1和本身整除的数),每行显示5个;并求和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import "fmt"

func main() {
sum := 0
count := 0
for i := 2; i <= 100; i++ {
if isPrime(i) {
sum += i
count++
fmt.Printf("%d ", i)
if count%5 == 0 {
fmt.Println()
}
}
}
fmt.Println("\n100以内素数的和为:", sum)
}

func isPrime(n int) bool {
if n <= 1 {
return false
}
for i := 2; i*i <= n; i++ {
if n%i == 0 {
return false
}
}
return true
}

练习4

编写一个函数,判断是打鱼还是晒网:

中国有句俗语叫“三天打鱼两天晒网”。如果从1990年1月1日起开始执行“三天打鱼两天晒网”。如何判断在以后的某一天中是“打鱼”还是“晒网”?

PS:这题其实可以和练习1结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"time"
)

func main() {
start := time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)
target := time.Date(2024, 4, 3, 0, 0, 0, 0, time.UTC) // 输入目标日期

duration := target.Sub(start)
days := int(duration.Hours() / 24)

cycle := days % 5
switch cycle {
case 0, 1, 2:
fmt.Println("打鱼")
case 3, 4:
fmt.Println("晒网")
}
}

优化前的代码(与练习1结合)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package main

import (
"fmt"
"time"
)

// 检查年份输入是否有效
func checkYear(year int) bool {
if year >= 0 {
return true
} else {
return false
}
}

// 检查月份是否有效
func checkMonth(month time.Month) bool {
if int(month) > 12 || int(month) < 1 {
return false
} else {
return true
}
}

// 检查日期是否有效
func checkDay(day int, month time.Month) bool {
maxDays := time.Date(2000, month, 0, 0, 0, 0, 0, time.UTC).Day() // 使用给定的年份和月份计算最大天数
return day >= 1 && day <= maxDays
}

// getDaysInMonth 获取给定年份和月份的天数
func getDaysInMonth(year int, month time.Month) int {
return time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()
}

func main() {
var year int
var month time.Month
var day int
for {
fmt.Printf("请输入年份:")
fmt.Scanln(&year)
if !checkYear(year) {
fmt.Println("输入的年份有误")
continue
}

fmt.Printf("请输入月份(1-12):")
var m int
fmt.Scanln(&m)
month = time.Month(m)
if !checkMonth(month) {
fmt.Println("输入的月份有误, 请输入1到12之间的整数")
continue
}
fmt.Printf("请输入日期(1-%d):", getDaysInMonth(year, month))
fmt.Scanln(&day)
if !checkDay(day, month) {
fmt.Println("输入的日期有误, 请输入1到", getDaysInMonth(year, month), "之间的整数")
continue
}
// 输入有效,输出结果
fmt.Printf("你输入的是%d年%d月%d日, 这个月有%d天\n", year, month, day, getDaysInMonth(year, month))
break
}
start := time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)
// 获取输入的日期
target := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
target_day := target.Format("2006/01/02")
duration := target.Sub(start)
days := int(duration.Hours() / 24)
cycle := days % 5
switch cycle {
case 0, 1, 2:
fmt.Println("请注意:", target_day, "需要打鱼")
case 3, 4:
fmt.Println("请注意:", target_day, "需要晒网")
}
}

代码优化方向

  1. 年份检查:调整checkYear函数,确保年份至少不小于1900,这个值根据实际应用场景可能需要进一步调整。
  2. 闰年处理:在getDaysInMonth函数中加入了闰年的判断逻辑,确保2月份的天数能够在闰年时正确处理。
  3. 性能优化:通过直接在getDaysInMonth函数中使用time.Date来计算天数,避免了之前可能的重复计算。
  4. 代码简化:在checkYear和checkMonth函数中去掉了if else结构,直接返回判断结果,使代码更为简洁。
  5. 强化输入校验:虽然原代码未明确显示如何处理非法输入类型,但通过加强checkYear、checkMonth和checkDay的逻辑,确保只有符合规则的输入才会被接受,这在一定程度上避免了类型错误的问题。

优化重构后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main

import (
"fmt"
"time"
)

// 检查年份输入是否有效
func checkYear(year int) bool {
// 调整年份检查范围,例如确保年份不小于1900
return year >= 1900
}

// 检查月份是否有效
func checkMonth(month time.Month) bool {
// 简化布尔表达式
return int(month) >= 1 && int(month) <= 12
}

// 检查日期是否有效
func checkDay(day int, month time.Month, year int) bool {
// 考虑闰年影响
maxDays := getDaysInMonth(month, year)
return day >= 1 && day <= maxDays
}

// getDaysInMonth 获取给定年份和月份的天数
func getDaysInMonth(month time.Month, year int) int {
// 直接使用time包计算天数,避免创建额外的时间对象
if month == 2 {
if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
return 29
}
}
return time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()
}

func main() {
var year int
var month time.Month
var day int
for {
fmt.Printf("请输入年份:")
fmt.Scanln(&year)
if !checkYear(year) {
fmt.Println("输入的年份有误")
continue
}

fmt.Printf("请输入月份(1-12):")
var m int
fmt.Scanln(&m)
month = time.Month(m)
if !checkMonth(month) {
fmt.Println("输入的月份有误, 请输入1到12之间的整数")
continue
}
fmt.Printf("请输入日期(1-%d):", getDaysInMonth(month, year))
fmt.Scanln(&day)
if !checkDay(day, month, year) {
fmt.Println("输入的日期有误, 请输入1到", getDaysInMonth(month, year), "之间的整数")
continue
}
// 输入有效,输出结果
fmt.Printf("你输入的是%d年%d月%d日, 这个月有%d天\n", year, month, day, getDaysInMonth(month, year))
break
}
start := time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)
// 获取输入的日期
target := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
target_day := target.Format("2006/01/02")
duration := target.Sub(start)
days := int(duration.Hours() / 24)
cycle := days % 5
switch cycle {
case 0, 1, 2:
fmt.Println("请注意:", target_day, "需要打鱼")
case 3, 4:
fmt.Println("请注意:", target_day, "需要晒网")
}
}

实现效果

练习5

要求:

编写一个小小计算器,其中 10和5固定,也可将10和5设置为输入变量

打印如下效果:

————————–小小计算器————————–

  1. 加法
  2. 减法
  3. 乘法
  4. 除法
  5. 退出

请选择: 1

10+5=15

流程图

流程图

优化前的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package main

import "fmt"

/*
todoList:
1. 优化main()
*/
// 计算器列表
func calculatorList() {
fmt.Println("==========小小计算器==========")
fmt.Println("1.加法")
fmt.Println("2.减法")
fmt.Println("3.乘法")
fmt.Println("4.除法")
fmt.Println("5.退出")
fmt.Println("请选择:")
}

// 识别选择的操作
func checkInput(a int) int {
fmt.Scanln(&a)
// 如果不在1-5的范围内,提示输入错误
if int(a) > 5 || int(a) < 1 {
fmt.Println("输入有误,请重新输入(输入范围为:1-5)")
return checkInput(a)
// 返回输入的数
} else if int(a) == 5 {
// 返回5,并接受程序的运行
fmt.Println("退出程序")
return 5
} else {
return a
}
}

// 判断是否要继续
func checkContinue() bool {
var b int
fmt.Println("是否继续(1.是 2.否)")
fmt.Scanln(&b)
if b == 1 {
fmt.Println("继续计算")
return true
} else {
fmt.Println("退出程序")
return false
}
}

// 识别输入需要计算的两个数字
func checkNums(num1 float64, num2 float64) (float64, float64) {
fmt.Println("请输入需要计算的第一个数字:")
fmt.Scanln(&num1)
fmt.Println("请输入需要计算的第二个数字:")
fmt.Scanln(&num2)
return num1, num2
}

// 计算
func calculator(num1 float64, num2 float64, operator byte) float64 {
var result float64
switch operator {
case 1:
result = num1 + num2
fmt.Printf("进行加法运算...\n结果为:\n%.2f + %.2f = %.2f\n", num1, num2, result)
case 2:
result = num1 - num2
fmt.Printf("进行减法运算...\n结果为:\n%.2f - %.2f = %.2f\n", num1, num2, result)
case 3:
result = num1 * num2
fmt.Printf("进行乘法运算...\n结果为:\n%.2f * %.2f = %.2f\n", num1, num2, result)
case 4:
for num2 == 0 {
fmt.Println("除数不能为0, 请重新输入第二个数字")
fmt.Scanln(&num2)
if num2 != 0 {
result = num1 / num2
fmt.Printf("进行除法运算...\n结果为:\n%.2f / %.2f = %.2f\n", num1, num2, result)
}
}
if num2 != 0 {
result = num1 / num2
fmt.Printf("进行除法运算...\n结果为:\n%.2f / %.2f = %.2f\n", num1, num2, result)
}
case 5:
fmt.Println("退出")
break
}
return result
}

func main() {
// 1. 打印计算器功能列表
calculatorList()
// 2. 根据选择的操作进行计算
for {
var a int
var num1 float64
var num2 float64
a = checkInput(a)
if a == 5 {
break
}
num1, num2 = checkNums(num1, num2)
// 输出计算结果
result := calculator(num1, num2, byte(a))
if result == 0 {
break
}
if checkContinue() == false {
break
} else {
calculatorList()
}
}
}

潜在问题及风险提示

  1. 输入循环: 在checkInput函数中,如果用户输入的不是1到5之间的数字,程序会提示错误并重新要求输入。这个逻辑可能会导致无限循环,如果用户持续输入无效数据。一个改进方案是限制尝试输入的次数,超过次数则程序自动退出。
  2. 除数为零的处理: 在进行除法运算时,程序确实检查了除数是否为零。但这个检查发生在循环内,如果用户连续输入0作为除数,程序会不断提示重新输入,这可能不是最佳用户体验。更好的做法是在checkNums函数里就进行除数为零的检查,并直接返回错误或提示信息,避免进入除法运算。
  3. 强制类型转换: 在checkInput函数中,a原本就是int类型,无需再次进行int(a)的转换。直接使用a进行比较和操作即可。
  4. break语句的使用: 在calculator函数中,使用了break语句直接退出循环。这会导致函数提前结束,而不会打印结果。考虑到函数的设计,可能更适合使用return语句来结束函数。
  5. 边界情况处理: 当用户选择进行除法运算时,程序没有明确处理除数持续为0的情况,这可能导致程序卡住或出现未定义行为。

优化建议

  1. 性能优化: 目前程序的性能瓶颈不明显,因为它的计算任务相对简单。但为了提高性能,可以考虑优化输入输出的部分,比如使用bufio.Scanner代替fmt.Scanln以提高读取输入的效率。
  2. 可读性提升:
  • 函数命名可以更具体一些。例如,checkInput可以改为getOperationChoice,以更清晰地反映其功能。
  • 在calculator函数中,对每个case的处理可以封装成独立的函数,如performAddition,performSubtraction等,这样可以提高代码的可读性和可维护性。
  1. 错误处理: 目前程序对错误的处理较为简单,通常只是打印一条信息。可以考虑引入更详细的错误处理机制,比如返回错误代码或使用错误日志记录详细错误信息,以便于问题追踪和调试。
  2. 代码重构: 考虑将主循环中的逻辑分解成更小的函数或方法,这样不仅可以提高代码的可读性,还可以使得代码更容易维护和扩展。例如,可以引入一个processCalculation函数来处理从获取操作选择到执行计算的整个流程。
  3. 使用更高级的Go特性: 随着你对Go语言的进一步了解,可以考虑使用一些更高级的特性来优化代码,如使用flag包处理命令行输入,使用fmt的更高级格式化功能来简化输出等。

优化重构后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

/*
todoList:
1. 优化main()
*/
// 计算器列表
func printCalculatorList() {
fmt.Println("==========小小计算器==========")
fmt.Println("1.加法")
fmt.Println("2.减法")
fmt.Println("3.乘法")
fmt.Println("4.除法")
fmt.Println("5.退出")
fmt.Println("请选择:")
}

// 获取用户的操作
func getOperationChoice() int {
scanner := bufio.NewScanner(os.Stdin)
fmt.Printf("请输入需要计算的操作(1-5):")
scanner.Scan()
a, err := strconv.Atoi(scanner.Text())
if err != nil || a < 1 || a > 5 {
fmt.Println("输入有误,请重新输入(输入范围为:1-5)")
return getOperationChoice()
}
if a == 5 {
fmt.Println("退出程序")
}
return a
}

// 判断是否要继续
func checkContinue() bool {
var response string
fmt.Println("是否继续(1.是 2.否)")
fmt.Scanln(&response)
return strings.TrimSpace(response) == "1"
}

// 识别输入需要计算的两个数字
func getNumbers() (float64, float64) {
var num1, num2 float64
fmt.Println("请输入需要计算的第一个数字:")
fmt.Scanln(&num1)
fmt.Println("请输入需要计算的第二个数字:")
fmt.Scanln(&num2)
return num1, num2
}

// 计算
func performCalculation(num1, num2 float64, operator byte) float64 {
var result float64
switch operator {
case 1:
result = num1 + num2
fmt.Printf("进行加法运算...\n结果为:\n%.2f + %.2f = %.2f\n", num1, num2, result)
case 2:
result = num1 - num2
fmt.Printf("进行减法运算...\n结果为:\n%.2f - %.2f = %.2f\n", num1, num2, result)
case 3:
result = num1 * num2
fmt.Printf("进行乘法运算...\n结果为:\n%.2f * %.2f = %.2f\n", num1, num2, result)
case 4:
if num2 == 0 {
fmt.Println("除数不能为0")
return 0
}
result = num1 / num2
fmt.Printf("进行除法运算...\n结果为:\n%.2f / %.2f = %.2f\n", num1, num2, result)
}
return result
}

func main() {
for {
printCalculatorList()
var a int
var num1, num2 float64
a = getOperationChoice()
if a == 5 {
break
}
num1, num2 = getNumbers()
// 输出计算结果
result := performCalculation(num1, num2, byte(a))
if result == 0 {
break
}
if checkContinue() == false {
break
}
}
}

实现效果

计算器效果


Go语言的一些练习题
https://suiyideali.github.io/2024/04/03/Go语言的一些练习题/
作者
m0ch4z
发布于
2024年4月3日
更新于
2024年4月23日
许可协议