Go语言的一些练习题
前言
最近又开始拾起Go语言了,记录一些练习题吧。
先用自己的想法编写好(即优化前的代码),然后通过AI去帮我优化代码,并且指出原代码潜在问题与风险,给出优化后的代码。加深自己的代码技术
这里我用的阿里云的通义灵码以及Claude对代码进行优化。
练习1
要求:
循环打印输入的月份的天数 【使用continue实现】
需要判断输入的月份是否错误的语句
实现效果如下:
优化前的代码
1 |
|
优化重构后的代码
- 函数抽象与模块化: 将年份有效性检查、月份有效性检查、日期有效性检查分别封装为独立的函数:checkYear、checkMonth和checkDay,这使得代码结构更清晰,易于阅读和维护。
- 单独提取获取月份天数的方法: 引入了getDaysInMonth函数,用于获取给定年份和月份的最大天数。这个改进避免了在多个地方重复相同的计算逻辑,提高了代码复用性。
- 更精确的输入验证: 在提示用户输入日期时,使用getDaysInMonth动态计算并显示月份的最大天数,确保用户输入的有效性提示更准确。
- 简化年份检查: checkYear函数进行了简化,只检查年份是否大于等于0,而不再关心是否为闰年,这是因为本代码片段并不需要处理因闰年带来的日期变化。
- 增强用户体验: 当用户输入错误时,提示信息包含了具体的期望输入范围,比如在提示输入日期时明确指出应输入1到指定月份天数之间的整数。
- 保持功能不变: 优化后的代码依然保留了原有的核心功能,即接收用户输入的年份、月份和日期,并检查其有效性,最后输出相关信息。在整个过程中,没有改变输入/输出形式和程序内部处理逻辑。
1 |
|
实现效果
练习2
要求:
编写一个函数:
随机猜数游戏:
- 随机生成一个1 – 100的整数
- 有十次机会如果第一次就猜中,提示“你真是个天才”
- 如果第2一一3次猜中,提示“你很聪明,赶上我了”
- 如果第4一一9次猜中,提示“一般般”
- 如果最后一次猜中,提示“可算猜对啦”
- 一次都没猜对,提示“说你点啥好呢”
优化前的代码
1 |
|
原代码潜在问题与风险
- 代码逻辑: 你的代码逻辑整体上是没有太大问题的,但是存在一些小的逻辑判断可以进行优化,比如当用户猜对数字时,对不同次数的猜测给出了不同的反馈,这个逻辑判断区域可以稍微整理一下,合并一些重复的条件判断会更清晰。
- 随机数生成:使用 rand.Intn(100) + 1 生成 1-100 的随机数是正确的,但需要注意的是 rand.Intn 是基于当前时间的种子生成的随机数,如果多次快速执行程序可能会得到相同的随机数序列。虽然在大多数应用场景下这不会成为问题,但如果需要更随机的随机数,可以考虑使用更复杂的随机数生成方式。
- 异常处理:当前代码中没有对 fmt.Scanln(&yourNum) 的输入进行校验,理论上用户可以输入非数字的内容,这可能会导致程序崩溃或行为异常。建议增加输入校验的逻辑。
- 边界条件处理:虽然你已经处理了猜测次数为0的情况,但没有对用户输入的数字进行边界检查,即用户可以输入超出1-100范围的数字。应该增加对用户输入数字的合法性校验。
优化方向
- 性能效率:当前程序性能主要受循环和条件判断影响,对于这个简单的程序来说,性能已经足够。但若想提升性能,可以考虑减少不必要的循环(例如当前随机数生成的循环,其实可以通过更优的方式一次性生成符合要求的随机数)和条件判断。
- 可维护性:
- 将魔术数字(如100、10等)定义为常量或变量,这样在需要修改游戏规则时,只需要在一个地方修改,就可以影响整个程序的行为,这会提高代码的可读性和可维护性。
- 提取重复代码块,例如在用户猜错时,提示还有多少次机会和减少次数的逻辑是重复的,可以将其提取到一个函数中,减少代码冗余。
- 增加注释,尤其是对一些复杂的逻辑判断或者算法进行解释,方便他人(或未来的你)更快地理解代码的意图。
- 代码风格:虽然代码的风格与性能和可维护性直接关系不大,但保持良好的代码风格(如Go语言的代码风格指南)可以让代码更易读、易懂,从而间接影响到代码的维护性和可合作性。
优化重构后的代码
1 |
|
实现效果
练习3
编写一个函数:输出100以内的所有素数(素数就只能被1和本身整除的数),每行显示5个;并求和
1 |
|
练习4
编写一个函数,判断是打鱼还是晒网:
中国有句俗语叫“三天打鱼两天晒网”。如果从1990年1月1日起开始执行“三天打鱼两天晒网”。如何判断在以后的某一天中是“打鱼”还是“晒网”?
PS:这题其实可以和练习1结合
1 |
|
优化前的代码(与练习1结合)
1 |
|
代码优化方向
- 年份检查:调整checkYear函数,确保年份至少不小于1900,这个值根据实际应用场景可能需要进一步调整。
- 闰年处理:在getDaysInMonth函数中加入了闰年的判断逻辑,确保2月份的天数能够在闰年时正确处理。
- 性能优化:通过直接在getDaysInMonth函数中使用time.Date来计算天数,避免了之前可能的重复计算。
- 代码简化:在checkYear和checkMonth函数中去掉了if else结构,直接返回判断结果,使代码更为简洁。
- 强化输入校验:虽然原代码未明确显示如何处理非法输入类型,但通过加强checkYear、checkMonth和checkDay的逻辑,确保只有符合规则的输入才会被接受,这在一定程度上避免了类型错误的问题。
优化重构后的代码
1 |
|
实现效果
练习5
要求:
编写一个小小计算器,其中 10和5固定,也可将10和5设置为输入变量
打印如下效果:
————————–小小计算器————————–
- 加法
- 减法
- 乘法
- 除法
- 退出
请选择: 1
10+5=15
流程图

