dsnhalq37505 2013-11-06 17:36
浏览 16
已采纳

切片从通道追加

I want to create slice and add values returned from channel. Below is the code I tried but could not able to solve it.

I have to send address of the slice, but I am not able to figure out how :(

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条回答 默认 最新

  • drz49609 2013-11-06 18:10
    关注

    Your code won't work for two (in fact three) reasons:

    1. append returns a new slice as soon as the capacity is reached. Thus, the assignment in appendInt will do nothing.

    2. appendInt runs concurrently, therefore:

      • As long as appendInt does not message main that it is finished, main does not know when the intSlice has all the values you want.
      • You have to wait for all goroutines to return at the end of main

    Problem 1: Modifying slices in functions

    You may know that in Go every value you pass to a function is copied. Reference values, such as slices, are copied too, but have pointers internally which then point to the original memory location. That means you can modify the elements of a slice in a function. What you can't do is reassigning this value with a new slice as the internal pointer would point to somewhere different. You need pointers for that. Example (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)
    }
    

    Problem 2: Synchronizing goroutines

    To wait for started goroutines, you can use a sync.WaitGroup. Example (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)
    }
    

    The example above waits (using wg.Wait()) for modify to finish (modify calls wg.Done() when finished). If you remove the wg.Wait() call, you will see why not synchronizing is a problem. Comparison of outputs:

    • With wg.Wait(): [1 2 3 0 1 2 3 4 5 6 7 8 9]
    • Without wg.Wait(): [1 2 3]

    The main goroutine returns earlier than the modify goroutine which is why you will never see the modified results. Therefore synchronizing is absolutely necessary.

    A good way to communicate the new slice would be to use a channel. You would not need to use pointers and you would have synchronization. Example (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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请问为什么我配置IPsec后PC1 ping不通 PC2,抓包出来数据包也并没有被加密
  • ¥200 求博主教我搞定neo4j简易问答系统,有偿
  • ¥15 nginx的使用与作用
  • ¥100 关于#VijeoCitect#的问题,如何解决?(标签-ar|关键词-数据类型)
  • ¥15 一个矿井排水监控系统的plc梯形图,求各程序段都是什么意思
  • ¥50 安卓10如何在没有root权限的情况下设置开机自动启动指定app?
  • ¥15 ats2837 spi2从机的代码
  • ¥200 wsl2 vllm qwen1.5部署问题
  • ¥100 有偿求数字经济对经贸的影响机制的一个数学模型,弄不出来已经快要碎掉了
  • ¥15 数学建模数学建模需要