goAgenda——CLI

服务计算——goAgenda

1. 安装使用 cobra

根据老师的指令:

  • go get -v github.com/spf13/cobra/cobra

随后会遇到以下的情况(提示报错信息):

Fetching https://golang.org/x/sys/unix?go-get=1

https fetch failed: Get https://golang.org/x/sys/unix?go-get=1: dial tcp 216.239.37.1:443: i/o timeout

到这里我们有两个解决的办法:

  1. 进入 $GOPATH/src/golang.org/x文件夹下,使用:
  1. 进入该链接,下载所需的文件,解压后复制到本地

随后使用

  • go install github.com/spf13/cobra/cobra

即可完成cobra的安装


2. goAgenda知识点汇总

2.1 JSON读写学习

2.1.1 编码

结构体转JSON代码:

package main

import (
    "encoding/json"
    "fmt"
)

type DebugInfo struct {
    Level  string `json:"level,omitempty"` // Level解析为level,忽略空值
    Msg    string `json:"message"`         // Msg解析为message
    Author string `json:"-"`               // 忽略Author,或者设为未导出字段
}


func main() {

    dbgInfs := []DebugInfo{
        DebugInfo{"debug", `File: "test.txt" Not Found`, "Cynhard"},
        DebugInfo{"", "Logic error", "Gopher"},
    }

    if data, err := json.Marshal(dbgInfs); err == nil {
        fmt.Printf("%s\n", data)
    }
}

自定义结构对MarshalJSON()接口的实现

package main

import (
    "encoding/json"
    "fmt"
)

type Point struct{ X, Y int }

