学习:单词格式转换 | Go 语言编程之旅 (eddycjy.com)
代码参考:go-programming-tour-book/tour: 《Go 语言编程之旅:一起用 Go 做项目》第一章:命令行程序(Command) (github.com)
使用工具cobra:
go get -u github.com/spf13/[email protected]
先搭好架子,再具体实现!
接口的应用中也有这种思想,接口相当于先制定标准再具体实现;
搭好架子/制定标准:全局架构清晰;具体实现。
搭好架子
$ tree
.
├── cmd
│ ├── root.go
│ └── word.go
├── main.go
cmd/word.go
,用于单词格式转换的子命令 word 的简单设置:
var wordCmd = &cobra.Command{
Use: "word", // 子命令的命令标识。
Short: "单词格式转换", // 简短说明,在 help 输出的帮助信息中展示。
Long: "支持多种单词格式转换", // 完整说明,在 help 输出的帮助信息中展示。
Run: func(cmd *cobra.Command, args []string) {}, // 具体实现Todo;
}
func init() {}
cmd/root.go
,用于创建根命令,将子命令加入根命令中:
var rootCmd = &cobra.Command{} // 新建的空Command
func Execute() error {
return rootCmd.Execute() // 执行设置的命令;
}
func init() { // init在main函数之间执行;在import此包的变量,常量后,立即执行;
rootCmd.AddCommand((wordCmd)) // 将创建的子命令加入rootCmd
}
- 关于init函数:
main包中导入cmd并使用cmd包:
import (
"log"
"github.com/KpiHang/tour/cmd"
)
var name string
func main() {
err := cmd.Execute()
if err != nil {
log.Fatalf("cmd.Execute err : %v", err)
}
}
详细设置word子命令
此步骤还不包括,功能具体的功能实现;
cmd/word.go
:
package cmd
import (
"log"
"strings"
"github.com/KpiHang/tour/internal/word"
"github.com/spf13/cobra"
)
// 用于单词格式转换的子命令 word 的设置
const (
ModeUpper = iota + 1 // 全部转大写;1
ModeLower // 全部转小写;2
ModeUnderscoreToUpperCamelCase // 下划线转大写驼峰;3
ModeUnderscoreToLowerCamelCase // 下线线转小写驼峰;4
ModeCamelCaseToUnderscore // 驼峰转下划线;5
)
var str string
var mode int8 // 选择转换模式mode
// Long desc: the long message shown in the 'help <this-command>' output.
var desc = strings.Join([]string{
"该子命令支持各种单词格式转换,模式如下:",
"1:全部转大写",
"2:全部转小写",
"3:下划线转大写驼峰",
"4:下划线转小写驼峰",
"5:驼峰转下划线",
}, "\n")
var wordCmd = &cobra.Command{
Use: "word", // 子命令的命令标识。
Short: "单词格式转换", // 简短说明,在 help 输出的帮助信息中展示。
Long: desc, // 完整说明,在 help 输出的帮助信息中展示。
Run: func(cmd *cobra.Command, args []string) {
var content string
switch mode {
case ModeUpper:
content = word.ToUpper(str)
case ModeLower:
content = word.ToLower(str)
case ModeUnderscoreToUpperCamelCase:
content = word.UnderscoreToUpperCamelCase(str)
case ModeUnderscoreToLowerCamelCase:
content = word.UnderscoreToLowerCamelCase(str)
case ModeCamelCaseToUnderscore:
content = word.CamelCaseToUnderscore(str)
default:
log.Fatalf("暂不支持该转换模式,请执行 help word 查看帮助文档")
}
log.Printf("输出结果: %s", content)
},
}
func init() {
wordCmd.Flags().StringVarP(&str, "str", "s", "", "请输入单词内容") // shorthand: 短标识;
wordCmd.Flags().Int8VarP(&mode, "mode", "m", 0, "请输入单词转换的模式")
// 在 VarP 系列的方法中,第一个参数为需绑定的变量、第二个参数为接收该参数的完整的命令标志,第三个参数为对应的短标识,第四个参数为默认值,第五个参数为使用说明。
}
-
因为,word子命令需要两个参数:
-m, --mode int8
请输入单词转换的模式-s, --str string
请输入单词内容
-
所以,要把这两个参数,绑定到两个变量,来使用:
wordCmd.Flags().StringVarP(&str, "str", "s", "", "请输入单词内容") // shorthand: 短标识; wordCmd.Flags().Int8VarP(&mode, "mode", "m", 0, "请输入单词转换的模式")
- 第一个参数为需绑定的变量
- 第二个参数为接收该参数的完整的命令标志
- 第三个参数为对应的短标识
- 第四个参数为默认值
- 第五个参数为使用说明
-
设置功能:
const ( ModeUpper = iota + 1 // 全部转大写;1 ModeLower // 全部转小写;2 ModeUnderscoreToUpperCamelCase // 下划线转大写驼峰;3 ModeUnderscoreToLowerCamelCase // 下线线转小写驼峰;4 ModeCamelCaseToUnderscore // 驼峰转下划线;5 ) var content string switch mode { case ModeUpper: content = word.ToUpper(str) case ModeLower: content = word.ToLower(str) case ModeUnderscoreToUpperCamelCase: content = word.UnderscoreToUpperCamelCase(str) case ModeUnderscoreToLowerCamelCase: content = word.UnderscoreToLowerCamelCase(str) case ModeCamelCaseToUnderscore: content = word.CamelCaseToUnderscore(str) default: log.Fatalf("暂不支持该转换模式,请执行 help word 查看帮助文档") }
功能具体实现
新增加internal目录:
$ tree
.
├── cmd
│ ├── root.go
│ └── word.go
├── internal
│ └── word
│ └── word.go
├── main.go
internal包,Go中命名为internal的package或者目录,两点需要注意:
- 只有直接父级package,以及父级package的子孙package可以访问,其他的都不行,再往上的祖先package也不行。
- 父级package也只能访问internal package使用大写暴露出的内容,小写的不行。
在项目中不被复用,也不能被其他项目导入,仅被本项目内部使用的代码包即私有的代码包都应该放在
internal
文件夹下。该文件夹下的所有包及相应文件都有一个项目保护级别,即其他项目是不能导入这些包的,仅仅是该项目内部使用。
internal/word/word.go
,功能的具体实现:
package word
import (
"strings"
"unicode"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
// 单词全部转为小写。
func ToLower(s string) string {
return strings.ToLower(s)
}
// 单词全部转为大写。
func ToUpper(s string) string {
return strings.ToUpper(s)
}
// 下划线单词转为大写驼峰。
func UnderscoreToUpperCamelCase(s string) string {
s = strings.Replace(s, "_", " ", -1) // 将下划线替换为空格字符
s = cases.Title(language.Und).String(s) // 将其所有字符修改为其对应的首字母大写的格式 strings.Title go1.18中被遗弃;
return strings.Replace(s, " ", "", -1) // 最后将先前的空格字符替换为空
}
// 下划线单词转为小写驼峰。
func UnderscoreToLowerCamelCase(s string) string {
s = UnderscoreToUpperCamelCase(s) // 主体逻辑可以直接复用大写驼峰的转换方法
return string(unicode.ToLower(rune(s[0]))) + s[1:] // 然后只需要对其首字母进行处理就好了
}
// 驼峰转下划线 eg AppStore --> app_store
func CamelCaseToUnderscore(s string) string {
var output []rune // rune代表一个utf-8字符
for i, r := range s {
if i == 0 {
output = append(output, unicode.ToLower(r))
continue
}
if unicode.IsUpper(r) {
output = append(output, '_')
}
output = append(output, unicode.ToLower(r))
}
return string(output)
}
-
注意Go 1.18以后,strings.Title()方法被遗弃了,用cases包代替:
s = cases.Title(language.Und).String(s) // 将其所有字符修改为其对应的首字母大写的格式