假设我有一个 go 接收通道。有没有一种方法可以让我同时收听所有内容?例如:
channels := make([]<-chan int, 0, N)
// fill the slice with channels
for _, channel := range channels {
<-channel
}
Run Code Online (Sandbox Code Playgroud)
这是我能做到的最接近的事情。但是,此实现取决于切片元素的顺序。
为了清楚起见,我不需要知道 go 通道的值。我只需要知道他们都完成了。
我想利用 golang 中的上下文在超时时用于取消。
代码:
package main
import "fmt"
import "time"
import "context"
func F(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx,3*time.Second)
defer cancel()
for i:=0;i<10;i++ {
time.Sleep(1 * time.Second)
fmt.Println("No: ",i)
}
select {
case <-ctx.Done():
fmt.Println("TIME OUT")
cancel()
return ctx.Err()
default:
fmt.Println("ALL DONE")
return nil
}
}
func main() {
ctx := context.Background()
err := F(ctx)
if err != nil {
fmt.Println(err)
}else {
fmt.Println("Success")
}
}
Run Code Online (Sandbox Code Playgroud)
期望:上面的代码应该在 counter 处停止运行循环2,因为超时为 3 秒,循环每次运行 1 秒。所以我期待这样的事情:
No: 0
No: …Run Code Online (Sandbox Code Playgroud) 在大多数示例中,SetReadDeadline在调用 之前调用net.Conn.Read()。
在我的程序中,为了中断我的net.Conn.Read(),我调用net.Conn.SetReadDeadline(time.Now())另一个线程/例程。这是正确的方法吗?
谢谢。
尝试了解 go 上下文取消如何中止后续代码的执行
实验详情:
2secsum在单独的 go-routine 中调用另一个 func - 它为1sectest-run-1 和4sectest-run-2休眠3sec让 spin go 例程完成执行package main
import (
"context"
"fmt"
"log"
"time"
)
func main() {
c := context.Background()
childCtx, cancel := context.WithTimeout(c, 2*time.Second)
defer cancel()
ch := make(chan int, 1)
go sum(5, 6, ch)
var msg string
select {
case <-childCtx.Done():
msg = "return from ctx done channel"
case res := <-ch:
msg = …Run Code Online (Sandbox Code Playgroud) 假设我有一个像这样的切片:
stu = [{"id":"001","name":"A"} {"id":"002", "name":"B"}]也许还有更多这样的元素。切片内部是一个长字符串,我想使用 json.unmarshal 来解析它。
type Student struct {
Id string `json:"id"`
Name string `json:"name"`
}
studentList := make([]Student,len(stu))
for i, st := range stu {
go func(st string){
studentList[i], err = getList(st)
if err != nil {
return ... //just example
}
}(st)
}
//and a function like this
func getList(stu string)(res Student, error){
var student Student
err := json.Unmarshal(([]byte)(stu), &student)
if err != nil {
return
}
return &student,nil
}
Run Code Online (Sandbox Code Playgroud)
我得到了 nil 结果,所以我想说 goroutine …
我有以下代码作为测试的一部分:
expected := 10
var wg sync.WaitGroup
for i := 0; i < expected; i++ {
go func(wg *sync.WaitGroup) {
wg.Add(1)
defer wg.Done()
// do something
}(&wg)
}
wg.Wait()
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,我panic: Fail in goroutine after TestReadWrite has completed在运行“go test”时得到了。当使用“go test -race”运行时,我没有感到恐慌,但测试后来失败了。在这两种情况下,尽管有 wg.Wait(),但 goroutine 并未完成执行。
我做了以下更改,现在测试按预期工作:
expected := 10
var wg sync.WaitGroup
wg.Add(expected)
for i := 0; i < expected; i++ {
go func(wg *sync.WaitGroup) {
defer wg.Done()
// do something
}(&wg)
}
wg.Wait()
Run Code Online (Sandbox Code Playgroud)
我的疑问是:
wg.Add(1)在 goroutine 内部完成的。为什么在这种特定情况下它会表现出意外?这里发生的情况似乎是,一些 …在以下代码库中的代码中,创建了 mongodb 客户端(如下所示):
import (
"context"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
Run Code Online (Sandbox Code Playgroud)
在我们的场景中:
Goroutine 1 用于collection1读写操作:
collection1 := client.Database("testing").Collection("collectionone")
Run Code Online (Sandbox Code Playgroud)
Go-routine 2 同时使用collection1&collection2进行读写操作:
collection2 := client.Database("testing").Collection("collectiontwo")
Run Code Online (Sandbox Code Playgroud)
client在多个 go 例程中使用并发安全吗?
我在做一些条件基础上,iteratating变量够程内检查i,发现它是给我结果我没想到,我决定用一些简单的代码来确认.
for i := 1; i <= 5; i++ {
wg.Add(1)
fmt.Println(i)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
1
2
3
4
5
6
6
6
6
6
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?有人可以解释为什么6被打印5次,虽然我只迭代到5?
我正在尝试使用goroutine,似乎我无法在goroutine中修改结构的值(下面的示例).这有什么工作吗?
编辑:如果我放置一个睡眠语句,似乎代码运行,表明如果给定更多时间,goroutines将运行,但它们在main()中的所有内容都已执行后完成运行.在继续之前,我如何"等待"我的goroutines完成?
package main
import (
"fmt"
)
type num struct {
val int
}
func (d *num) cube_val() {
fmt.Println("changing value...")
d.val = d.val*d.val*d.val
}
func main() {
a := []num{num{1},num{3},num{2},num{5},num{4}}
for i := range a {
go a[i].cube_val()
}
// code that waits for go routines to finish should get inserted here ...
fmt.Println(a) // change does NOT happen
for i := range a {
a[i].cube_val()
}
fmt.Println(a) // change happens, and fmt.Println statements worked?
}
Run Code Online (Sandbox Code Playgroud) 我刚刚阅读了Go的一些简短教程,并编写了一个简单的程序筛。Sieve使用sieve算法来打印所有小于10000的质数,这会创建许多go例程。我得到了正确的结果,但是程序非常慢(在我的计算机上为5秒)。我还编写了实现相同算法的lua脚本和python脚本,并且运行速度更快(两者在我的计算机上均为1秒左右)。
请注意,这样做的目的是要了解go例程与其他语言(例如lua)中的协程相比的性能。该实现效率很低,一些评论指出,这不是实现Eratosthenes筛网的正确方法。是的,这是故意的。其他一些答复指出,速度慢是由打印I / O引起的。所以我注释了打印行。
我的问题是为什么我在Go中实现的筛分程序这么慢?这是代码:
package main
import (
"fmt"
"sync"
)
type Sieve struct {
id int;
msg_queue chan int;
wg *sync.WaitGroup;
}
func NewSieve(id int) *Sieve {
sieve := new(Sieve)
sieve.id = id
sieve.msg_queue = make(chan int)
sieve.wg = new(sync.WaitGroup)
sieve.wg.Add(1)
return sieve
}
func (sieve *Sieve) run() {
defer sieve.wg.Done()
myprime := <-sieve.msg_queue
if myprime == 0 {
return
}
// fmt.Printf("Sieve (%d) is for prime number %d.\n", sieve.id, myprime)
next_sieve := NewSieve(sieve.id + 1)
go next_sieve.run() …Run Code Online (Sandbox Code Playgroud)