Go语言实践[回顾]教程06--通过时间判断时辰的示例【上】

示例项目的需求

  程序启动后,检测当前系统时间。根据时间不同,打印输出不同的信息内容:
  ● 23:00 点 ~ 1:00 点(不含1:00点),打印输出“现在是子时,俗称子夜”;
  ● 1:00 点 ~ 3:00 点(不含3:00点),打印输出“现在是丑时,俗称鸡鸣”;
  ● 3:00 点 ~ 5:00 点(不含5:00点),打印输出“现在是寅时,俗称黎明”;
  ● 5:00 点 ~ 7:00 点(不含7:00点),打印输出“现在是卯时,俗称破晓;
  ● 7:00 点 ~ 9:00 点(不含9:00点),打印输出“现在是辰时,俗称早晨;
  ● 9:00 点 ~ 11:00 点(不含11:00点),打印输出“现在是巳时,俗称上午;
  ● 11:00 点 ~ 13:00 点(不含13:00点),打印输出“现在是午时,俗称中午;
  ● 13:00 点 ~ 15:00 点(不含15:00点),打印输出“现在是未时,俗称日斜;
  ● 15:00 点 ~ 17:00 点(不含17:00点),打印输出“现在是申时,俗称日馎;
  ● 17:00 点 ~ 19:00 点(不含19:00点),打印输出“现在是酉时,俗称傍晚;
  ● 19:00 点 ~ 21:00 点(不含21:00点),打印输出“现在是戌时,俗称黄昏;
  ● 21:00 点 ~ 23:00 点(不含23:00点),打印输出“现在是亥时,俗称深夜;

实现示例需求的源代码

  实现一个项目需求,代码逻辑往往有很多种,下面就从最初实现到逐步优化的角度实践一下这个项目。

使用 if 判断逻辑实现的源代码

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	if now >= 23 || now < 1 {
		fmt.Println("现在是子时,俗称子夜")
	}
	if now >= 1 && now < 3 {
		fmt.Println("现在是丑时,俗称鸡鸣")
	}
	if now >= 3 && now < 5 {
		fmt.Println("现在是寅时,俗称黎明")
	}
	if now >= 5 && now < 7 {
		fmt.Println("现在是卯时,俗称破晓")
	}
	if now >= 7 && now < 9 {
		fmt.Println("现在是辰时,俗称早晨")
	}
	if now >= 9 && now < 11 {
		fmt.Println("现在是巳时,俗称上午")
	}
	if now >= 11 && now < 13 {
		fmt.Println("现在是午时,俗称中午")
	}
	if now >= 13 && now < 15 {
		fmt.Println("现在是未时,俗称日斜")
	}
	if now >= 15 && now < 17 {
		fmt.Println("现在是申时,俗称日馎")
	}
	if now >= 17 && now < 19 {
		fmt.Println("现在是酉时,俗称傍晚")
	}
	if now >= 19 && now < 21 {
		fmt.Println("现在是戌时,俗称黄昏")
	}
	if now >= 21 && now < 23 {
		fmt.Println("现在是亥时,俗称深夜")
	}
}

  上述代码编译运行,输出结果是正确的。下面解读一下代码中较之前示例新增的内容:

  ● 第9行,now 变量的值是 int 类型,因为 time.Now().Hour() 函数返回的是 0 ~ 23 的整数类型,表示当前时间是几点。与 time.Now().Hour() 类似的还有获取、年、月、日、分、秒等函数,在本节总结中会列出,还有常见的数据类型。

  ● 第12 ~ 47行,使用了12个 if 判断语句。可以看出,Go 语言的 if 判断语句省略了包裹判断条件的括号。与函数的格式一样,包裹条件成立执行代码块的花括号中的左花括号 { ,必须与 if 关键字及条件在同一行且必须在行尾。

  ● 第12行,判断条件有两个,使用的是 || 逻辑运算符,是 或 的关系。now 在第9行获得的最大值是23,最小值是0。所以判断子时的条件应该是大于等于23(也可以是等于 == 逻辑运算符,因为没有24和更大值了)或者小于1(因为需求中要求23点至1点之间,不包括1点整,为子时)。

  ● 第15行,判断条件也有两个,但是使用的是 && 逻辑运算符,是 并且 的关系。因为需求中要求1点至3点(不含3点),所以应该是大于等于1并且小于3(而不是小于等于3)。后面的几个判断条件原理相同。

使用 if else if 判断逻辑实现的源代码

  在上面代码中,12个判断是并列依次执行的。也就是无论如何12个判断都要执行一遍,即使第一个已经成立,那后面的11个判断依然要执行。每次运行程序,其实只能有一个判断的条件会成立,那这样也12个判断都要执行一遍的逻辑显然不是最优的选择。那么该如何优化呢?看下面的代码:

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	if now >= 1 && now < 3 {
		fmt.Println("现在是丑时,俗称鸡鸣")
	} else if now >= 3 && now < 5 {
		fmt.Println("现在是寅时,俗称黎明")
	} else if now >= 5 && now < 7 {
		fmt.Println("现在是卯时,俗称破晓")
	} else if now >= 7 && now < 9 {
		fmt.Println("现在是辰时,俗称早晨")
	} else if now >= 9 && now < 11 {
		fmt.Println("现在是巳时,俗称上午")
	} else if now >= 11 && now < 13 {
		fmt.Println("现在是午时,俗称中午")
	} else if now >= 13 && now < 15 {
		fmt.Println("现在是未时,俗称日斜")
	} else if now >= 15 && now < 17 {
		fmt.Println("现在是申时,俗称日馎")
	} else if now >= 17 && now < 19 {
		fmt.Println("现在是酉时,俗称傍晚")
	} else if now >= 19 && now < 21 {
		fmt.Println("现在是戌时,俗称黄昏")
	} else if now >= 21 && now < 23 {
		fmt.Println("现在是亥时,俗称深夜")
	} else {
		fmt.Println("现在是子时,俗称子夜")
	}
}

  上述代码编译运行,输出结果是正确的。

  经过这样优化后,12个独立的判断就合并成一组判断,只要有一个条件成立,就不会再执行这组中的其它判断,很显然,是 else 关键字的作用,这与其他大部分编程语言基本一致。

  第14、16、18、20、22、24、26、28、30、32行,都是使用的关键字 else if,意思是前面的条件如果不成立的话继续判断本行的条件是否成立。

  第34行,仅使用 else 关键字,意思是前面的条件不成立,那么就执行这里的代码。