优化前的代码
1 |
|
潜在问题及风险提示
- 输入循环: 在checkInput函数中,如果用户输入的不是1到5之间的数字,程序会提示错误并重新要求输入。这个逻辑可能会导致无限循环,如果用户持续输入无效数据。一个改进方案是限制尝试输入的次数,超过次数则程序自动退出。
- 除数为零的处理: 在进行除法运算时,程序确实检查了除数是否为零。但这个检查发生在循环内,如果用户连续输入0作为除数,程序会不断提示重新输入,这可能不是最佳用户体验。更好的做法是在checkNums函数里就进行除数为零的检查,并直接返回错误或提示信息,避免进入除法运算。
- 强制类型转换: 在checkInput函数中,a原本就是int类型,无需再次进行int(a)的转换。直接使用a进行比较和操作即可。
- break语句的使用: 在calculator函数中,使用了break语句直接退出循环。这会导致函数提前结束,而不会打印结果。考虑到函数的设计,可能更适合使用return语句来结束函数。
- 边界情况处理: 当用户选择进行除法运算时,程序没有明确处理除数持续为0的情况,这可能导致程序卡住或出现未定义行为。
优化建议
- 性能优化: 目前程序的性能瓶颈不明显,因为它的计算任务相对简单。但为了提高性能,可以考虑优化输入输出的部分,比如使用bufio.Scanner代替fmt.Scanln以提高读取输入的效率。
- 可读性提升:
- 函数命名可以更具体一些。例如,checkInput可以改为getOperationChoice,以更清晰地反映其功能。
- 在calculator函数中,对每个case的处理可以封装成独立的函数,如performAddition,performSubtraction等,这样可以提高代码的可读性和可维护性。
- 错误处理: 目前程序对错误的处理较为简单,通常只是打印一条信息。可以考虑引入更详细的错误处理机制,比如返回错误代码或使用错误日志记录详细错误信息,以便于问题追踪和调试。
- 代码重构: 考虑将主循环中的逻辑分解成更小的函数或方法,这样不仅可以提高代码的可读性,还可以使得代码更容易维护和扩展。例如,可以引入一个processCalculation函数来处理从获取操作选择到执行计算的整个流程。
- 使用更高级的Go特性: 随着你对Go语言的进一步了解,可以考虑使用一些更高级的特性来优化代码,如使用flag包处理命令行输入,使用fmt的更高级格式化功能来简化输出等。
优化重构后的代码
1 |
|
实现效果
Go语言的一些练习题
https://suiyideali.github.io/2024/04/03/Go语言的一些练习题/