用Golang实现一个统计代码行数的程序

在开发中,我们有时候想要统计一个文件夹下的所有代码的行数,但是有时候找这样的工具也挺麻烦的。那么就自己实现一个吧。

思路:
1、通过命令行参数获取要统计的代码所在根目录以及代码文件的后缀,比如Go语言是.go C++语言是.cpp,可以同时统计多种类型的文件

2、从根目录开始递归遍历文件:1.如果是目录,就递归遍历;2.如果是普通文件,根据后缀判断是否是要统计的代码的文件,如果是就统计并打印代码行数。

代码如下:

package mainimport ("bufio""fmt"flag "github.com/spf13/pflag""io/ioutil""os""path""path/filepath""sync"
)var (suffixLines   map[string]inttotalLines    introotPath      stringdefaultSuffix string = ".go"suffix        map[string]struct{}wg           sync.WaitGroupstaticticsWg sync.WaitGroup
)type Line struct {Filepath stringLines    int
}func main() {// 先获取要统计的代码所在的rootPath 以及代码文件名后缀err := getPath()if err != nil {fmt.Println("Get Current Path error:", err)return}// 如果不是目录,直接统计文件行数,然后返回ok := IsDir(rootPath)if !ok {line := getFileLine(rootPath)fmt.Printf("%s: %d\n", rootPath, line)return}// 统计目录中所以指定后缀文件的行数staticticsWg.Add(1)staticsChan := make(chan *Line, 128)go statictics(staticsChan)// 遍历目录下的文件wg.Add(1)pathSeparator := string(os.PathSeparator)go staticticsAllFile(pathSeparator, rootPath, staticsChan)// wait返回表示目录已经遍历完毕wg.Wait()// 通知统计协程退出close(staticsChan)staticticsWg.Wait()for name, lines := range suffixLines {fmt.Printf("File suffix %s total line: %d\n", name, lines)}fmt.Println("Total Line: ", totalLines)
}// 给rootPath以及后缀赋值
func getPath() error {dafaultFile, err := os.Getwd()if err != nil {return err}filename := flag.String("f", dafaultFile, "-f filePath")sfxs := flag.StringSlice("s", []string{defaultSuffix}, "-s suffix1,...,suffixn")flag.Parse()// 如果是否是相对路径if (*filename)[0] != '.' {rootPath = *filename} else {rootPath, _ = filepath.Abs(*filename)}suffix = make(map[string]struct{}, len(*sfxs))for i := 0; i < len(*sfxs); i++ {key := (*sfxs)[i]suffix[key] = struct{}{}}fmt.Printf(`Statistics target Root Path: "%s"`, rootPath)fmt.Println()fmt.Println(`File Suffix: `, *sfxs)fmt.Println()fmt.Println()fmt.Println("--------------------------------------------------------------------------------")fmt.Println()return nil
}// 打印并统计代码总行数
func statictics(channel chan *Line) {defer staticticsWg.Done()suffixLines = make(map[string]int, len(suffix))for {line, ok := <-channelif !ok {return}totalLines += line.LinessuffixLines[path.Ext(line.Filepath)] += line.Linesfmt.Printf("%s: %d\n", line.Filepath, line.Lines)}}// 遍历所有文件,如果是普通文件就统计行数,如果是目录,递归遍历目录
func staticticsAllFile(pathSeparator string, fileDir string, channel chan *Line) {files, _ := ioutil.ReadDir(fileDir)for _, file := range files {filePath := fileDir + pathSeparator + file.Name()if file.IsDir() {if (file.Name())[0] == '.' { // 忽略隐藏文件continue}wg.Add(1)go staticticsAllFile(pathSeparator, filePath, channel)} else if _, ok := suffix[path.Ext(file.Name())]; ok {line := getFileLine(filePath)channel <- &Line{Filepath: filePath,Lines:    line,}}}wg.Done()
}// 获取文件的行数
func getFileLine(filename string) (line int) {file, err := os.Open(filename)if err != nil {fmt.Println("getFileLine error, file name:", filename, " error:", err)return 0}defer file.Close()line = 0reader := bufio.NewReader(file)for {_, isPrefix, err := reader.ReadLine()if err != nil {break}if !isPrefix {line++}}return
}// 判断所给路径是否为文件夹
func IsDir(path string) bool {s, err := os.Stat(path)if err != nil {return false}return s.IsDir()
}

编译后,可以将其位置加入到环境变量。我使用的是git bash,所以我就将生成的可执行文件放在了git bash的/usr/bin文件下,这样就可以直接在终端中调用:
在这里插入图片描述

在添加 -f 参数时,要用引号将路径引起来,否则因为路径中有 \ 导致获取的路径会有问题,-s 参数不需要:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1380399.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

视觉里程计-代码仓库

1. 基于opencv的视觉里程计&#xff08;visual odometry) GitHub - Transportation-Inspection/visual_odometry: visual odometry in python scripts The Python Monocular Visual Odometry (py-MVO) project used the monoVO-python repository, which is a Python impleme…

VTK学习笔记(二十一)

显示立方体已经做过了&#xff0c;现在想简单处理一下立方体&#xff0c;比如每个面上增加一些文字。效果如下。 #include <vtkAnnotatedCubeActor.h> #include <vtkCamera.h> #include <vtkNamedColors.h> #include <vtkNew.h> #include <vtkPrope…

如何减少项目在Corona和V-Ray中的3ds Max渲染时间?

相信在大多 3D 项目里&#xff0c;渲染是最耗费时间的部分&#xff0c;它不仅是建模和纹理化 3D 场景的过程&#xff0c;而是需要利用硬件来完成任务。我们在配备独立GPU和带有2到4个强大内核的CPU的中档计算机上&#xff0c;可以将3ds Max中创建和处理的项目轻松渲染完成&…

渲染函数render

文章目录 节点、树以及虚拟 DOM树节点虚拟 DOMvue中render函数的作用 render函数去创建子组件内容createElement官方文档参考 节点、树以及虚拟 DOM 在深入渲染函数之前&#xff0c;了解一些浏览器的工作原理是很重要的。以下面这段 HTML 为例&#xff1a; <div><h1…

如何使用vray进行建筑渲染?

如果您刚开始渲染世界&#xff0c;您可能会遇到的一些最常见的问题是&#xff1a;我应该如何开始&#xff1f;目前流行哪些技术&#xff1f;我怎么能确定我在做什么是正确的&#xff1f; 建模和 3D 平台 如果您是建筑或设计专业的学生&#xff0c;​​或者是专业人士&#xff0…

web-vue

<html><head><title>永远朋友</title><script src"../js/vue.js"></script></head><body><div id "app"><input type"text" v-model"message">{{ message }}</div&g…

40岁后吃不胖的秘诀 济阳高穗饮食理论

欢迎使用 {小书匠}(xiaoshujiang)编辑器 济阳高穗&#xff1a;研究所所长、医院院长、临床教授、医学博士、执刀4000台手术&#xff0c;半数为癌症患者&#xff0c;首创的“济阳式膳食疗法”让许多癌症早期患者得到治愈。 40岁以后&#xff0c;身体必需的【食物】会变得截然不…

大学生川菜网页制作教程 学生HTML静态美食菜品网页设计作业成品 简单网页制作代码 学生美食网页作品免费设计

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

Java猪人刷怪塔_我的世界:经验不够怎么办?MC6大快速升级方法,养鸡也行?...

《我的世界》经验值是非常重要的&#xff0c;但记住&#xff0c;任何刷经验的方法&#xff0c;都不要一次性刷超过30级。因为在30级之前&#xff0c;效率最高!想要拥有神级装备&#xff0c;给装备附魔你就不得不想办法获得大量的经验值。那么有哪些方法可以快速获得经验值呢? …

白萝卜炖鸡汤

主料 鸡1000克 白萝卜1个750克 红枣100克 枸杞25克 配料 姜1小块 盐适量 料酒 步骤 1、将鸡剁成大块&#xff0c;洗完用料酒、盐、五香粉腌制30分钟&#xff0c;使鸡肉进盐&#xff1b; 2、用锅内加少许底油&#xff0c;把鸡肉放进锅里翻炒到鸡肉呈黄色 3、鸡肉放进高压锅或者炖…

第三篇:设计模式六大原则: 一个萝卜一个坑 -- 单一职责原则

形形色色的代码接触多了&#xff0c;越发意识到 面向对象 这个被人说烂却鲜有用好的概念的重要性。之前看了《大话设计模式》也只是匆匆一瞥&#xff0c;没有敲代码或者记博客&#xff0c;这次连着《Android 源码设计模式解析与实战》一起学习&#xff0c;总结记录下来。 设计模…

c语言小兔子原来有1个萝卜,小兔子和小狐狸的100个睡前晚安小故事

小兔子和小狐狸的睡前故事,小兔子的甜甜的小故事,100个小兔子和小狐狸的晚安小故事。 小兔子和小狐狸的晚安故事合集(更新中) 小兔子的睡前故事 30.喜欢就是我对你的感觉呀 小兔子偷偷看了书,书上说,女孩儿在这段时间都会经历这个心情。 这个心情,叫做喜欢。 可是书上说的…

土豆炖鸡

先上成品图 1. 红烧萝卜 原料&#xff1a;鸡切块、土豆去皮切块、姜切片、葱切段、蒜切片、八角、 锅里烧水放入肉块&#xff0c;煮沸几分钟焯一下&#xff0c;更卫生油锅烧热&#xff0c;加入小辣椒、花椒爆香&#xff0c;加入鸡块炒至微变色加入葱段、姜片、蒜片&#x…

九大体质测试软件,著名的九大体质测试,快来测一测

原标题&#xff1a;著名的九大体质测试&#xff0c;快来测一测 如果对中医有些了解&#xff0c;那么九大体质肯定听说过。中医将我们常见的体质分为九种&#xff0c;并根据个体先天因素和后天因素&#xff0c;对各个体质做出判断&#xff0c;可得知今后你容易患上哪些疾病。 著…

胡萝卜(5)

目录 目录 1、stacking模型以及做模型融合的知识2、怎样去优化SVM算法模型的&#xff1f;3、现有底层是tensorflow的keras框架&#xff0c;如果现在有一个tensorflow训练好的模型&#xff0c;keras怎么读取&#xff1f;4、卷积层为什么能抽取特征&#xff1f; Pool层的作用5、L…

设计模式六大原则: 一个萝卜一个坑 -- 单一职责原则

形形色色的代码接触多了&#xff0c;越发意识到 面向对象 这个被人说烂却鲜有用好的概念的重要性。之前看了《大话设计模式》也只是匆匆一瞥&#xff0c;没有敲代码或者记博客&#xff0c;这次连着《Android 源码设计模式解析与实战》一起学习&#xff0c;总结记录下来。 设计模…

板栗烧鸡的家常做法

板栗烧鸡:板栗香甜,鸡肉鲜嫩http://www.fangyuxing.top/?s=%E6%9D%BF%E6%A0%97 【板栗小知识】 板栗的原产地就是我国,是属于坚果的一种,也是食用中最早的坚果之一。板栗的营养丰富,它的营养是世界群栗之冠,一般都是炒了吃。比如常见的是糖炒板栗,吃起来口感软糯又香…

学煲汤,70个汤

40、玉米萝卜大骨汤原材料&#xff1a;玉米棒150克&#xff0c;排骨250克&#xff0c;红萝卜50克&#xff0c;生姜、红枣少许作法&#xff1a;1、玉米棒去外皮&#xff0c;切成段&#xff0c;红萝卜切块&#xff0c;排骨砍成块&#xff0c;生姜切处&#xff0c;红枣洗净&#x…

Vector - CAPL - 诊断模块函数(流控制帧续)

目录 CanTpGetFirstSequenceNumber & CanTpSetFirstSequenceNumber 代码示例 CanTpIsUseFlowControlSTmin & CanTpIsUseFlowControlSTmin & CanTpUseFlowControlSTmin CanTpIsUseFlowControlFrames & CanTpUseFlowControlFrames 代码示例 CanTpSetFlowC…

B057-spring增强 依赖注入 AOP 代理模式 创建Bean

目录 AOP概念代理模式引出AOP实现方式xml方式实现注解方式实现 AOP 概念 事务管理&#xff1a;比如可以抽取try catch的重复代码 日志监控&#xff1a;比如业务逻辑前后打印关于当前订单数量的日志&#xff0c;了解业务做了什么 性能监控&#xff1a;比如业务前后打印时间&…