编写 golang 命令行小工具

2023-11-09

1. 前言

把想了很久的命令行小工具写了个demo。前几天看了 7 天仿 gin 项目,于是今天借鉴了其路由匹配方式,写出了这个demo。
思路是:创建一个类似路由的map,key值为选项,value为选项信息的结构体,结构体中保存有选项的动作函数。程序启动时实例化一个路由map并初始化,然后进行选项匹配,如果map中有这个选项的key,就执行对应的动作。思路很简单。
以下是代码,注释都有。为了管理方便我把源码拆分成了三份:main文件main.go,route相关定义的文件route.go,动作函数文件optionFunc.go

2. 代码部分

main.go

package main

import (
	"fmt"
	"os"
)

func main() {
	//route参数信息,只有选项没有参数的可以不写参数,参数动作函数集中到了optionFunc.go文件中
	//新的选项直接写在下面,动作函数handle也要写在optionFunc.go文件中
	var router = route{
		"-v": commandInfo{
			desc:   "Show version",
			handle: version,
		},
		"-cdb": commandInfo{
			desc:   "批量创建文件夹,参数后写 '路径' '文件夹前缀' '创建数目'",
			params: params{"路径", "文件夹前缀", "创建数目"},
			handle: branchCreateDir,
		},
	}

	//没有选项就打印帮助信心
	if len(os.Args) == 1 {
		printHelp(router)
		return
	}

	// -h 选项打印帮助信息
	//因为涉及到route,所以单独把 -h 摘取出来
	if os.Args[1] == "-h" {
		printHelp(router)
		return
	}

	//匹配到选项就执行选项信息中的动作,不然打印提示
	if commanInfo, ok := router[os.Args[1]]; ok {
		commanInfo.handle(os.Args[1:])

	} else {
		fmt.Printf("unknown flag '%s', please use '-h' to get help info\n", os.Args[1])
	}
}

// 打印帮助信息的函数
func printHelp(router route) {
	fmt.Printf("Usage:\n  %s [OPTIONS]\n\nOptions:\n", os.Args[0])
	for k, v := range router {
		if v.params == nil {
			fmt.Printf("  %s\t%s\n", k, v.desc)
		} else {
			fmt.Printf("  %s [ ", k)
			for _, item := range v.params {
				fmt.Printf("%s ", item)
			}
			fmt.Printf("]\t%s\n", v.desc)
		}

	}
}

route.go

package main

type params []string

// 选项的动作函数
type handFunc func(values params)

// 保存选项的动作、参数说明和选项功能的信息
type commandInfo struct {
	handle handFunc
	desc   string
	params params
}

// 将选项和动作成对存在map里
type route map[string]commandInfo

optionFunc.go

package main

