使用Go
语言编写一个Linktable
的库,并重写Menu
程序,将代码上传至GitHub
学习和使用了Go语言以及接口的定义与设计
库的接口设计尽量与业务逻辑独立,从而提高程序的复用性
代码参考Lab7
编写LinkTable
库
定义结点和链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
type LinkTableNode struct { pNext *LinkTableNode }
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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中包含的结构体指针类型转换使用了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
| 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
| 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
| 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
| func ExecuteMenu() { 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() }
|
运行结果
在GitHub上更新代码
代码地址
1 2 3
| git add linktable.go git commit -m "add basic link table interface" git push
|
作者:406