当前位置: 首页 > 面试题库 >

Go Playground和我的机器上的Go之间有差异吗?

司寇善
2023-03-14
问题内容

为了解决我对goroutine的一些误解,我去了Go游乐场并运行了以下代码:

package main

import (
    "fmt"
)

func other(done chan bool) {
    done <- true
    go func() {
        for {
            fmt.Println("Here")
        }
    }()
}

func main() {
    fmt.Println("Hello, playground")
    done := make(chan bool)
    go other(done)
    <-done
    fmt.Println("Finished.")
}

如我所料,Go操场出现了一个错误: 过程花费了太长时间

这似乎暗示在其中创建的goroutine other永远运行。

但是,当我在自己的机器上运行相同的代码时,几乎立即获得以下输出:

Hello, playground.
Finished.

这似乎暗示other主goroutine完成时,其中的goroutine将退出。 这是真的?
还是主goroutine完成,而其他goroutine继续在后台运行?


问题答案:

您看到的解释:

在Go
Playground上,GOMAXPROCS是1(证明)。

这意味着一次执行一个goroutine,并且如果该goroutine没有阻塞,则不会强制调度程序切换到其他goroutine。

您的代码(像每个Go应用程序一样)以执行main()函数的goroutine(主goroutine)开始。它启动另一个执行该other()功能的goroutine
,然后从done通道接收-阻塞。因此,调度程序必须切换到另一个goroutine(执行other()功能)。

other()html" target="_blank">函数中,当您在done通道上发送值时,这将使当前(other())和maingoroutine可运行。调度选择继续运行other(),并且因为GOMAXPROCS=1main()没有继续。现在other()启动另一个执行无限循环的goroutine。调度程序选择执行此goroutine,这将永远花费到阻塞状态,因此main()不会继续。

然后,Go Playground沙箱的超时就可以解决:

过程花了太长时间

请注意, Go Memory Model
仅保证某些事件先于其他事件发生,而不能保证如何执行2个并发goroutine。这使得输出不确定。

您不要质疑任何不违反Go Memory
Model的执行顺序。如果您希望执行达到代码中的某些点(执行某些语句),则需要显式同步(您需要同步goroutine)。

另请注意,Go
Playground上的输出已缓存,因此如果再次运行该应用程序,则不会再次运行该应用程序,而是会立即显示已缓存的输出。如果您更改了代码中的任何内容(例如,插入空格或注释),然后再次运行它,它将被编译并再次运行。您会注意到响应时间增加了。使用当前版本(Go
1.6),您每次都会看到相同的输出。

在本地运行(在您的计算机上):

在本地运行它时,很有可能GOMAXPROCS会大于1默认值,因为它默认为可用的CPU核心数(从Go
1.5开始)。因此,是否有执行无穷循环的goroutine无关紧要,另一个goroutine将同时执行,即main(),当main()返回时,程序终止;它不会等待其他非main例程完成(请参见规范:程序执行)。

另请注意,即使您将设置GOMAXPROCS1,您的应用也很可能会在“很短的时间内”退出,因为调度程序的实现将切换到其他goroutine,而不仅仅是永久执行无限循环(但是,如上所述,这是不确定的)。然后,它将成为main()goroutine,因此当main()完成并返回时,您的应用程序终止。

在Go Playground上玩您的应用程序:

如前所述,默认情况下GOMAXPROCS位于1Go Playground上。但是,可以将其设置为更高的值,例如:

runtime.GOMAXPROCS(2)

没有显式同步,执行仍然是不确定的,但是您会观察到不同的执行顺序和终止,而不会发生超时:

Hello, playground
Here
Here
Here
...
<Here is printed 996 times, then:>
Finished.

在Go Playground上尝试使用此变体。



 类似资料:
  • 问题内容: 今天,我的一个好朋友问我最新的Go语言和Cython之间的主要区别是什么,后者是Python的一组C扩展。我对Python的了解不多,有人可以告诉我为什么Go比Cython更好/更差吗? 问题答案: Cython并不是传统意义上的语言。它是构建Python扩展程序的预处理器,该扩展程序采用类似Python的语法(实际上,他们力求完全兼容Python)并生成C代码(使用Python C

  • 问题内容: 很快就有两个相等运算符:double equals( )和Triple equals( ),两者之间有什么区别? 问题答案: 简而言之: 操作员检查其实例值是否相等, 操作员检查引用是否指向同一实例, 长答案: 类是引用类型,可能有多个常量和变量在幕后引用类的同一单个实例。类引用保留在运行时堆栈(RTS)中,其实例保留在内存的堆区域中。当您控制平等时, 这意味着它们的实例是否彼此相等。

  • 和操作符之间有什么区别,它们的用例是什么?他们似乎都在等待一项任务?

  • 我编写了一个简单的脚本,它接受任意数量的参数来演示< code>$@和< code>$*之间的区别: 在我做的 CLI 上 这就是打印出来的 因为它们是相同的,这是否意味着等于?还是我遗漏了一点?

  • 本文向大家介绍成本差异和进度差异之间的差异,包括了成本差异和进度差异之间的差异的使用技巧和注意事项,需要的朋友参考一下 对于任何应用程序或专门用于任何项目,最关注的因素之一是在开发前和开发后阶段的预算管理和时间管理。因此,要评估任何项目的这两个主要因素,有很多方法,其中成本差异和进度差异是两个重要且主要的方法。 顾名思义,“成本差异”基于项目开发中花费的成本,而“进度差异”则基于相同开发中花费的时

  • 我现在做了很多研究,以找出React Native项目、CRNA和世博会项目之间的确切区别和取舍。 我的主要指导是 但是,我仍然不明白,与使用本机代码的普通React本机项目相比,使用ExpoKit和本机代码有什么(不)优势,除了我不能在普通React本机项目中使用Expo API这一事实。 我知道,当我在世博会上启动一个项目时,我可以将其作为ExpoKit项目或React原生项目弹出。在这两种情