使用 switch case 判断式逻辑实现的源代码

  在上面代码中,依然有12个 if 判断式,能不能简化一下使代码更易读呢?看下面的代码:

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	switch {
	case now >= 1 && now < 3:
		fmt.Println("现在是丑时,俗称鸡鸣")
	case now >= 3 && now < 5:
		fmt.Println("现在是寅时,俗称黎明")
	case now >= 5 && now < 7:
		fmt.Println("现在是卯时,俗称破晓")
	case now >= 7 && now < 9:
		fmt.Println("现在是辰时,俗称早晨")
	case now >= 9 && now < 11:
		fmt.Println("现在是巳时,俗称上午")
	case now >= 11 && now < 13:
		fmt.Println("现在是午时,俗称中午")
	case now >= 13 && now < 15:
		fmt.Println("现在是未时,俗称日斜")
	case now >= 15 && now < 17:
		fmt.Println("现在是申时,俗称日馎")
	case now >= 17 && now < 19:
		fmt.Println("现在是酉时,俗称傍晚")
	case now >= 19 && now < 21:
		fmt.Println("现在是戌时,俗称黄昏")
	case now >= 21 && now < 23:
		fmt.Println("现在是亥时,俗称深夜")
	default:
		fmt.Println("现在是子时,俗称子夜")
	}
}

  上述代码编译运行,输出结果是正确的。

  这次简化,使用 switch 判断取代了 if 判断,运行的结果是一样的。

  第12行,使用了 switch 关键字,且后面没有变量,直接是左花括号。这表示后面的判断分支 case 将是布尔值类型的值,真为条件成立,假为条件不成立。

  Go 语言的 switch 判断与其他语言类似,也是有一个 case 条件满足就不会再去判断其他 case,但也有些差别。switch 关键字后面可以没有变量,这时每个 case 后面就是布尔值(所以可以是判断式)为真则执行本段代码;当 switch 关键字后面有变量的时候, case 后面就是对应的值,变量等于该值则执行本段代码。default 的作用是所有条件都不成立时执行此段代码。