import (
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func version(params params) {
	fmt.Println("hanta-tools version 0.1.0")
}

func branchCreateDir(params params) {
	//参数个数或者关键参数为空直接提示错误
	if len(params) != 4 || params[1] == "" || params[3] == "" {
		fmt.Printf("  %s ERROR: 请输入正确的参数", os.Args[0])
		return
	}

	//字符串转数字失败提示参数错误
	num, err := strconv.Atoi(params[3])
	if err != nil {
		fmt.Printf("  %s ERROR: 请输入正确的文件数", os.Args[0])
		return
	}
	//剔除路径后的 “\” 和 “/” 符号
	prePath := strings.TrimRight(params[1], "\\")
	prePath = strings.TrimRight(prePath, "/")
	for i := 1; i <= num; i++ {
		var dirPath = ""
		//根据不同系统平台来拼接完整路径
		if runtime.GOOS == "windows" {
			dirPath = fmt.Sprintf("%s\\%s%d", prePath, params[2], i)
		} else {
			dirPath = fmt.Sprintf("%s/%s%d", prePath, params[2], i)
		}
		err := os.Mkdir(dirPath, 0666)
		//将创建失败信息完整打印到控制台
		if err != nil {
			fmt.Printf("  %s ERROR: %s", os.Args[0], err)
			break
		}
	}
}

3. 效果

Windows平台编译后运行效果:
在这里插入图片描述
Centos 7.6编译后运行效果:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编写 golang 命令行小工具 的相关文章

  • 如何展平嵌套 JSON

    尝试将嵌套的 json 响应从 2 层深度压平到 1 层 这是我在 Go Playground 上的工作代码 http play golang org p kHAYuZUTko http play golang org p kHAYuZUT
  • Golang - 如何在特定时间执行函数

    我需要在一天中的特定时间运行一个函数 例如 0010 0610 1210 1810 我目前的方法使用自动收报机for range time Tick 21600 time Second 我以这些时间间隔之一 例如 1210 手动启动该程序
  • 为什么这里会出现僵局

    我想了解 golang 通道是如何工作的 我读了一本关于go语言的书 发现了下面的例子 package main import fmt Send the sequence 2 3 4 to returned channel func gen
  • 为什么Go中可以在多个return语句中重新定义err

    考虑下面的示例来说明这个问题 它只是为了解释这个问题而构建的 但我在书中以及实际项目中都看到了类似的代码 package main import strconv fmt log func main n1 err strconv Atoi 1
  • 如何将 interface{} 转换回其原始结构?

    我需要一种方法将结构 接口动态转换回其原始对象 我可以在里面添加方法 函数 基本上我需要这样的东西 MyStruct gt Interface gt MyStruct 在最终转换时 除了结构内部的内容之外 我对原始结构一无所知 所以我不能这
  • 接口实现中的非接口方法

    我有一个定义方法的接口 我有一个结构实施这个界面 在其中 我实现了该接口中的方法 并且还定义了其他方法 例如 package main import fmt type Animal interface MakeNoise type Dog
  • struct{} 和 struct{}{} 在 Go 中如何工作?

    我想知道 Go 中的 struct 和 struct 是什么意思 示例如下 array index struct or make map type struct struct is a keyword https golang org re
  • 从恐慌中恢复的程序未按预期退出

    根据我的理解 当恐慌恢复时 我期望程序退出并表现出正常行为 但事实并非如此 我期望最后一行打印 程序结束 是正确的吗 如果出现运行时错误 它不会被打印 是吗 package main import fmt func main defer f
  • Airbrake 抛出错误“pybrake - 错误 - strconv.ParseInt:解析“None”:无效语法”

    我正在尝试按照中描述的步骤在 Django 项目中使用 Airbrake 记录器https github com airbrake pybrake django integration https github com airbrake p
  • Go 中的格式错误 - %s %v 或 %w

    s v and w可用于格式化 Go 中的错误 将它们转换为字符串 fmt Errorf 它们在 Go 自己的工具中的使用方式似乎有所不同 In cmd go internal get path go https github com go
  • 在 Golang Server 中接受持久的 tcp 连接

    我正在尝试使用 Go 并且想创建一个 TCP 服务器 我可以通过 telnet 访问该服务器 发送命令并接收响应 const CONN HOST localhost CONN PORT 3333 CONN TYPE tcp func mai
  • 按顺序范围循环映射

    我正在寻找一种确定的方法来范围Go map为了 Go 规范 https golang org ref spec For statements陈述如下 映射的迭代顺序未指定 并且不保证从一次迭代到下一次迭代的顺序相同 如果在迭代过程中删除尚未
  • 如何访问 Go 中的嵌套模块(子模块)?

    去版本 1 12 9 这是一个简单演示项目的结构 所以我们有一个模块domain 其中包含两个模块 activity and person 我想将域与主文件中的所有嵌套模块一起使用 gt 模块 go 我知道如何导入domain主要在go m
  • 地图中的最大元素数

    GO 中的 Map 最多可以存储多少个元素 如果我需要经常从 Map 访问数据 那么在长时间运行的程序中不断向 Map 添加项目并从中检索项目是一个好主意吗 除了map length类型的最大值之外 map中的元素数量没有理论上的限制 in
  • 读取一个文本文件,替换其中的单词,输出到另一个文本文件

    所以我试图在 GO 中编写一个程序来获取一个充满代码的文本文件并将其转换为 GO 代码 然后将该文件保存到 GO 文件或文本文件中 我一直在试图弄清楚如何保存对文本文件所做的更改 但我可以看到更改的唯一方法是通过 println 语句 因为
  • 为什么我不能执行 fmt.Sprintf("%d.%d.%d.%d", a...)?

    我正在学习 Go 但我一直坚持 Go 之旅 exercise stringer go https tour golang org methods 7 https tour golang org methods 7 这是一些代码 type I
  • 带 cookie 身份验证的 Gorilla websocket

    这是我的设置 我正在构建一个带有用户登录的服务 使用 Negroni 和 Gorilla 登录后 用户会获得一个会话 cookie 服务器使用该会话 cookie 来授权受保护的端点 受保护的端点之一允许用户 客户端与服务器打开 Webso
  • 为什么结构体不能转换为嵌入类型

    package main type Inner struct x int type Outer struct Inner func main x Inner 1 y Outer x cannot convert x type Inner t
  • 如何顺序运行 golang 测试?

    当我跑步时go test 我的输出 FAIL TestGETSearchSuccess 0 00s Location drivers api test go 283 Error Not equal 200 expected 204 actu
  • Google Cloud Kubernetes 上任务队列的替代方案

    我发现任务队列主要用于App Engine标准环境 我正在将现有服务从 App Engine 迁移到 Kubernetes 任务队列的一个好的替代方案是什么 推送队列是当前正在使用的队列 我在线阅读文档并浏览了此链接 何时使用 PubSub

随机推荐

  • PHP微信获取小程序手机号失败 -41003

    使用官方的PHP版demo解密 调用接口后返回错误码 41003 并未成功解密出想要的信息 以为是encryptedData 数据传输的时候 号会自动转换为空格 但是不是 打印了一下解密后的iv 和 encryptedData 发现是乱码
  • matlab开根号_matlab基本计算

    这里介绍的内容是使用MATLAB进行基本的数学计算 完成的是类似计算机计算数学算式的功能 这篇文章基本可以帮助你学会所有基本的matlab计算方法 1 基本计算 MATLAB中的基本的运算符号为 四则运算规则和平时使用的计算器相同 使用MA
  • C++语句 与简单方法

    语句 在c primer plus 第二章中除了讲到输出流 还提到了更多的语句 书中称之为Statement 简单看来语句有申明语句 赋值语句 调用函数的语句 下面看书上的一组例子 include
  • 锁的四种状态及升级过程

    锁的四种状态与锁升级过程 图文详解 一 前言 锁的状态总共有四种 级别由低到高依次为 无锁 偏向锁 轻量级锁 重量级锁 这四种锁状态分别代表什么 为什么会有锁升级 其实在 JDK 1 6之前 synchronized 还是一个重量级锁 是一
  • react脚手架、使用步骤、在react脚手架里做项目的步骤、反向代理

    脚手架 facebook的官方脚手架 1 安装 create react app CRA npm install create react app g yarn global add create react app 安装yarn 方法一
  • Shiro学习小记--身份验证得到principals

    项目使用shiro进行权限管理 Shiro国内目前资料极少 学习时完全就是根据张开涛的 跟我学Shiro 自己去摸索的 慢慢的开始入门 Shiro中有一个概念是principals 解释如下 principals 身份 即主体的标识属性 可
  • 软件测试-环境搭建思路/测试流程

    环境搭建思路 测试流程 1 软件测试环境搭建 1 1 搭建测试环境前 1 2 环境搭建模式 1 3 测试环境建设思路 2 测试过程 2 1 测试策划过程 2 1 1 需求分析 余额宝需求测试实战 2 1 2 测试策略 2 1 3 测试方案设
  • 视频教程-卷积神经网络从原理到实战-深度学习

    卷积神经网络从原理到实战 本科北京航空航天大学计算机科学与技术专业 长期从事图像算法和文本算法 曾就业于航天相关机密单位 熟悉FasterRCNN SSD YOLO MASKRCNN一系列图像框架 及Bert Bilstm等NLP相关技术
  • App隐私合规注意事项和相关材料

    合规条文相关资料 最新 移动互联网应用程序信息服务管理规定 2022年8月1日起施行 http www cac gov cn 2022 06 14 c 1656821626455324 htm 全国APP技术检测平台 APP公共服务系统 h
  • 【HarmonyOS】详解低代码端云一体化开发之数据模型

    关键字 元服务 低代码平台 端云一体化开发 数据模型 拖拽式UI 1 写在前面 上一篇中分享了关于低代码平台开发元服务的基本使用 有兴趣的可以看一下 文章地址如下 华为开发者论坛 但是在上一篇中我们的数据都是在端侧配置的 这种方式肯定是无法
  • IDEA 快捷键大全

    目录 一 文本编辑 二 光标操作 三 文本选择 四 代码折叠 五 辅助编码 六 上下文导航 七 查找操作 八 符号导航 九 代码分析 十 运行和调试 十一 代码重构 一 文本编辑 Ctrl Shift V 从历史选择粘贴 Ctrl D 复制
  • Java多线程实现的四种方式

    多线程实现的四种方式 1 继承Thread类 重写run方法 2 实现Runnable接口 重写run方法 实现Runnable接口的实现类的实例对象作为Thread构造函数的target 3 通过Callable和FutureTask创建
  • mbind: Operation not permitted

    问题描述 IntelliJ IDEA 中 Docker Integration 插件 启动 MySql 容器 然后使用 Navicat for MySQL 来连接 只要连接数据库就会出现 mbind Operation not permit
  • java 性能监控 jstack 线程死锁 JConsole 和 BTrace 图形化工具

    java 性能监控 工具 除了 javac java javap 之外 jdk 安装包还提供了很多其他工具 列出 bin 目录下的文件 TomChens MacBook Pro Commands tomchen ls appletviewe
  • 挖坑指南:npm install命令各参数的区别(--sava --save-dev -g)

    前言 在前端工作中 npm已经成为必不可少的一部分 npm install可以为我们的项目安装依赖 那么这个命令的参数 各代表什么含义呢 开始 我们逐一来看看npm install save dev 安装我们项目开发时的依赖 比如一些插件
  • [Unity][AssetBundle]从AB包中加载Material材质球

    名字为111的AB包中 已经有打包的材质 名字为 test using UnityEditor public AssetBundle ab material public Material m
  • Ubuntu16.04为ROS搭建Qt开发环境

    很早之前就听说了Qt有ROS插件可以使用 只是阴 lan 差 de 阳 qu 错 gao 一直到今天还是在使用纯文本的方式在开发ROS 上午心 shou 血 bu 来 liao 潮 le 走上了Qt ros qtc plugin的不归路 所
  • 【华为机试真题Python】字符串消消乐游戏

    目录 题目描述 测试用例 参考代码 题目描述 输入一个只包含英文字母的字符串 字符串中的两个字母如果相邻且相同 就可以消除 在字符串上反复执行消除的动作 直到无法继续消除为止 此时游戏结束 输出最终消除完后留下的字符串 测试用例 用例1 输
  • 网络编程学习笔记

    网络基础 协议的概念 什么是协议 从应用的角度出发 协议可理解为 规则 是数据传输和数据的解释的规则 假设 A B双方欲传输文件 规定 第一次 传输文件名 接收方接收到文件名 应答OK给传输方 第二次 发送文件的尺寸 接收方接收到该数据再次
  • 编写 golang 命令行小工具

    1 前言 把想了很久的命令行小工具写了个demo 前几天看了 7 天仿 gin 项目 于是今天借鉴了其路由匹配方式 写出了这个demo 思路是 创建一个类似路由的map key值为选项 value为选项信息的结构体 结构体中保存有选项的动作