同时将节点添加到链表中(使用golang)

huangapple go评论69阅读模式
英文:

Concurrently Add Nodes to Linked List golang

问题

我正在尝试使用通道和goroutine并发地向链表中添加节点。然而,我似乎做错了一些事情。以下是我目前编写的代码。

目前,我的打印函数只是重复打印第8个节点。这在其他链表上似乎是有效的,所以我不太理解问题所在。任何帮助都将是很好的。这是我编写的代码:

func makeNodes(ctx context.Context, wg *sync.WaitGroup, ch chan Node) {
	defer wg.Done()
	for i := 0; i < 9; i++ {
		tmp := Node{Data: i, Next: nil}
		ch <- tmp
	}
	<-ctx.Done()
	return
}

type Node struct {
	Data int
	Next *Node
}

type List struct {
	Head   *Node
	Length int
	Last   *Node
}

func (l *List) addToEnd(n *Node) {
	if l.Head == nil {
		l.Head = n
		l.Last = n
		l.Length++
		return
	}
	tmp := l.Last
	tmp.Next = n
	l.Last = n
	l.Length++
}

func (l List) print() {
	tmp := l.Head
	for tmp != nil {
		fmt.Println(tmp)
		tmp = tmp.Next
	}
	fmt.Println("\n")
}

func main() {
	cha := make(chan Node)
	defer close(cha)

	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	var wg sync.WaitGroup

	wg.Add(1)
	list := List{nil, 0, nil}
	go makeNodes(ctx, &wg, cha)

	go func() {
		for j := range cha {
			list.addToEnd(&j)
		}
	}()

	cancel()
	wg.Wait()

	list.print()
}

希望对你有所帮助!

英文:

I'm trying to add nodes to a linked list concurrently using channels and goroutines. I seem to be doing be something wrong, however. Here's what I've written so far.

Currently, my print function is just repeating the 8th node. This seems to work on other linked lists, so I don't totally understand the issue. Any help would be great. Here is the code that I wrote

func makeNodes(ctx context.Context, wg *sync.WaitGroup, ch chan Node) {
defer wg.Done()
for i := 0; i &lt; 9; i++ {
tmp := Node{Data: i, Next: nil}
ch &lt;- tmp
}
&lt;-ctx.Done()
return
}
type Node struct {
Data int
Next *Node
}
type List struct {
Head   *Node
Length int
Last   *Node
}
func (l *List) addToEnd(n *Node) {
if l.Head == nil {
l.Head = n
l.Last = n
l.Length++
return
}
tmp := l.Last
tmp.Next = n
l.Last = n
l.Length++
}
func (l List) print() {
tmp := l.Head
for tmp != nil {
fmt.Println(tmp)
tmp = tmp.Next
}
fmt.Println(&quot;\n&quot;)
}
func main() {
cha := make(chan Node)
defer close(cha)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
wg.Add(1)
list := List{nil, 0, nil}
go makeNodes(ctx, &amp;wg, cha)
go func() {
for j := range cha {
list.addToEnd(&amp;j)
}
}()
cancel()
wg.Wait()
list.print()
}

答案1

得分: 1

这个程序通过在for j:= range循环中分配一个单一的结构体(j),并重复用从通道中读取的内容覆盖它。

这导致同一个变量(j)多次添加到列表中,但它们位于固定的内存位置。

考虑将通道修改为指针类型的通道。

main()函数中:

cha := make(chan *Node)

然后在makeNodes()函数中:
每次创建一个新节点(通过Node{}),将一个新的节点指针放入通道中。

func makeNodes(ctx context.Context, wg *sync.WaitGroup, ch chan *Node) {
defer wg.Done()
for i := 0; i < 9; i++ {
tmp := Node{Data: i, Next: nil}
ch <- &tmp
}
<-ctx.Done()
return
}

现在,以下代码将正确地将每个唯一的节点指针添加到列表中。

go func() {
for j := range cha {
list.addToEnd(j)
}
}()

此外,你可能会发现并非所有实体都能添加到列表中或从通道中读取。你需要改进生产者(makeNodes())和消费者(for j:= range)之间的同步方法。

英文:

This program allocates a single structure (j in the for j:= range loop) and repeatedly overwrites it with the contents read from the channel.

This results in the same variable (j, at a fixed memory location) being added to the list multiple times.

Consider modifying the channel to be a channel of pointers.

In main()

cha := make(chan *Node)

Then for makeNodes()
Each time a new node is created (via Node{}), a new Node pointer is placed into the channel.

func makeNodes(ctx context.Context, wg *sync.WaitGroup, ch chan *Node) {
defer wg.Done()
for i := 0; i &lt; 9; i++ {
tmp := Node{Data: i, Next: nil}
ch &lt;- &amp;tmp
}
&lt;-ctx.Done()
return
}

The following will now correctly add each unique Node pointer to the list.

go func() {
for j := range cha {
list.addToEnd(j)
}
}()

Also, you may find not all entities make it to the list or are read from the channel. Your method for synchronizing the producer (makeNodes()) and consume (for j:= range) needs work.

huangapple
  • 本文由 发表于 2022年6月27日 12:21:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/72766963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定