切片附加在渠道上

时间:2013-11-06 17:36:53

标签: go

我想创建切片并添加从通道返回的值。 下面是我尝试但无法解决的代码。

我必须发送切片的地址,但我无法弄清楚如何:(

package main

import "fmt"
import "time"

func sendvalues(cs chan int){
    for i:=0;i<10;i++{
        cs<-i   
    }   
}

func appendInt(cs chan int, aINt []int)[]*int{
    for {
        select {
        case i := <-cs:
            aINt = append(aINt,i)//append returns new type right ?
            fmt.Println("slice",aINt)
        }   
    }   
}



func main() {
    cs := make(chan int)
    intSlice := make([]int, 0,10)

    fmt.Println("Before",intSlice)
    go sendvalues(cs)
    go appendInt(cs,intSlice)// I have to pass address here

    time.Sleep(999*999999)
    fmt.Println("After",intSlice)
}

1 个答案:

答案 0 :(得分:10)

您的代码不适用于两个(实际上是三个)原因:

  1. append会在达到容量后立即返回新切片。 因此,appendInt中的作业将不执行任何操作。

  2. appendInt同时运行,因此:

    • 只要appendInt没有告知main它已完成, main无法知道intSlice何时拥有您想要的所有值。
    • 您必须等待所有goroutines在main
    • 结束时返回
  3. 问题1:修改函数中的切片

    您可能知道在Go中,您传递给函数的每个值都会被复制。参考值, 如切片,也被复制,但内部有指针,然后指向原始内存位置。这意味着您可以修改函数中切片的元素。你是什​​么 不能做的是用新切片重新分配这个值,因为内部指针指向不同的地方。 你需要指针。示例(Play):

    func modify(s *[]int) {
        for i:=0; i < 10; i++ {
            *s = append(*s, i)
        }
    }
    
    func main() {
        s := []int{1,2,3}
        modify(&s)
        fmt.Println(s)
    }
    

    问题2:同步goroutine

    要等待已启动的goroutines,您可以使用sync.WaitGroup。示例(Play):

    func modify(wg *sync.WaitGroup, s *[]int) {
        defer wg.Done()
        for i:=0; i < 10; i++ {
            *s = append(*s, i)
        }
    }
    
    func main() {
        wg := &sync.WaitGroup{}
        s := []int{1,2,3}
    
        wg.Add(1)
        go modify(wg, &s)
    
        wg.Wait()
        fmt.Println(s)
    }
    

    上面的示例等待(使用wg.Wait()modify完成 (modify完成后调用wg.Done()。如果您删除wg.Wait()来电,则会 看看为什么不同步是一个问题。产出比较:

    • 使用wg.Wait()[1 2 3 0 1 2 3 4 5 6 7 8 9]
    • 没有wg.Wait()[1 2 3]

    主要goroutine早于modify goroutine返回,这就是为什么你永远不会 看到修改后的结果。因此,同步是绝对必要的

    传递新切片的好方法是使用频道。你不需要 使用指针,你会有同步。示例(Play):

    func modify(res chan []int) {
        s := []int{}
        for i:=0; i < 10; i++ {
            s = append(s, i)
        }
        res <- s
    }
    
    func main() {
        c := make(chan []int)
        go modify(c)
    
        s := <-c
        fmt.Println(s)
    }