func (pt Point)MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"X":%d,"Y":%d}`, pt.X, pt.Y)), nil
}

func main() {
    if data, err := json.Marshal(Point{50, 50}); err == nil {
        fmt.Printf("%s\n", data)
    }
}
2.1.2 解码

解码主要使用的是JSON包的函数func Unmarshal(data []byte,v interface{}) error

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    data := `[{"Level":"debug","Msg":"File: \"test.txt\" Not Found"},` +
        `{"Level":"","Msg":"Logic error"}]`

    var dbgInfos []map[string]string
    json.Unmarshal([]byte(data), &dbgInfos)

    fmt.Println(dbgInfos)
}
2.1.3 JSON转结构体

与编码一样,JSON是通过反射机制来实现解码的,所以结构必须导出所转换的字段,不导出的字段不会被JSON包解析。另外解析的时候不区分大小写。

package main

import (
    "encoding/json"
    "fmt"
)

type DebugInfo struct {
    Level string
    Msg string
    author string  // 未导出字段不会被json解析
}

func (dbgInfo DebugInfo) String() string {
    return fmt.Sprintf("{Level: %s, Msg: %s}", dbgInfo.Level, dbgInfo.Msg)
}

func main() {
    data := `[{"level":"debug","msg":"File Not Found","author":"Cynhard"},` +
        `{"level":"","msg":"Logic error","author":"Gopher"}]`

    var dbgInfos []DebugInfo
    json.Unmarshal([]byte(data), &dbgInfos)

    fmt.Println(dbgInfos)
}

结构体也可以与编码的时候一样设置结构体字段标签

2.1.4 转换接口

和编码的时候类似,解码使用接口Unmarshaler,需要实现UnmarshalJSON([]byte) error

下面这个接口没有实现解码算法,只是将参数打印出来

package main

import (
    "encoding/json"
    "fmt"
)

type Point struct{ X, Y int }

func (Point) UnmarshalJSON(data []byte) error {
    fmt.Println(string(data))
    return nil
}

func main() {
    data := `{"X":80,"Y":80}`
    var pt Point
    json.Unmarshal([]byte(data), &pt)
}

2.2 文件读写

使用ioutil的ReadFile和WriteFile,并使用stirng()等函数进行类型转换,例程:

package main

import(
    "fmt"
    "io/ioutil"
)

func main() {
    //read
    b, err := ioutil.ReadFile("test.log")
    if err != nil {
        fmt.Print(err)
    }
    fmt.Println(b)
    str := string(b)
    fmt.Println(str)
    //write
    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("test.txt", d1, 0644)
    check(err)
}

2.3 实例

使用user进行的测试(已经通过)

	var myuser []entity.User
	fmt.Println("JSON decode to structure test1")
	jsonStr := `[{"username":"wtysos11""password":"123456","email":"wtysos11"}{"username":"wtysos11","password":"123456""email":"wtysos11"}]`
	json.Unmarshal([]byte(jsonStr),&myuser)
	fmt.Println(myuser)
	
	if data,err:=json.Marshal(myuser);err==nil{
		fmt.Printf("%s\n",data)
	}

2.4 StringArray使用

使用cmd.Flags().StringArray()可以声明一个flag
使用cmd.Flags().GetStringArray()可以取得这个数组
对于数组而言只有重复使用标签才能够作为不同元素,比如-a="ss" -a="tt",而同一个标签内都算作是一个字符窜


2.5 异常

if 遇到错误
    return errors.New("遇到xx错误")

3. 分析设计

3.1 子命令

  • 大的方向上要实现help、user、meeting三个子命令
  • 用户信息存储在curUser.txt中,UserMeeting实体要用json进行存储
  • 实现日志服务

3.2 agenda help

寻求帮助使用子命令agenda help,列出命令说明。此外输入agenda help register可以列出regsiter命令的描述


3.3 agenda user register

用户注册使用命令agenda user register

改指令可接受四个参数(必选):

  • –username/-u,用户名
  • –password/-p,密码
  • –email/-e,邮箱
  • –telphone/-t,电话

  • 此外用户名是唯一的,要查重。
  • 邮箱、电话要检查有效性。

反馈

  • 如果登记成功,返回成功注册的信息
  • 如果登记失败,反馈错误信息

3.4 agenda user login

用户登录使用子命令agenda user login

  • –username/-u,用户名
  • –password/-p,密码

  • 用户名密码这两个参数为必须

反馈

  • 用户名与密码都正确的时候返回一个成功登录的信息
  • 登录失败,返回登录失败的信息

3.5 agenda user logout

用户登出使用子命令agenda user logout

用户登出后只能够使用用户注册和用户登录功能且这里命令不接受参数

反馈

  • 反馈登出信息

3.6 agenda user lookup

在创建的用户中查找某用户使用子命令agenda user lookup

注:

只有在已经登录的状态才可以使用

反馈

  • 如果找到用户,返回已注册的所有用户的用户名、邮箱以及电话信息(打表)

3.7 agenda user delete

删除用户使用子命令agenda user delete

  • 操作为删除自己的账号,自动注销
  • 用户账号删除之后:
    • 以该用户为发起者的会议将会被删除
    • 以该用户为参与者的会议将会从参与者列表中移除该用户。如果此操作造成参与者数量为0,则会议也会被移除。

反馈:

  • 返回成功注销的信息
  • 失败要返回注销失败(有什么情况会导致注销失败吗?)

3.8 agenda meeting create

创建会议使用子命令agenda meeting create

参数:

  • –start/-s,开始时间,格式为(YYYY-MM-DD/HH:mm:ss)
  • –end/-e,结束时间
  • –title/-t,会议主题
  • –participant/-p,会议参与者

注:

  • 用户无法分身参与多个会议,如果用户已有的会议安排与将要创建的会议在时间上有重叠,则会无法创建这个会议。
  • 会议主题是唯一的。

反馈:

  • 成功返回创建成功提示信息
  • 失败返回创建失败相关信息

3.9 agenda meeting addUser

添加会议参与者使用子命令meeting addUser -p [Participator] -t [Title]

参数:

  • –title/-t,会议主题
  • –participants/-p,要添加的用户名(可以为多个)

反馈:

  • 成功返回相关信息
  • 失败也返回相关信息

3.10 agenda meeting deleteUser

删除会议参与者使用子命令meeting deleteUser -p [Participator] -t [Title]

参数:

  • –title/-t,会议主题
  • –participants/-p,要添加的用户名(可以为多个)

反馈:

  • 成功返回相关信息
  • 失败也返回相关信息

3.11 agenda meeting lookup

查找会议(仅登录可用)使用子命令meeting lookup -s [StartTime] -e [EndTime]

参数:

  • –start/-s,开始时间
  • –end/-e,结束时间

注:

  • 已登录的用户可以查询自己的议程在某一时间段内的所有会议安排

3.11 agenda meeting cancel

取消会议(已经登录的用户可以取消自己发起的某一会议安排)使用子命令meeting cancel -t [title]

参数:

  • –title/-t,会议主题

3.12 agenda meeting exit

退出会议(已经登录的用户可以退出自己参与的某一会议安排)使用子命令meeting exit -t [title]

参数:

  • –title/-t,会议主题

注:

  • 如果此操作造成会议参与者人数为0,则会议将会被删除

3.13 agenda meeting clear

清空会议(已经登录的用户可以清空自己发起的所有会议安排)使用子命令clear


4. 数据结构定义

4.1 用户(user)

位置:entity/useroper.go

作用:定义用户所需要的结构,以及相关的操作函数

type User struct{

    Username string //用户名

    Password string //密码

    Email string // 电子邮箱
 
    Telphone string // 电话

}

4.2 会议(conference)

位置:entity/conference.go

作用:定义会议所需要的结构,以及相关的操作函数

type Meeting struct{

    StartTime string //开始时间

    EndTime string //结束时间

    Title string //会议标题
    
    UserList []User //参与人数列表 
}

5. 程序测试

为了可以在任意位置使用agenda命令,而不是进入工作目录后go run main.go,采用先go build main.go后重命名可执行程序为agenda,然后移动到gowork/bin中,在每次运行命令时,golang会根据GOPATH的位置,在bin中找到相应的可执行程序,从而在任意位置使用agenda命令。

本次测试的shell为Z shell(zsh)。

根据cmd-design中的需求,对三个子命令分别进行测试,并将相应输出记录到日志中。

5.1 agenda根命令

1

5.2 help子命令

可以查看user子命令的帮助信息,用法如下:

  1. agenda help user
  2. agenda user —help

2

还可以查看用户命令下的其他子命令用法,如agenda help user register等。

在这里插入图片描述

在这里插入图片描述

查看meeting子命令的帮助信息,用法:

  1. agenda help meeting
  2. agenda meeting --help

在这里插入图片描述

在这里插入图片描述

同样查看用户命令下的其他子命令用法,如agenda help meeting addUser等。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.3 user子命令

5.3.1 lookup

由于需要在运行agenda命令的目录下中保存user.txt和cache.txt,估进入goAgenda目录。

初始时在cache.txt保存着一个用户的登录信息,故可以直接使用lookup命令。

在这里插入图片描述

退出后cache.txt为logout状态,且只能使用register和login命令(见上图)。

在这里插入图片描述

5.3.2 login

在这里插入图片描述

5.3.3 register

在这里插入图片描述

5.3.4 delete

在这里插入图片描述

5.4 meeting子命令

5.4.1 lookup

在这里插入图片描述

5.4.2 addUser

在这里插入图片描述

在这里插入图片描述

5.4.3 deleteUser

在这里插入图片描述

在这里插入图片描述

5.3.4 cancel

在这里插入图片描述

在这里插入图片描述

5.3.5 create

在这里插入图片描述

5.3.6 exit

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.3.7 clear

在这里插入图片描述


6. 项目组内成员与分工

姓名学号工作
王迎旭16340226实验报告与测试程序
吴天扬16340240整体框架的搭建、user与meeting功能的完善
王泽浩16340232debug与优化提示信息
吴聪16340237完善日志功能、完善程序接口

7. 源代码

Github


8. 参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值