使用Go语言编写Link Table库以及重写Menu

使用Go语言编写一个Linktable的库,并重写Menu程序,将代码上传至GitHub

学习和使用了Go语言以及接口的定义与设计

库的接口设计尽量与业务逻辑独立,从而提高程序的复用性

代码参考Lab7

编写LinkTable

定义结点和链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* LinkTable Node Type
*/
type LinkTableNode struct {
pNext *LinkTableNode
}

/*
* Define LinkTable
*/
type LinkTable struct {
pHead *LinkTableNode
pTail *LinkTableNode
SumOfNode int
mutex sync.Mutex
}

定义链表操作

创建链表

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
* Create a LinkTable
*/
func CreateLinkTable() *LinkTable {
var pLinkTable *LinkTable = new(LinkTable)
if pLinkTable == nil {
return nil
}
pLinkTable.pHead = nil
pLinkTable.pTail = nil
pLinkTable.SumOfNode = 0
return pLinkTable
}

删除链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
* Delete a LinkTable
*/
func DeleteLinkTable(pLinkTable *LinkTable) int {
if pLinkTable == nil {
return FAILURE
}
for pLinkTable.pHead != nil {
var p *LinkTableNode = pLinkTable.pHead
pLinkTable.mutex.Lock()
pLinkTable.pHead = p.pNext
pLinkTable.SumOfNode--
pLinkTable.mutex.Unlock()
}
pLinkTable.pHead = nil
pLinkTable.pTail = nil
pLinkTable.SumOfNode = 0
return SUCCESS
}

链表上添加结点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* Add a LinkTableNode to LinkTable
*/
func AddLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) int {
if pLinkTable == nil || pNode == nil {
return FAILURE
}
pNode.pNext = nil
pLinkTable.mutex.Lock()
if pLinkTable.pHead == nil {
pLinkTable.pHead = pNode
}
if pLinkTable.pTail == nil {
pLinkTable.pTail = pNode
} else {
pLinkTable.pTail.pNext = pNode
pLinkTable.pTail = pNode
}
pLinkTable.SumOfNode++
pLinkTable.mutex.Unlock()
return SUCCESS
}

链表上删除结点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
* Delete a LinkTableNode from LinkTable
*/
func DelLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) int {
if pLinkTable == nil || pNode == nil {
return FAILURE
}
pLinkTable.mutex.Lock()
if pLinkTable.pHead == pNode {
pLinkTable.pHead = pLinkTable.pHead.pNext
pLinkTable.SumOfNode--
if pLinkTable.SumOfNode == 0 {
pLinkTable.pTail = nil
}
pLinkTable.mutex.Unlock()
return SUCCESS
}
var pTempNode *LinkTableNode = pLinkTable.pHead
for pTempNode != nil {
if pTempNode.pNext == pNode {
pTempNode.pNext = pTempNode.pNext.pNext
pLinkTable.SumOfNode--
if pLinkTable.SumOfNode == 0 {
pLinkTable.pTail = nil
}
pLinkTable.mutex.Unlock()
return SUCCESS
}
pTempNode = pTempNode.pNext
}
pLinkTable.mutex.Unlock()
return FAILURE
}

在链表上查询结点(使用回调函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* Search a LinkTableNode from LinkTable
* Condition func(pNode *LinkTableNode, args interface{}) int
*/
func SearchLinkTableNode(pLinkTable *LinkTable, Condition func(pNode *LinkTableNode, args interface{}) int, args interface{}) *LinkTableNode {
if pLinkTable == nil || Condition == nil {
return nil
}
var pNode *LinkTableNode = pLinkTable.pHead
for pNode != nil {
if Condition(pNode, args) == SUCCESS {
return pNode
}
pNode = pNode.pNext
}
return nil
}

获取链表头

1
2
3
4
5
6
7
8
9
10
/*
* get LinkTableHead
*/
func GetLinkTableHead(pLinkTable *LinkTable) *LinkTableNode {
if pLinkTable == nil {
fmt.Println("LinkTable is empty")
return nil
}
return pLinkTable.pHead
}

获取链表尾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* get next LinkTableNode
*/
func GetNextLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) *LinkTableNode {
if pLinkTable == nil || pNode == nil {
fmt.Println("Linktable is empty")
return nil
}
var pTempNode *LinkTableNode = pLinkTable.pHead
for pTempNode != nil {
if pTempNode == pNode {
return pTempNode.pNext
}
pTempNode = pTempNode.pNext
}
return nil
}

