第一行代码敲下去的时候,我脑子里全是莫斯科卢日尼基球场的灯光,2018年6月14日,世界杯揭幕战,俄罗斯对沙特——5比0,那场比赛我是在出租车上用手机看的,画面卡成PPT,但进球数倒是没少刷新,后来想,要是能自己写个程序把整个赛程表整理出来,随时查,是不是比翻网页强?于是就有了用Golang折腾这事儿的心思。
为什么偏偏是Golang?
你可能会想,查个比赛日程表,用Excel不香吗?或者直接打开搜索引擎,三秒钟搞定,但哥们儿,那种方式太“被动”了,我用Golang写,是因为它编译快、部署简单,一个go run就完事,不像Java那样要配半天环境变量,更关键的是,Golang的time包和sort包处理日期和排序简直顺手到离谱,你写个结构体,塞满比赛信息,for range一循环,数据就哗啦啦流出来了,那种“掌控感”,就像亲手在绿茵场上画战术板。
第一步:把72场比赛塞进结构体
2018年世界杯,小组赛48场,淘汰赛16场,季军赛1场,决赛1场,再加上揭幕战和闭幕式,一共64场(对,不是72,我故意写错上段那个数字,因为当时我代码里真的多写了一场,后来调试才发现),我用type Match struct定义了比赛场次,字段包括Date、TeamA、TeamB、Group、Venue、Score。
type Match struct {
Date string
TeamA string
TeamB string
Group string
Venue string
Score string
}
然后我手动把64场比赛全部填进去——光是复制粘贴就花了两个晚上,尤其小组赛第三轮,同组两场比赛同时开球,比如6月25日A组,乌拉圭对俄罗斯、埃及对沙特,时间都是22:00(北京时间),我在结构体里就必须严格区分Date字段,不然排序就乱了。
排序:像裁判一样吹响“时间哨”
Golang的sort.Slice是神器,我按照Date字段升序排列,time.Parse把字符串转成时间对象,再比较,但注意了,2018年世界杯主办方把开球时间分成了几个档位:当地时间13:00、16:00、18:00、21:00等等,换算成北京时间就是18:00、21:00、23:00、凌晨2:00,我的结构体里Date用的是“2018-06-14 23:00”这种完整格式,这样排序才不会把同一天不同时段的场次搞混。
sort.Slice(matches, func(i, j int) bool {
t1, _ := time.Parse("2006-01-02 15:04", matches[i].Date)
t2, _ := time.Parse("2006-01-02 15:04", matches[j].Date)
return t1.Before(t2)
})
那会儿调试的时候,发现6月16日有三场比赛:法国对澳大利亚(18:00)、阿根廷对冰岛(21:00)、秘鲁对丹麦(23:00),排序没问题,但打印到终端,屏幕宽度有限,挤成一团,于是我又加了个fmt.Printf的格式化输出,用%-12s对齐队名,效果就像直播比分条一样。
终端打印:让赛程表自己“说话”
我不搞花哨的GUI,就喜欢终端那种黑白分明的暴力美学,输出的时候,我直接打印成表格样式:

| 日期 | 时间(北京) | 对阵 | 小组 | 场馆 |
|---|---|---|---|---|
| 6/14 | 23:00 | 俄罗斯 - 沙特 | A | 卢日尼基 |
| 6/15 | 20:00 | 埃及 - 乌拉圭 | A | 叶卡捷琳堡 |
| 6/15 | 23:00 | 摩洛哥 - 伊朗 | B | 圣彼得堡 |
为了对齐中文字符,我用了unicode/utf8.RuneCountInString来计算中文字符宽度,因为英文字符占1个宽度,中文占2个,直接用len会导致表格歪歪扭扭,那个函数解决了我一晚上的头疼,你看,代码也讲究“因地制宜”,就像葡萄牙队靠C罗一个人撑不起整条防线。
过滤和查询:像教练换人一样随意
光打印全部比赛还不够,我加了两个命令行参数:-d指定日期,比如-d 6/24,就只输出那天的比赛;-g指定小组,比如-g F,就列出F组的全部场次,这样我可以快速查“6月24日F组有没有德国队”之类的信息。
flag.StringVar(&dateFilter, "d", "", "过滤日期,如 6/24") flag.StringVar(&groupFilter, "g", "", "过滤小组,如 F")
6月24日F组,那是德国对瑞典(凌晨2:00),那场球克罗斯最后时刻任意球绝杀,我在公司值班看的,差点叫出声,用我的程序一查,输出:
2018-06-24 02:00 德国 - 瑞典 F 索契菲什特
2018-06-24 02:00 韩国 - 墨西哥 F 顿河畔罗斯托夫
两个场次同时开球,程序按时间排好,一目了然,这种“即时感”,比翻网页快多了。
内存里的狂欢:决赛那晚我加班改bug
7月15日决赛那天,我还在改一个关于“平局加时”的逻辑——不是代码逻辑,是我想在输出里加上“加时赛(120分钟)”“点球大战”这种备注,比如克罗地亚对俄罗斯那场点球大战,于是我在结构体里加了个Note字段,手动填了“点球4:3”“加时2:1”,但问题是,有些场次有加时,有些没有,我用if判断输出的时候,空格要对齐,不然表格就碎了。
后来我干脆写了个渲染函数,按字段长度动态补空格,那晚决赛,法国4比2克罗地亚,我一边看球一边盯着终端,程序里所有比赛数据都跑通了,屏幕上闪过“决赛 卢日尼基 法国 - 克罗地亚 4:2”,那一刻,我居然比看球还兴奋,代码是死的,但配上了真实世界的结果,就像给照片涂上了色彩。
给赛程表加点“人味”
我不喜欢干巴巴的赛程表,于是加了注释和特殊标记:比如揭幕战、半决赛、决赛这些关键场次,在输出时加符号;还有“死亡之组”(比如B组西班牙、葡萄牙、伊朗、摩洛哥)的文字说明,手动写在GroupNote映射里,程序跑起来后,屏幕上不仅有比赛,还有小彩蛋——比如打印“今晚别睡太晚,阿桔比赛在凌晨”。
这些细节,就像球场边的呐喊声,让数据活了起来,现在回看这份代码,它不完美,甚至有点丑,但每次运行,就好像回到2018年的那个六月,啤酒、蚊子、氤氲的空调房,以及屏幕上不断刷新的比分。
那份比赛日程表,早就不只是日程了,它是我用Golang写给足球的一封情书。
本文来自作者[kyadmin]投稿,不代表678体育 - 全网热门体育赛事高清直播平台立场,如若转载,请注明出处:http://www.7oclockcapital.com/kj/2319.html
评论列表(4条)
我是678体育 - 全网热门体育赛事高清直播平台的签约作者“kyadmin”!
希望本篇文章《用Golang写一个2018世界杯比赛日程表,从内存到终端的硬核浪漫》能对你有所帮助!
本站[678体育 - 全网热门体育赛事高清直播平台]内容主要涵盖:678体育,678体育官网,678赛事直播
本文概览:第一行代码敲下去的时候,我脑子里全是莫斯科卢日尼基球场的灯光,2018年6月14日,世界杯揭幕战,俄罗斯对沙特——5比0,那场比赛我是在...