我想创建切片并添加从通道返回的值。 下面是我尝试但无法解决的代码。
我必须发送切片的地址,但我无法弄清楚如何:(
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)
}
答案 0 :(得分:10)
您的代码不适用于两个(实际上是三个)原因:
append
会在达到容量后立即返回新切片。
因此,appendInt
中的作业将不执行任何操作。
appendInt
同时运行,因此:
appendInt
没有告知main
它已完成,
main
无法知道intSlice
何时拥有您想要的所有值。main
您可能知道在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)
}
要等待已启动的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)
}