代码之家  ›  专栏  ›  技术社区  ›  vtm11

Python样式生成器实现为通道:过早读取

  •  1
  • vtm11  · 技术社区  · 2 年前

    我尝试用下面的通道实现Python风格的生成器 this :

    package main
    
    import (
        "fmt"
    )
    
    type ContainerIterable[T any] struct {
        content []T
    }
    
    func NewContainerIterable[T any]() *ContainerIterable[T] {
        return &ContainerIterable[T]{content: make([]T, 0)}
    }
    
    func (c *ContainerIterable[T]) Iterate() chan T {
        ch := make(chan T)
        go func() {
            for _, v := range c.content {
                ch <- v
            }
            close(ch)
        }()
        return ch
    }
    
    func (c *ContainerIterable[T]) Add(e T) {
        c.content = append(c.content, e)
    }
    
    func main() {
        c := NewContainerIterable[int]()
    
        for i := 0; i < 5; i++ {
            c.Add(i)
        }
    
        r := make([]int, 0)
        for v := range c.Iterate() {
            r = append(r, v)
        }
    
        for i := 0; i < 5; i++ {
            fmt.Println(i, r[i], i == r[i])
        }
    }
    

    这工作得很好,输出

    0 0 true
    1 1 true
    2 2 true
    3 3 true
    4 4 true
    

    然而,当我改变

    r := make([]int, 0)
    

    r := make([]int, 5)
    

    结果是不同的:

    0 0 true
    1 0 false
    2 0 false
    3 0 false
    4 0 false
    

    我理解第二种情况 c.Iterate() 在之前开始从通道读取

        go func() {
            for _, v := range c.content {
                ch <- v
            }
    

    有机会向频道发送任何内容。 这不适用于第一种情况,因为 main() goroutine需要一些时间来重新分配空间 r 切片时间 append() 被调用。

    请建议如何调整我的代码 Iterate() 工作正常吗?

    1 回复  |  直到 2 年前
        1
  •  1
  •   Burak Serdar    2 年前

    这个:

    r := make([]int, 5)
    

    将初始化一个具有5个元素(全部为0)的切片。然后你将再添加5个元素。你的程序正在读取前5个零元素。

    使用: r:=make([]int,0,5)