编写Menu代码

Menu中包含的结构体指针类型转换使用了unsafe的指针转换

定义数据结点

1
2
3
4
5
6
type DataNode struct {
pnext *LinkTableNode
cmd string
desc string
handler func(argc int, argv []string)
}

定义搜索函数

1
2
3
4
5
6
7
8
func SearchConditon(pLinkTableNode *LinkTableNode, arg interface{}) int {
var cmd string = arg.(string)
var pNode *DataNode = (*DataNode)(unsafe.Pointer(pLinkTableNode))
if pNode.cmd == cmd {
return SUCCESS
}
return FAILURE
}

定义查找命令函数

1
2
3
4
5
6
7
8
9
10
11
/* find a cmd in the linklist and return the datanode pointer */
func FindCmd(head *LinkTable, cmd string) *DataNode {
var pNode *DataNode = (*DataNode)(unsafe.Pointer(GetLinkTableHead(head)))
for pNode != nil {
if pNode.cmd != cmd {
return pNode
}
pNode = (*DataNode)(unsafe.Pointer(GetNextLinkTableNode(head, (*LinkTableNode)(unsafe.Pointer(pNode)))))
}
return nil
}

定义显示所有命令函数

1
2
3
4
5
6
7
8
9
/* show all cmd in listlist */
func ShowAllCmd(head *LinkTable) int {
var pNode *DataNode = (*DataNode)(unsafe.Pointer(GetLinkTableHead(head)))
for pNode != nil {
fmt.Println(pNode.cmd + " - " + pNode.desc)
pNode = (*DataNode)(unsafe.Pointer(GetNextLinkTableNode(head, (*LinkTableNode)(unsafe.Pointer(pNode)))))
}
return 0
}

定义帮助函数

1
2
3
func Help(argc int, argv []string) {
ShowAllCmd(head)
}

定义添加命令函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* add cmd to menu */
func MenuConfig(cmd string, desc string, handler func(argc int, argv []string)) int {
var pNode *DataNode = nil
if head == nil {
head = CreateLinkTable()
pNode = new(DataNode)
pNode.cmd = "help"
pNode.desc = "Menu List:"
pNode.handler = Help
AddLinkTableNode(head, (*LinkTableNode)(unsafe.Pointer(pNode)))
}
pNode = new(DataNode)
pNode.cmd = cmd
pNode.desc = desc
pNode.handler = handler
AddLinkTableNode(head, (*LinkTableNode)(unsafe.Pointer(pNode)))
return 0
}

定义执行命令函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Menu Engine Execute */
func ExecuteMenu() {
/* cmd line begins */
for true {
var argc int = 0
var argv []string
var cmdline string
fmt.Print("Input a cmd > ")
fmt.Scan(&cmdline)
if cmdline == "" {
continue
}
var cmdList = strings.Split(cmdline, " ")
if len(cmdList) <= CMD_MAX_ARGV_NUM {
argc = len(cmdList)
} else {
fmt.Println("This is a wrong cmd!")
continue
}
argv = cmdList
var p *DataNode = (*DataNode)(unsafe.Pointer(SearchLinkTableNode(head, SearchConditon, argv[0])))
if p == nil {
fmt.Println("This is a wrong cmd!")
continue
}
if p.handler != nil {
p.handler(argc, argv)
}
}
}

定义退出函数

1
2
3
4
func Quit(argc int, argv []string) {
fmt.Println("Program terminated.")
os.Exit(0)
}

定义主函数

1
2
3
4
5
func main() {
MenuConfig("version", "Menu-Go V1.0(menu program v1.0 inside)", nil)
MenuConfig("quit", "Quit from Menu-Go", Quit)
ExecuteMenu()
}

运行结果

image-20220622143537817

在GitHub上更新代码

代码地址

1
2
3
git add linktable.go
git commit -m "add basic link table interface"
git push

image-20220406175330301

作者:406