Go实现LinkTable库

余生. 2022-04-04 14:42:42

使用go重写老师所给的LinkTable及menu.c(main.go)

一、LinkTable

package main

import (
	"fmt"
	"sync"
)

/********************************************************************/
/* Copyright (C) LK-USTC, 2022                                      */
/*                                                                  */
/*  FILE NAME             :  linktabe.go                            */
/*  PRINCIPAL AUTHOR      :  LeiKun                                 */
/*  SUBSYSTEM NAME        :  menu                                   */
/*  MODULE NAME           :  menu                                   */
/*  LANGUAGE              :  GO                                     */
/*  TARGET ENVIRONMENT    :  ANY                                    */
/*  DATE OF FIRST RELEASE :  2022/04/04                             */
/*  DESCRIPTION           :  interface of Link Table                */
/********************************************************************/

const SUCCESS = 0
const FAILURE = -1

/*
 * LinkTable Node Type
 */
type LinkTableNode struct {
	pNext *LinkTableNode
}

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

/*
 * 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
}

/*
 * 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
}

/*
 * 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 += 1
	pLinkTable.mutex.Unlock()
	return SUCCESS
}

/*
 * 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 -= 1
		if pLinkTable.SumOfNode == 0 {
			pLinkTable.pTail = nil
		}
		pLinkTable.mutex.Unlock()
		return SUCCESS
	}
	var pTempNode *LinkTableNode = pLinkTable.pHead

	for pTempNode != nil {
		if pTempNode == pNode {
			pTempNode.pNext = pTempNode.pNext.pNext
			pLinkTable.SumOfNode -= 1
			if pLinkTable.SumOfNode == 0 {
				pLinkTable.pTail = nil
			}
			pLinkTable.mutex.Unlock()
			return SUCCESS
		}
		pTempNode = pTempNode.pNext
	}
	pLinkTable.mutex.Unlock()
	return FAILURE
}

/*
 * get LinkTableHead
 */
func GetLinkTableHead(pLinkTable *LinkTable) *LinkTableNode {
	if pLinkTable == nil {
		fmt.Println("It's empty LinkTable,return nil !!!")
		return nil
	}
	return pLinkTable.pHead
}

/*
 * get next LinkTableNode
 */
func GetNextLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) *LinkTableNode {
	if pLinkTable == nil || pNode == nil {
		return nil
	}
	var pTempNode = pLinkTable.pHead
	for pTempNode != nil {
		if pTempNode == pNode {
			return pTempNode.pNext
		}
		pTempNode = pTempNode.pNext
	}
	return nil
}

二、问题

注意问题 :

1、在go中使用其他.go文件定义,需要其在定义一个package下,本项目为(main)

2、进行强制类型转换时

C/C++:

tDataNode * pNode = (tDataNode*)GetLinkTableHead(head);

go,需要使用unsafe包进行类型强制转换:

var pNode *DataNode = (*DataNode)(unsafe.Pointer(GetLinkTableHead(head)))

3、go互斥锁

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

三、测试

代码:

package main

import (
	"fmt"
	"unsafe"
)

/**************************************************************************************************/
/* Copyright (C) ,LK_USTC, 2022                                                                   */
/*                                                                                                */
/*  FILE NAME             :  main.go                                                              */
/*  PRINCIPAL AUTHOR      :  LeiKun                                                               */
/*  SUBSYSTEM NAME        :  menu                                                                 */
/*  MODULE NAME           :  menu                                                                 */
/*  LANGUAGE              :  GO                                                                   */
/*  TARGET ENVIRONMENT    :  ANY                                                                  */
/*  DATE OF FIRST RELEASE :  2022/04/04                                                           */
/*  DESCRIPTION           :  This is a menu program                                               */
/**************************************************************************************************/

const CMD_MAX_LEN = 128
const DESC_LEN = 1024
const CMD_NUM = 10

/* data struct and its operations */
type DataNode struct {
	pNext   *LinkTableNode
	cmd     string
	desc    string
	handler func() int
}

/* 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
}

/* show all cmd in listlist */
func ShowAllCmd(head *LinkTable) int {
	var pNode *DataNode = (*DataNode)(unsafe.Pointer(GetLinkTableHead(head)))
	for pNode != nil {
		fmt.Printf("%s - %s\n", pNode.cmd, pNode.desc)
		pNode = (*DataNode)(unsafe.Pointer(GetNextLinkTableNode(head, (*LinkTableNode)(unsafe.Pointer(pNode)))))
	}
	return 0
}

//init DataNode
func InitMenuData(ppLinktable **LinkTable) int {
	*ppLinktable = CreateLinkTable()
	pNode := new(DataNode)
	pNode.cmd = "help"
	pNode.desc = "Menu List"
	pNode.handler = Help
	AddLinkTableNode(*ppLinktable, (*LinkTableNode)(unsafe.Pointer(pNode)))
	pNode = new(DataNode)
	pNode.cmd = "version"
	pNode.desc = "Menu Program v2.0"
	pNode.handler = version
	AddLinkTableNode(*ppLinktable, (*LinkTableNode)(unsafe.Pointer(pNode)))
	pNode = new(DataNode)
	pNode.cmd = "quit"
	pNode.desc = "Quit from Menu Program v2.0"
	pNode.handler = Quit
	AddLinkTableNode(*ppLinktable, (*LinkTableNode)(unsafe.Pointer(pNode)))
	return 0
}

/* menu program */
var head *LinkTable = nil


func main() {
	InitMenuData(&head)
	var cmd string
	for {
		fmt.Print("Input a cmd number > ")
		fmt.Scanln(&cmd)
		p := FindCmd(head, cmd)
		if p == nil {
			fmt.Println("This is a wrong cmd!")
			continue
		}
		fmt.Printf("%s - %s\n", p.cmd, p.desc)
		if p.handler != nil {
			if p.handler() < 0 {
				return
			}
		}
	}
}

func Help() int {
	ShowAllCmd(head)
	return 0
}

func version() int {
	fmt.Println("menu version 2.0")
	return 0
}

func Quit() int {
	fmt.Println("Menu exit")
	return -1
}

 

更新库

 

 

gitee库:LinkTable

学号:SA21225256

...全文
155 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