用Go编写一个Linktable库

statelogin 2022-04-06 12:10:58

一. LinkTable.go

1. 定义LinkTableNode节点和LinkTable的结构

type LinkTableNode struct {
	pNext *LinkTableNode
}

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

2. 定义创建LinkTable和删除LinkTable的函数

/*
 * Create a LinkTable
 */
func CreateLinkTable() *LinkTable {
	LinkTable := LinkTable{}
	pLinkTable := &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 -1
	}
	for {
		if pLinkTable.pHead == nil {
			break
		}
		pLinkTable.mutex.Lock()
		pLinkTable.pHead = pLinkTable.pHead.pNext
		pLinkTable.SumOfNode -= 1
		pLinkTable.mutex.Unlock()

	}
	pLinkTable.pHead = nil
	pLinkTable.pTail = nil
	pLinkTable.SumOfNode = 0

	return 0
}

3.  向LinkTable中添加LinkTableNode或者删除LinkTableNode

/*
 * Add a LinkTableNode to LinkTable
 */
func AddLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) int {
	if pLinkTable == nil || pNode == nil {
		return -1
	}
	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 0
}

/*
 * Delete a LinkTableNode from LinkTable
 */
func DelLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode) int {
	if pLinkTable == nil || pNode == nil {
		return -1
	}
	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 0
	}
	var pTempNode *LinkTableNode = pLinkTable.pHead
	for {
		if pTempNode == nil {
			break
		}
		if pTempNode.pNext == pNode {
			pTempNode.pNext = pTempNode.pNext.pNext
			pLinkTable.SumOfNode -= 1
			if pLinkTable.SumOfNode == 0 {
				pLinkTable.pTail = nil
			}
			pLinkTable.mutex.Unlock()
			return 1
		}
		pTempNode = pTempNode.pNext
	}
	pLinkTable.mutex.Unlock()
	return -1
}

 4. 查询时,先获取LinkTable头节点

/*
 * get LinkTableHead
 */
func GetLinkTableHead(pLinkTable *LinkTable) *LinkTableNode {
	if pLinkTable == nil {
		return nil
	}
	return pLinkTable.pHead
}

5. 查询时,每次获取LinkTable的下一节点 

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

 

二. LinkTableTest.go(测试LinkTable.go效果)

 1. 定义自己的结构体,内部包含LinkTableNode,可以添加其他元素

type Node struct {
	node LinkTableNode
	data int
	// data2 int
}

2.  定义查询链表节点的函数,利用内部LinkTableNode的指针建立LinkTable并遍历。为了使LinkTableNode指针能对应到Node中的其他元素,使用unsafe包的功能,将LinkTableNode指针转为Node的指针,以访问其他元素。通过指针转换,可以让外部自定义的结构体和函数通过LinkTableNode指针,调用LinkTable库的接口完成相关操作,从而实现模块化的效果。

func Search(pLinkTable *LinkTable) *Node {
	var pNode *Node = &Node{}
	//tansfer the pointer with unsafe package
	pNode = (*Node)(unsafe.Pointer(reflect.ValueOf(GetLinkTableHead(pLinkTable)).Pointer()))
	for {
		if pNode == nil {
			break
		}
		if pNode.data == 5 {
			return pNode
		}

		pNode = (*Node)(unsafe.Pointer(reflect.ValueOf(GetNextLinkTableNode(pLinkTable, &pNode.node)).Pointer()))

	}
	return nil
}

3.  测试所用的main函数,基于上述原理建立LinkTable, 测试相关操作

func main() {
	//build the LinkNodeTable
	pLinkTable := CreateLinkTable()
	if pLinkTable == nil {
		fmt.Println("CreateLinkTable Error!")
		os.Exit(0)
	}
	for i := 0; i < 10; i++ {
		var pNode *Node = &Node{}
		pNode.data = i
		// pNode.data2 = i * i
		if AddLinkTableNode(pLinkTable, &pNode.node) == -1 {
			fmt.Println("AddLinkTable Error!")
			os.Exit(0)
		}
	}
	// search one by one
	var pTempNode *Node = Search(pLinkTable)
	if pTempNode == nil {
		fmt.Println("Cannot find the node you need!")
		os.Exit(0)
	}

	fmt.Printf("%d\n", pTempNode.data)
	DelLinkTableNode(pLinkTable, &pTempNode.node)
	DeleteLinkTable(pLinkTable)
}

4. 运行结果

 

 

三. 编写心得

LinkTable.go包括结构体和常见操作的函数,通过结构体指针的传入传出实现对外接口。主函数可以通过接口调用这个库,实现链表的创建和操作,且主函数中的链表节点可以添加不同元素。但是此版本的库遵循的仍是C语言的思路,以指针操作为主,go语言下还有其他思路实现类似功能。

 

https://gitee.com/statelogin/se-menu/tree/master/experiment3

作者:21225 245 

 

 

 

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

571

社区成员

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

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