使用 switch 变量 case 值逻辑实现的源代码

  在上面代码中,与使用 if else if 相差不是很大,我们还可以使用 switch 变量 case 值 的形式进行判断,代码如下:

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	switch now {
	case 1, 2:
		fmt.Println("现在是丑时,俗称鸡鸣")
	case 3, 4:
		fmt.Println("现在是寅时,俗称黎明")
	case 5, 6:
		fmt.Println("现在是卯时,俗称破晓")
	case 7, 8:
		fmt.Println("现在是辰时,俗称早晨")
	case 9, 10:
		fmt.Println("现在是巳时,俗称上午")
	case 11, 12:
		fmt.Println("现在是午时,俗称中午")
	case 13, 14:
		fmt.Println("现在是未时,俗称日斜")
	case 15, 16:
		fmt.Println("现在是申时,俗称日馎")
	case 17, 18:
		fmt.Println("现在是酉时,俗称傍晚")
	case 19, 20:
		fmt.Println("现在是戌时,俗称黄昏")
	case 21, 22:
		fmt.Println("现在是亥时,俗称深夜")
	case 23, 0:
		fmt.Println("现在是子时,俗称子夜")
	}
}

  上述代码编译运行,输出结果是正确的。

  这次修改仍然使用 switch 关键字,区别是使用了swith 的另一种格式。

  第12行,在 switch 关键字后面加入了 now 变量,这里与大部分编程语言就几乎一样了。注意:这里变量不需要用括号包起来

  第13、15、17、19、21、23、25、27、29、31、33、35行,case 关键字后面可以是多个值,这样就相当于是 或 的关系,也就是变量 now 的值等于 case 后面的其中任何一个值都算条件成立,都会执行该段代码。这与大部分编程语言不一样,Go 语言这个比较灵活方便。

  这样修改后,感观上代码清晰了不少。

减少 fmt.Println() 函数使用次数的源代码

  在上面代码中,fmt.Println() 函数被使用了12次,且都是在判断结构中的同一位置,是否可以减少使用次数呢?看下面代码:

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	var info string

	switch now {
	case 1, 2:
		info = "现在是丑时,俗称鸡鸣"
	case 3, 4:
		info = "现在是寅时,俗称黎明"
	case 5, 6:
		info = "现在是卯时,俗称破晓"
	case 7, 8:
		info = "现在是辰时,俗称早晨"
	case 9, 10:
		info = "现在是巳时,俗称上午"
	case 11, 12:
		info = "现在是午时,俗称中午"
	case 13, 14:
		info = "现在是未时,俗称日斜"
	case 15, 16:
		info = "现在是申时,俗称日馎"
	case 17, 18:
		info = "现在是酉时,俗称傍晚"
	case 19, 20:
		info = "现在是戌时,俗称黄昏"
	case 21, 22:
		info = "现在是亥时,俗称深夜"
	case 23, 0:
		info = "现在是子时,俗称子夜"
	}

	fmt.Println(info)
}

  上述代码编译运行,输出结果是正确的。

  这次修改增加了第12行的内容,声明了一个字符串类型的局部变量 info,没有初始化赋值,那默认就是空字符串。然后在下面每个 case 里分别给变量 info 赋不同的值,最后在第41行使用一次 fmt.Println(info),就可以输出不同的信息了,因为实际打印输出的是变量 info 里的内容,而 info 里的内容是上面根据判断赋值的,不是一成不变的。

减少多次重复出现的字符串字面量的源代码

  在上面代码中,虽然减少了fmt.Println() 函数的使用次数,但可以看出“现在是”、“,俗称”重复出现了12次,且也都是在判断结构中的同一位置,是否也可以减少使用次数呢?看下面代码:

// test01 project main.go
package main

import (
	"fmt"
	"time"
)

var now = time.Now().Hour() // 返回的是int类型

func main() {
	var shiChen, suCheng string

	switch now {
	case 1, 2:
		shiChen = "丑时"
		suCheng = "鸡鸣"
	case 3, 4:
		shiChen = "寅时"
		suCheng = "黎明"
	case 5, 6:
		shiChen = "卯时"
		suCheng = "破晓"
	case 7, 8:
		shiChen = "辰时"
		suCheng = "早晨"
	case 9, 10:
		shiChen = "巳时"
		suCheng = "上午"
	case 11, 12:
		shiChen = "午时"
		suCheng = "中午"
	case 13, 14:
		shiChen = "未时"
		suCheng = "日斜"
	case 15, 16:
		shiChen = "申时"
		suCheng = "日馎"
	case 17, 18:
		shiChen = "酉时"
		suCheng = "傍晚"
	case 19, 20:
		shiChen = "戌时"
		suCheng = "黄昏"
	case 21, 22:
		shiChen = "亥时"
		suCheng = "深夜"
	case 23, 0:
		shiChen = "子时"
		suCheng = "子夜"
	}

	info := "现在是" + shiChen + ",俗称" + suCheng

	fmt.Println(info)
}

  上述代码编译运行,输出结果是正确的。

  这次修改是在第12行声明定义了两个字符串局部变量 shiChen 和 suCheng,分别代表 时辰名 和 俗称,声明后没有初始化,会默认为空字符串,然后在下面的每个 case 里分别给这两个变量赋相应的字符串值。到第53行,将 “现在是”、变量 shiChen、“,俗称”、变量 suCheng 四个字符串拼接到一起后,赋值给新声明的变量 info,然后在第55行输出这个最后保存合并内容的变量 info,就得到了想要的完整信息内容。Go 语言中字符串拼接可以直接使用加号 “+” 完成

  也可以将第53行等号右侧的代码复制,然后替换掉第55行函数中的参数 info,这样就可以删除53行代码,程序执行结果也是正常的。

  本节对“通过时间判断时辰的示例”先探讨到这里,下一节中将继续实践。

