为什么我要用Go语言写一个“我的农村365种花视频”管理程序?
说实话,一开始我压根儿没想过要写代码,我就是个喜欢在院子里种花的人,闲着没事拍拍视频,记录一下院子里的月季开了、向日葵长高了、隔壁老王家那棵石榴树又结果了,拍着拍着,视频越来越多,手机里的文件夹乱成一锅粥,我寻思着,能不能用个什么办法,把这些视频管起来?正好我最近学了点Go语言,觉得这玩意儿简单直接,就想试试。
我的农村365种花视频这个想法,其实挺朴素的——就是想每天拍一种花,一年下来,凑够365种,但拍完之后呢?怎么分类?怎么标记?哪天拍的?什么花?在哪个位置?这些信息要是光靠文件名,根本记不住。
我决定用Go语言写一个小工具,专门管理这些视频。

第一步:用Go语言定义“花”的数据结构
我先想了一下,每一段视频,至少得有几个关键信息:
- 花的名字(牡丹”)
- 拍摄日期
- 拍摄地点(前院、后院、路边…)
- 视频文件路径
- 一个编号(用来排序)
在Go里面,我用了一个结构体(struct),大概长这样:
type FlowerVideo struct {
ID int
Name string
Date string
Location string
FilePath string
}
结构体这玩意儿吧,就像是给每一段视频做了一个“标签卡”,上面写清楚是什么花、什么时候拍的、在哪儿拍的,这样我一查就能知道——哦,“石榴花”这个视频是5月3号在院子东边拍的。
为什么用结构体不用map?
其实我刚开始也想过用map,但后来发现,map不适合做这种多个字段绑定在一起的数据,结构体能保证每个字段的类型和顺序都固定,不容易乱,而且Go的结构体还支持嵌套,万一以后我想把“花”的信息再细化,比如加上“花期”“颜色”之类的,直接往里加字段就行。
第二步:读取视频文件,构建“我的农村365种花视频”列表
我的视频文件都放在一个文件夹里,文件名格式大概是这样:
20250412_月季_前院.mp4
20250413_向日葵_后院.mp4
20250414_石榴花_路边.mp4
…………
我用Go的filepath.Walk方法,把整个文件夹里的.mp4文件扫一遍,然后用正则把文件名拆开,存到结构体数组里。
这里有个坑:文件名里的中文,有时候编码会乱,后来我查了一下,Go对UTF-8支持还不错,但文件名的读取要小心,尽量不要用
ioutil.ReadDir(这个已经被废弃了),改用os.ReadDir和filepath.Walk更稳。
代码大概是这个感觉:
videos := []FlowerVideo{}
filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(info.Name(), ".mp4") {
// 拆文件名:日期、花名、地点
parts := strings.Split(strings.TrimSuffix(info.Name(), ".mp4"), "_")
// 忽略错误处理,实际肯定要写
videos = append(videos, FlowerVideo{
ID: len(videos) + 1,
Name: parts[1],
Date: parts[0],
Location: parts[2],
FilePath: path,
})
}
return nil
})
这一步做完,我就有了一个“我的农村365种花视频”列表,里面存着所有视频的信息,每一次运行程序,它都会自动扫描文件夹,不用我手动录入,这比在Excel里一行行输入强多了。
第三步:把视频列表变成网页——用Go做简单的HTTP服务器
光有数据还不够,我想在手机上也能看这个列表,于是我用Go的内置net/http包搭了一个简单的Web服务器。
它做的事情很简单:
- 启动一个HTTP服务,监听在某个端口(比如8080)
- 收到请求后,把
FlowerVideo列表渲染成一个HTML页面 - 页面上用表格展示每个视频的信息,还带一个播放链接
我不搞什么复杂的前端框架,就用html/template包,写一个简单的模板,模板里用<table>标签排版,每一行是一条视频信息。
tmpl := `
<h1>我的农村365种花视频</h1>
<table border="1">
<tr><th>编号</th><th>花名</th><th>日期</th><th>地点</th><th>播放</th></tr>
{{range .}}
<tr>
<td>{{.ID}}</td>
<td><strong>{{.Name}}</strong></td>
<td><em>{{.Date}}</em></td>
<td>{{.Location}}</td>
<td><a href="/play?id={{.ID}}">观看</a></td>
</tr>
{{end}}
</table>
`
在实际运行的时候,我还加了一个/play路由,用来直接播放视频,Go里面用http.ServeFile就能直接把视频文件流式发送给浏览器,不需要额外插件。
一点真实的小插曲
我一开始写的模板忘记用<em>和<strong>标记了,后来觉得花的名字得重点显示,日期嘛,斜体显得更文艺点,于是加上了<strong>和<em>,其实这些标签对功能没啥影响,但看着顺眼。
为什么我觉得Go适合做这个事?
你可能觉得,这功能用Python写也行,用Node.js也行,为啥非要用Go?
说实话,我也试过Python,但Python跑起来得装一大堆依赖,Flask也好、Django也好,动不动就几百兆,我那个破服务器是台旧电脑,跑Python web应用有点吃力,Go编译出来就一个二进制文件,丢到服务器直接运行,CPU和内存占用都很低。
而且Go的并发模型,虽然我这小应用用不上,但我心里安心,万一以后我要同时处理多路视频转码、缩略图生成,Go的goroutine就派上用场了。
给想自己写类似程序的朋友一些建议
一定要先想好数据结构
别像我一开始那样,用文件名存所有信息,后来我发现,有些花名里带了空格或特殊符号,文件名解析就出错了,最好用数据库,或者至少用JSON来存,我现在是把FlowerVideo列表序列化成JSON文件,每次启动时读取,这样即使视频文件夹变了,元数据也不会丢。
记得加搜索功能
我写了这个程序之后,拍了快两个月,视频文件越来越多,光靠翻表格找特定某种花,根本翻不过来,后来我加了一个简单的搜索框,用Go处理URL参数/search?name=月季,然后在列表里用strings.Contains做模糊匹配。
虽然方法土,但够用,你想想,大半夜的你在院子里的灯光下翻手机,不就想快点找到那段“月季开花”的视频吗?
视频播放最好用HLS或者流媒体
直接把MP4文件发给浏览器,在电脑上没问题,在手机上就卡得不行,后来我把视频转成HLS格式(就是用FFmpeg切成一小段一小段的.ts文件),然后Go返回一个.m3u8文件给前端,用<video>标签配合hls.js,流畅多了。
这个操作有点麻烦,但用户体验好,农村嘛,网络有时候不太好,分段加载就很实用。
一个让我很开心的细节
有一次我妈看到我在院子里拍花,问我:“你拍这么多干什么?”我说我在写一个程序管理这些视频,她没太听懂,但后来我在手机上打开那个网页给她看——她一眼就看到表格里有一条:“20250406_油菜花_田埂.mp4”,她愣了一下,说:“这不就是你去年春天在河边拍的那片菜花吗?”
那一刻我觉得,这程序写值了。
我的农村365种花视频”这个项目的未来
我现在已经拍了一百多种花了,离365还差得远,但我不急,一年拍不完就两年,两年拍不完就三年,反正程序已经写好了,Go语言写的,稳定运行,几乎不出错,偶尔我更新一下代码,重新编译,替换一下二进制文件就好。
以后我还想加个功能:在表格里显示视频的缩略图,用FFmpeg从视频里截取第一帧作为封面,大概思路是先调用外部命令,截好图存到某个文件夹,然后在模板里直接用<img>标签显示,Go里可以用os/exec包来调用FFmpeg。
不过这个不急,慢慢来。
写在最后
我写这个东西,从一开始就是为了解决我自己的一个小问题——管理那些农村院子里拍的花的视频,结果发现,用Go语言做这件事,比我想象中简单,也比我之前用Python做的那版稳定得多。
现在每天晚上吃完饭,我都会打开那个网页,翻一翻“我的农村365种花视频”列表,看看今天又记录了什么花,有时候院子里什么花都没开,我就翻翻之前拍的,看看春天开过的海棠、夏天盛开的紫薇、秋天冒出来的野菊,每一段视频后面,都藏着一个天气晴好的下午,或者一场雨后泥土的气息。
表格里的数字在慢慢变多,从1到100,再到现在的127,我不知道什么时候能凑到365,但没关系,代码在跑,花在开,生活也在继续。
对了,昨天拍的是一朵牵牛花,在栅栏边上,开得正好,我已经加到程序里了,编号128。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.uss1.cn/lvyou/1915.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《我的农村365种花视频,用Go语言记录每一朵花的绽放》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:为什么我要用Go语言写一个“我的农村365种花视频”管理程序?说实话,一开始我压根儿没想过要写代码,我就是个喜欢在院子里种花的人,闲...