如何在golang中创建异步迭代器 - 但目前死锁

问题描述 投票:0回答:1

我有这个,我相信它接近按预期工作。我想做的是在一个序列上进行范围,但能够自己异步调用下一个项目

同步:

for r := range even.Sequence() {
    if !r.Done {
        r.Contnue()
    }
}

或异步:

   for r := range even.Sequence() {
        go func(){
          if !r.Done {
            r.Contnue()
           }
        }()
    }

这是 main 中的完整代码:

package main

import "fmt"

type HasNext[T any] interface {
    Next() (bool, T)
}

type Nexter[T int] struct {
    Val int
    End int
}

type Ret struct {
    Done    bool
    Value   int
    Contnue func()
}

func (n *Nexter[int]) Sequence() chan Ret {

    var c = make(chan Ret)
    even := newEven()

    var x func()

    x = func() {
        fmt.Println("got here 3")
        <-c
        fmt.Println("got here 4")
        fmt.Println("got here 5")
        var b, v = even.Next()
        c <- Ret{b, v, x}
        if b {
            close(c)
        }
    }

    go func() {
        var b, v = even.Next()
        fmt.Println("got here 1")
        c <- Ret{b, v, x}
        fmt.Println("got here 2")
    }()

    return c

}

func (n *Nexter[int]) Next() (bool, int) {
    n.Val = n.Val + 1
    if n.Val > n.End {
        return true, int(n.Val)
    }
    return false, int(n.Val)
}

func newEven() *Nexter[int] {
    n := 0
    return &Nexter[int]{n, 5}
}

func main() {


    even := newEven()


    for r := range even.Sequence() {

        fmt.Println("value:", r.Value)
        if !r.Done {
            fmt.Println("continuing...")
            r.Contnue()
        }
    }

}

但目前我得到这个输出:

got here 1
got here 2
value: 1
continuing...
got here 3
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
        /Users/me/codes/vibeirl/wss/test/iterator/main.go:83 +0x66

很明显它在某个地方陷入僵局,但不确定在哪里/如何准确

go deadlock goroutine
1个回答
0
投票

让它工作,我试图自己从通道中读取数据,但意识到(显然)范围本质上是从通道中读取的:

package main

import (
    "fmt"
    "time"
)

type HasNext[T any] interface {
    Next() (bool, T)
}

type Nexter[T int] struct {
    Val int
    End int
}

type Ret struct {
    Done    bool
    Value   int
    Contnue func()
}

func (n *Nexter[int]) Sequence() chan Ret {

    var c = make(chan Ret, 1)
    even := newEven()
    var isClosed = false

    var x func()

    x = func() {
        if isClosed {
            fmt.Println("warning channel closed")
            return
        }
        var b, v = even.Next()
        if b {
            isClosed = true
        }
        c <- Ret{b, v, x}
        if b {
            close(c)
        }
    }

    go func() {
        var b, v = even.Next()
        c <- Ret{b, v, x}
    }()

    return c

}

func (n *Nexter[int]) Next() (bool, int) {
    n.Val = n.Val + 1
    if n.Val >= n.End {
        return true, int(n.Val)
    }
    return false, int(n.Val)
}

func newEven() *Nexter[int] {
    n := 0
    return &Nexter[int]{n, 5}
}

func main() {

    even := newEven()

    for r := range even.Sequence() {

        time.Sleep(time.Millisecond * 500)

        fmt.Println("value:", r.Value)

        if !r.Done {
            r.Contnue()
        }


    }

}

我想知道一些事情 - isClosed 是否需要用锁来保护,但对我来说要弄清楚如何做到这一点并不容易

© www.soinside.com 2019 - 2024. All rights reserved.