本节小结

  下是对本节涉及的 Go 语言编程内容的归纳总结,方便记忆:

  ● 基础数据类型见下表(本例中没有用到的也一并列出了)

类型说明
bool布尔true / false通常代表 真/假、有/无、是/否、1/0等
string字符串字节序列UTF-8 字符序列,ASCII 码表中字符占 1 个字节,其它字符占用 2-4 个字节,汉字三个字节
int整数32位 或 64位 有符号有正负数 ,长度随系统
int8整数8位 有符号有正负数 ,长度8位,-128 ~ 127
int16整数16位 有符号有正负数 ,长度16位,-32768 ~ 32767
int32整数32位 有符号有正负数 ,长度32位,-2147483648 ~ 2147483647
int64整数64位 有符号有正负数 ,长度64位,-9223372036854775808 ~ 9223372036854775807
uint整数32位 或 64位 无符号无负数 ,长度随系统
uint8整数8位 无符号无负数 ,长度8位,0 ~ 255
uint16整数16位 无符号无负数 ,长度16位,0 ~ 65535
uint32整数32位 无符号无负数 ,长度32位,0 ~ 4294967295
uint64整数64位 无符号无负数 ,长度64位,0 ~ 18446744073709551615
uintptr整数无符号无负数 ,一个能足够容纳指针位数大小的整数类型
byte字节8位 无符号uint8 的别名 ,用于表示一个字节
rune符文32位 无符号uint32 的别名 ,用于表示一个Unicode 码
float32单精度32位 有符号单精度浮点数,占用32位长度
float64双精度64位 有符号双精度浮点数,占用64位长度
complex6464位复数64位 有符号由两个float32构成,一个表示实部,一个表示虚部
complex128128位复数128位 有符号由两个float64构成,一个表示实部,一个表示虚部

  ● 变量声明时如果没有初始化赋值,那么默认布尔类型为 false,字符串类型为 空字符串,整数类型为 0 ,浮点数类型为 0.0,指针类型为 nil(空值,也就是未赋值的意思)。

  ● time包中类似 time.Now().Hour() 的常用函数有以下这些:

函数返回值功能说明
time.Now().Year()2022等获取当前年份
time.Now().Month()1 ~ 12获取当前月份
time.Now().Day()1-31获取当前日期
time.Now().Hour()0-23获取当前小时
time.Now().Minute()0-59获取当前分钟
time.Now().Second()0-59获取当前秒

  ● 逻辑判断 if 与 if else 及 if else if 也是判断 if 后面的条件是否成立,如果成立就执行紧跟其后的花括号包裹的代码段。但是条件部分不需要用小括号了,且左花括号必须与 if 关键字及条件表达式在同一行。else 也是表示上面判断不成立则执行这里的代码段的含义。

   ● 逻辑判断 swith case 除了 swith 变量,然后用户 case 值 匹配这种写法外,还可以 swith 不带任何变量,在 case 后面写逻辑表达式或布尔值,哪个条件成立或为真就进入哪个代码段,其他的 case 不在去执行匹配判断。在使用 swith 变量 这种格式时,变量也不需要用括号包起来。

   ● 多个字符串拼接直接使用加号 + 即可按照顺序拼接成一个新的字符串。

   ● 代码中多次出现重复的代码,是可以优化掉的,通常通过创建变量、函数、包的办法,然后共用他们。
.
.
上一节:Go/Golang语言学习实践[回顾]教程05–深入实践第一个Go语言示例

下一节:Go/Golang语言学习实践[回顾]教程07–通过时间判断时辰的示例【中】
.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学为所用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值