566
社区成员
发帖
与我相关
我的任务
分享
linktable · qyanzh/menu - 码云 - 开源中国 (gitee.com)
先写接口,把接口调用串起来,然后再实现,可以使得代码结构变得更加清晰,让我们对代码流程有一个宏观的把握,并且可以提早发现错误,提高代码质量。
type Node struct {
Next *Node
}
type ILinkTable interface {
AddLinkTableNode(node *Node) error
DelLinkTableNode(node *Node) error
GetLinkTableHead() *Node
GetNextLinkTableNode(node *Node) (*Node, error)
}
type LinkTable struct {
Head *Node
Tail *Node
SumOfNode int
mutex sync.Mutex
}
func (lt *LinkTable) AddLinkTableNode(node *Node) error {
if node == nil {
return fmt.Errorf("nil node")
}
lt.mutex.Lock()
if lt.Head == nil {
lt.Head = node
lt.Tail = node
} else {
lt.Tail.Next = node
lt.Tail = lt.Tail.Next
}
lt.SumOfNode++
lt.mutex.Unlock()
return nil
}
func (lt *LinkTable) DelLinkTableNode(node *Node) error {
if node == nil {
return fmt.Errorf("nil node")
}
if lt.Head == nil {
return fmt.Errorf("empty table")
}
pre := &Node{Next: lt.Head}
for pre.Next != nil {
if pre.Next == node {
lt.mutex.Lock()
pre.Next = node.Next
if node == lt.Head {
lt.Head = lt.Head.Next
}
if node == lt.Tail {
lt.Tail = lt.Tail.Next
}
lt.SumOfNode--
lt.mutex.Unlock()
return nil
}
pre = pre.Next
}
return fmt.Errorf("node isn't in table")
}
func (lt *LinkTable) GetLinkTableHead() *Node {
return lt.Head
}
func (lt *LinkTable) GetNextLinkTableNode(node *Node) (*Node, error) {
if node == nil {
return nil, fmt.Errorf("nil node")
}
if lt.Head == nil {
return nil, fmt.Errorf("empty table")
}
for p := lt.Head; p != nil; {
if p == node {
return p.Next, nil
}
p = p.Next
}
return nil, fmt.Errorf("node isn't in table")
}
func CreateLinkTable() *LinkTable {
return &LinkTable{}
}
type MyNode struct {
Node
data int
}
func TestLinkTable(t *testing.T) {
lt := CreateLinkTable()
for i := 0; i < 10; i++ {
node := MyNode{data: i}
pNode := (*Node)(unsafe.Pointer(&node))
if err := lt.AddLinkTableNode(pNode); err != nil {
panic(err)
}
fmt.Println("AddLinkTableNode")
}
lt.Traverse()
myNode := lt.Search(5)
fmt.Println(myNode.data)
fmt.Println("DelLinkTableNode")
err := lt.DelLinkTableNode((*Node)(unsafe.Pointer(myNode)))
if err != nil {
panic(err)
}
lt.Traverse()
}
func (lt *LinkTable) Search(target int) *MyNode {
var err error
node := lt.GetLinkTableHead()
for node != nil {
myNode := (*MyNode)(unsafe.Pointer(node))
if myNode.data == target {
return myNode
}
node, err = lt.GetNextLinkTableNode(node)
if err != nil {
panic(err)
}
}
return nil
}
func (lt *LinkTable) Traverse() {
var err error
node := lt.GetLinkTableHead()
for node != nil {
myNode := (*MyNode)(unsafe.Pointer(node))
fmt.Printf("%d ", myNode.data)
node, err = lt.GetNextLinkTableNode(node)
if err != nil {
panic(err)
}
}
fmt.Println()
}