我是Go的新手.假设我有一台服务器正在侦听HTTP请求,同时我需要检查Redis通知,以便我可以更新数据.以下是一个例子:
func checkExpire() {
for {
switch msg := pubSubConn.Receive().(type) {
case redis.Message:
...
}
}
server.ListenAndServe()
Run Code Online (Sandbox Code Playgroud)
简单地将checkExpiregoroutine 放入一个好的解决方案吗?
go func() {
for {
switch msg := pubSubConn.Receive().(type) {
case redis.Message:
...
}
}()
Run Code Online (Sandbox Code Playgroud) func getRecords(ctx context.Context, ids *[]Id) error {
ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
defer cancel()
var wg sync.WaitGroup
size := len(*ids)
allErrors := make(chan error, size)
for i := 0; i < size; i++ {
wg.Add(1)
go func(x int){
err := //call to other func which return error type. nil or error
if err != nil { // I will be creating n goroutines. How to exit rightaway if one of
// them return error
allErrors <- err
}
wg.Done()
}(i) …Run Code Online (Sandbox Code Playgroud) 我尝试了Go Tour 练习#71
如果它运行go run 71_hang.go ok,它工作正常.
但是,如果您使用go run 71_hang.go nogood,它将永远运行.
唯一的区别是额外fmt.Print("")的default的select语句.
我不确定,但我怀疑某种无限循环和竞争条件?这是我的解决方案.
注意:Go并没有死锁 throw: all goroutines are asleep - deadlock!
package main
import (
"fmt"
"os"
)
type Fetcher interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (body string, urls []string, err error)
}
func crawl(todo Todo, fetcher Fetcher,
todoList chan Todo, done chan bool) { …Run Code Online (Sandbox Code Playgroud) 假设我有一堆 goroutine 的堆栈跟踪,例如:
goroutine 5633 [select]:
net/http.(*persistConn).writeLoop(0xc21303ac00)
/usr/lib/go/src/pkg/net/http/transport.go:791 +0x271
created by net/http.(*Transport).dialConn
/usr/lib/go/src/pkg/net/http/transport.go:529 +0x61e
Run Code Online (Sandbox Code Playgroud)
在我的例子中,一个独特的特定于应用程序的对象由一组 goroutine 提供服务,我想查看与特定对象相关的 goroutine 的堆栈跟踪。我有数百个特定于应用程序的对象,所以我得到了数百个相同的 goroutine。
我将如何将我的日志与堆栈跟踪中的 goroutine 相关联?似乎没有一种方法可以在堆栈跟踪中识别当前 goroutine,也无法命名 goroutine,因此我可以在堆栈跟踪中看到特定值。
聚苯乙烯
我已经在 Go 邮件列表上阅读了相关的为什么你想要做的帖子,所以我正在寻找替代方案/黑客/解决方法(希望不涉及用日志散布代码每隔一行调用一次)。
我不知道为什么我们需要运行wg.Wait()在goroutine
// This one works as expected...
func main() {
var wg sync.WaitGroup
for i:=0; i<5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
}()
time.Sleep(time.Second)
}
go func() {
wg.Wait()
}()
}
Run Code Online (Sandbox Code Playgroud)
但这个永远不会结束永远等待
func main() {
var wg sync.WaitGroup
for i:=0; i<5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
}()
time.Sleep(time.Second)
}
wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)
谁能解释为什么我需要在另一个 goroutine 中等待?
谢谢!
想象一下以下代码:
func waitForOneOfTwoProcesses() {
c := make(chan bool)
go func() {
time.Sleep(1 * time.Second)
c<-true
}()
go func() {
time.Sleep(2 * time.Second)
c<-true
}()
<-c
}
Run Code Online (Sandbox Code Playgroud)
这是否泄漏了一个频道和goroutine,或者Go认识到它c已经消失并且goroutine可以退出?
如果通道的缓冲区大小为2,答案是否会有所不同?
并发性是编程的一部分.最近的时间goroutine非常受欢迎.我的问题是 - 其他语言中存在哪种类似的goroutine类似物?
假设我有这个:
go func() {
for range time.Tick(1 * time.Millisecond) {
a, b = b, a
}
}()
Run Code Online (Sandbox Code Playgroud)
其他地方:
i := a // <-- Is this safe?
Run Code Online (Sandbox Code Playgroud)
对于这个问题,i与原始a或者相关的价值是不重要的b.唯一的问题是阅读a是否安全.也就是说,是否有可能a被nil部分分配,无效,未定义,......除了有效值之外的任何东西?
我试图让它失败,但到目前为止它总是成功(在我的Mac上).
在Go Go Memory Model文档中,我无法找到超出此引用的任何特定内容:
大于单个机器字的值的读取和写入表现为以未指定的顺序进行的多个机器字大小的操作.
这是否意味着单个机器字写入实际上是原子的?并且,如果是这样,函数指针写入Go单个机器字操作?
更新:这是一个正确同步的解决方案
我有一片 30'000 根弦。如何将这个切片分成 10 个 goroutine 进行处理,这些协程将从切片中获取 3000 个字符串,从中提取一些数据并推送到一个新切片中?
所以,最后,我将有 10 个切片,每个切片有 3000 个处理结果。处理这个问题的模式是什么?
我已经看过这篇文章,但不确定这些模式中的哪一种适用于我的情况。
我试图在 Go 的背景下更好地理解抢占式和协作式的定义。维基百科关于抢占式多任务处理的说明
在计算中,抢占是暂时中断正在执行的任务的行为,以便稍后恢复它。该中断由外部调度程序完成,无需任务的协助或配合。
维基百科指出“外部调度程序”。我想这意味着调度程序更加具体,因为据我所知,调度程序只负责选择队列中的下一个进程。
Go 通常被称为部分抢占式,因为同步点/抢占点仅位于函数调用处,而不位于任何给定指令处。这就说得通了。但正如 wiki 定义所述,抢占是由外部调度程序完成的。
但是,不是每个进程或任务都是抢占式的,因为 CPU 可以在任何进程执行中停止执行,以便切换到另一个进程吗?任何澄清表示赞赏!
我能想到的唯一解释是我们谈论不同的抢占级别。一种用于进程,一种用于内核/用户线程。在这种情况下,CPU 调度程序选择下一个进程,但 Go 调度程序负责 goroutine/线程。
go ×10
goroutine ×10
channel ×3
concurrency ×2
preemption ×1
scheduler ×1
select ×1
sync ×1
worker ×1