Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 为什么我需要用一个新的子程序运行Walk?_Go - Fatal编程技术网

Go 为什么我需要用一个新的子程序运行Walk?

Go 为什么我需要用一个新的子程序运行Walk?,go,Go,我在写一个基本上按顺序遍历树的。我的作品: package main import ( "fmt" "code.google.com/p/go-tour/tree" ) // Walk walks the tree t sending all values // from the tree to the channel ch. func Walk__helper(t *tree.Tree, ch chan int) { if (t == nil) {

我在写一个基本上按顺序遍历树的。我的作品:

package main

import (
    "fmt"
    "code.google.com/p/go-tour/tree"
)

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk__helper(t *tree.Tree, ch chan int) {
    if (t == nil) {
        return
    }

    Walk__helper(t.Left, ch)
    ch <- t.Value
    Walk__helper(t.Right, ch)
}

func Walk(t *tree.Tree, ch chan int) {
    Walk__helper(t, ch)
    close(ch)
}

func main() {
    ch := make(chan int)
    go Walk(tree.New(1), ch)
    for v := range ch {
        fmt.Println(v)   
    }
}
主程序包
进口(
“fmt”
“code.google.com/p/go-tour/tree”
)
//Walk在树上行走,并发送所有值
//从树到通道ch。
func Walk__辅助对象(t*tree.tree,ch chan int){
如果(t==nil){
返回
}
步行助手(t.左,ch)

ch这里的关键点是与通道耦合时的
范围

当您通过一个通道(在本例中为
ch
)进行
range
时,它将在循环之前等待在通道上发送项目。这是一个安全的“阻塞”操作,在等待通道接收项目时不会死锁

不使用goroutine时会发生死锁,因为您的通道没有缓冲。如果不使用goroutine,则方法调用是同步的,
Walk
在通道上放置某个内容。它会阻塞,直到弹出。它永远不会弹出。因为方法调用是同步的

我的印象是go关键字基本上会产生一个新的线程


…这是不正确的。需要了解更多重要的实现细节。您应该将goroutine的思维过程与线程分离。只需将goroutine视为一段并发执行的代码,而不使用“线程”.

这里的关键点是与通道耦合时的
范围

当您通过一个通道(在本例中为
ch
)进行
range
时,它将在循环之前等待在通道上发送项目。这是一个安全的“阻塞”操作,在等待通道接收项目时不会死锁

不使用goroutine时会发生死锁,因为您的通道没有缓冲。如果不使用goroutine,则方法调用是同步的,
Walk
在通道上放置某个内容。它会阻塞,直到弹出。它永远不会弹出。因为方法调用是同步的

我的印象是go关键字基本上会产生一个新的线程


…这是不正确的。需要了解更多重要的实现细节。您应该将goroutine的思维过程与线程分离。只需将goroutine视为一段并发执行的代码,而不使用“线程”.

哦,谢谢。关于线程与goroutine的区别,我想你是指同步(互斥体、信号量)基本上可以用通道缓冲区实现?它们完全不同。Goroutines是一个位于线程之上的抽象。Go运行时对Goroutines进行切片,就像操作系统对线程进行切片一样。但是这样做要便宜得多。它可以在单个线程上对多个goroutine进行切片。如果goroutine可以被抢占到正在阻止一个线程。运行时将生成一个新线程,并在另一个线程被阻止时将goroutines时间切片到另一个线程。这是它的基本运行情况。不过,还有更多。在较低的级别上,goroutines与OS线程的一些关键区别:goroutines启动时有一个小堆栈,稍后可以扩展,因此启动一个goroutines不需要太多时间ime或RAM;Go的
net
package、channels等,当某些阻塞操作发生时,使goroutine屈服于Go的用户模式调度器;当屈服于此时,用户模式调度器可以将控制权传递给另一个goroutine,而无需花费大量的内核空间。在某些方面,它们就像Windows世界所称的“光纤”@我不知道“光纤”这个术语。我不知道从用户模式到内核模式的转换有一个官方术语。谢谢你的信息!)哦,谢谢。关于线程与goroutine的区别,我想你是指同步(互斥体、信号量)基本上可以用通道缓冲区实现?它们完全不同。Goroutines是一个位于线程之上的抽象。Go运行时对Goroutines进行切片,就像操作系统对线程进行切片一样。但是这样做要便宜得多。它可以在单个线程上对多个goroutine进行切片。如果goroutine可以被抢占到正在阻止一个线程。运行时将生成一个新线程,并在另一个线程被阻止时将goroutines时间切片到另一个线程。这是它的基本运行情况。不过,还有更多。在较低的级别上,goroutines与OS线程的一些关键区别:goroutines启动时有一个小堆栈,稍后可以扩展,因此启动一个goroutines不需要太多时间ime或RAM;Go的
net
package、channels等,当某些阻塞操作发生时,使goroutine屈服于Go的用户模式调度器;当屈服于此时,用户模式调度器可以将控制权传递给另一个goroutine,而无需花费大量的内核空间。在某些方面,它们就像Windows世界所称的“光纤”@我不知道“光纤”这个术语。我不知道从用户模式到内核模式的转换有一个官方术语。谢谢你的信息!:)