Cobra既是用于创建强大的现代CLI应用程序的库,也是用于生成应用程序和命令文件的程序。程序选择Cobra进行命令行的解析,以下配置基于Ubuntu16.04
直接使用命令 go get -v github.com/spf13/cobra/cobra
下载会出现错误,首先需要安装golang的项目依赖test和sys
首先cd到$GOPATH/src/golang.org/x文件夹下,采用git clone命令安装两个依赖包如下
执行go install github.com/spf13/cobra/cobra命令即可在$GOBIN下生成对应的可执行文件
在新建的项目文件夹下使用cobra init --pkg-name [name]命令可以初始化一个新的项目,成功后初始化的项目结构如下
在项目文件夹下使用Cobra add命令可以为你的程序添加新的命令,首先先添加一个login命令为例
可以看到命令执行完成后cmd文件夹下出现了一个login.go文件,只需要修改相应代码就可以执行相关命令了
由于要求简化,此次我只实现了用户相关的命令,没有实现会议相关的命令
实现的操作包括
用户注册
用户注册的代码实现逻辑是首先读取命令接收到的用户信息,接下来需要查找要注册的用户名是否已经注册,如果注册需要返回出错信息,用户信息我使用了一个json文件进行存取,使用go语言的"encoding/json"包对其进行编码,这里我在entity包编写了两个辅助函数用于对用户信息的保存和读取,代码实现如下
func GetUsers() []User {
jsondata, err := ioutil.ReadFile("./data/userinfo.json")
if err != nil{
fmt.Println(err)
}
var users []User
json.Unmarshal(jsondata, &users)
return users
}
func SetUsers(users []User) {
//源文件清除
os.Truncate("./data/userinfo.json", 0)
//转为json串
jsondata, err := json.Marshal(users)
if err != nil{
fmt.Println(err)
}
ioutil.WriteFile("./data/userinfo.json", jsondata, os.ModeAppend)
os.Chmod("./data/userinfo.json", 0777)//开放文件写权限
}
其中用户信息结构为一个结构体,包含4个字段
//用户信息
type User struct {
UserName string
Password string
Email string
Phone string
}
在用户注册过程中对各项信息的格式内容有一定的限制,这里我采取了正则表达式匹配的方式,如果注册成功将其写入json文件并给用户返回一个注册成功的信息
var registerCmd = &cobra.Command{
Use: "register",
Short: "user register",
Long: `use register -u [username], -p [password], -e [email], -c [cellphone] to register a user`,
Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("register called")
//获取参数
user, _ := cmd.Flags().GetString("username")
pass, _ := cmd.Flags().GetString("password")
email, _ := cmd.Flags().GetString("email")
phone, _ := cmd.Flags().GetString("cellphone")
//fmt.Println(user,pass,email,phone)
//未输入输出帮助信息
if user == "" || pass == "" || email == "" || phone == "" {
fmt.Println("User message can't be empty")
printRegisterUsage()
return
}
if !isNameVaild(user) || !isPasswordVaild(pass) || !isEmailVaild(email) || !isPhoneVaild(phone){
fmt.Println("Infomation error")
return
}
users := entity.GetUsers()
for i := 0; i < len(users); i ++{
if user == users[i].UserName{
fmt.Println("User name already exist")
return
}
}
newuser := entity.User{UserName: user, Password: pass, Email: email, Phone: phone}
users = append(users,newuser)
entity.SetUsers(users)//保存新用户
fmt.Println("Register success")
},
}
用户登录
用户登陆需要用户名存在于已注册用户列表中且密码需要和设置时候匹配,由于用户查询和用户删除操作需要在登陆的状态下才能操作,所以同样需要一个json文件保存当前登陆的用户,仿照用户注册需要两个辅助函数用于对当前登陆用户的读取和写入
func SetLoginUser(user *User){
//初始化清空
os.Truncate("./data/userLogin.json", 0)
if user != nil {
jsondata, err := json.Marshal(user)
if err != nil{
fmt.Println(err)
}
ioutil.WriteFile("./data/userLogin.json", jsondata, os.ModeAppend)
os.Chmod("./data/userLogin.json", 0777)//开放文件写权限
}
}
func GetLoginUser() *User{
var user User
jsondata, err := ioutil.ReadFile("./data/userLogin.json")
if err != nil{
fmt.Println(err)
}
json.Unmarshal(jsondata, &user)
return &user
}
用户登陆只需要判断用户名密码后将登陆用户写入文件即可
var loginCmd = &cobra.Command{
Use: "login",
Short: "user login",
Long: `use login -u [username], -p [password] to login`,
Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("login called")
user, _ := cmd.Flags().GetString("username")
pass, _ := cmd.Flags().GetString("password")
//未输入输出帮助信息
if user == "" || pass == "" {
fmt.Println("User message can't be empty")
printRegisterUsage()
return
}
users := entity.GetUsers()
for i := 0; i < len(users); i ++{
//用户存在
if user == users[i].UserName{
if pass == users[i].Password{
entity.SetLoginUser(&users[i])
fmt.Println(user + " login")
fmt.Println("Hello " + user)
return
}else{
fmt.Println("Password Error")
return
}
}
}
fmt.Println("User not exist")
},
}
用户登出
用户登出即首先判断是否登陆后将当前登陆的用户json文件设为空即可
var logoutCmd = &cobra.Command{
Use: "logout",
Short: "user logout",
Long: `use logout to logout your user`,
Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("logout called")
//获取当前登录用户
loginUser := entity.GetLoginUser()
if loginUser == nil{
fmt.Println("User not login")
}else{
fmt.Println(loginUser.UserName + " want to logout")
entity.SetLoginUser(nil)//保存当前登录用户为nil
fmt.Println(loginUser.UserName + " logout success")
}
},
}
用户查询
查询操作提供了一个可选参数-u,如果提供该参数则表示对单个用户查询,否则输出所有用户的信息,只需要获取所有用户后遍历输出结果即可
var queryuserCmd = &cobra.Command{
Use: "queryuser",
Short: "query single user or all users",
Long: `user queryuser to list all users
queryuser [-u name] to query single user`,
Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("queryuser called")
loginUser := entity.GetLoginUser()
users := entity.GetUsers()
user, _ := cmd.Flags().GetString("queryname")
if loginUser == nil || loginUser.UserName == ""{
fmt.Println("User not login")
}else{
fmt.Println(loginUser.UserName + " want to query user")
if user == ""{
for i := 0; i < len(users); i ++{
fmt.Print("Username: " + users[i].UserName + "\t")
fmt.Print("Email: " + users[i].Email + "\t")
fmt.Print("Phone: " + users[i].Phone + "\t")
fmt.Println("")
}
return
}else{
for i := 0; i < len(users); i ++{
if user == users[i].UserName{
fmt.Print("Username: " + users[i].UserName + "\t")
fmt.Print("Email: " + users[i].Email + "\t")
fmt.Println("Phone: " + users[i].Phone)
fmt.Println("")
return
}
}
fmt.Println("User you want to query not exist")
}
}
},
}
用户删除
用户删除只需要判断用户是否在登录状态,是的话调用辅助函数将当前用户设置为空,即实现用户登出并在所有用户的json文件中删除当前用户即可,这里使用切片后拼接的形式进行删除
var deleteuserCmd = &cobra.Command{
Use: "deleteuser",
Short: "delete user",
Long: `user deleteuser to delete user login`,
Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("deleteuser called")
loginUser := entity.GetLoginUser()
users := entity.GetUsers()
if loginUser == nil{
fmt.Println("User not login")
}else{
fmt.Println(loginUser.UserName + " want to delete user")
for i := 0; i < len(users); i ++{
if users[i].UserName == loginUser.UserName{
tmpName := loginUser.UserName
var tmpusers = users[:i]
tmpusers = append(tmpusers,users[i+1:]...)
entity.SetUsers(tmpusers)//重置users
entity.SetLoginUser(nil) //登录用户删除
fmt.Println("User " + tmpName + " is delete success")
return
}
}
}
},
}
本次程序测试在GoOnline上完成
由于GoOnline上的go语言包搜索路径和linux本地不一致,首先需要修改引用的entity和main.go下的cmd包路径为当前建立项目的路径,当前路径可以通过pwd命令查看
import(
"git.go-online.org.cn/agent0/agenda/entity"
"git.go-online.org.cn/agent0/agenda/cmd"
)
接下来输入命令su进入root用户模式,将将/home文件夹递归777权限
完成配置后就可以通过go run命令运行程序了
如果有参数没有输入会输出错误信息和正确的提示,信息格式错误也会提示
删除后使用另一个用户登录并查询该用户发现查询不到
登出后无法执行查询和删除用户功能
完整代码见GoOnline