我有一个非常简单的脚本,它发出一个获取请求,然后对响应执行一些操作。我有两个版本,第一个版本使用 goroutine,另一个版本没有,我对这两个版本进行了基准测试,速度没有差异。这是我正在做的事情的一个简单版本:
普通版:
func main() {
url := "http://finance.yahoo.com/q?s=aapl"
for i := 0; i < 250; i++ {
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
}
fmt.Println(resp.Status)
}
}
Run Code Online (Sandbox Code Playgroud)
日常安排:
func main() {
url := "http://finance.yahoo.com/q?s=aapl"
for i := 0; i < 250; i++ {
wg.Add(1)
go run(url, &wg)
wg.Wait()
}
}
func run(url string, wg *sync.WaitGroup) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
}
fmt.Println(resp.Status)
}
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,当我使用 go 例程时,程序的执行时间会更长。为了有效地理解并发性,我缺少什么概念?
参考此示例,我想在作业初始化和终止之间添加预定义的延迟。我已将数据(即 jobid 和 waittime)存储在地图中。然后我将整个映射复制到与映射相同结构类型的通道中。但我无法在 go 例程调用中获取地图值。请帮助我,我是 Go 新手。
package main
import "fmt"
type Vertex struct {
id, waitime int
}
var m = map[int]Vertex{
1: {1, 1000},
2: {2, 2000},
3: {3, 1000},
4: {4, 2000},
5: {5, 1000},
6: {6, 2000},
7: {7, 1000},
8: {8, 2000},
9: {9, 1000},
10: {10, 2000},
}
func worker(w int, jobs <-chan Vertex, results chan<- int) {
for j := 1; j <= len(m); j++ {
a, b := <-jobs.id, …Run Code Online (Sandbox Code Playgroud) 为什么不将go sum(s[len(s)/2:], c)(第二个)返回的最后一个结果分配给x?这两个<-c让我很困惑。此代码来自A Tour of Go - [Channels]。
package main
import "fmt"
func sum(s []int, c chan int) { // int is the return value type
sum := 0
for _, v := range s {
sum += v
}
c <- sum // Sends sum to c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y …Run Code Online (Sandbox Code Playgroud) 我正在 8 个不同的 goroutine 上运行一个 cpu 密集型脚本。每个 goroutine 都至少需要几分钟才能完成,我想知道这样的事情是否可能:
for i := 0; i < len(input); i += 1 {
wait_for_number_of_processes_running_to_be_less_than_8
go calc_math_and_things(input[i])
}
Run Code Online (Sandbox Code Playgroud) 当尝试将此结构与多个 goroutine 一起使用时,有时我会收到以下错误之一:
fatal error: concurrent map read and map write
或者
concurrent map writes
读完这篇文章后后,我确保在构造函数中返回一个引用,并将引用传递给接收者。
使用此功能的完整代码位于此 github 存储库中
type concurrentStorage struct {
sync.Mutex
domain string
urls map[url.URL]bool
}
func newConcurrentStorage(d string) *concurrentStorage{
return &concurrentStorage{
domain: d,
urls: map[url.URL]bool{},
}
}
func (c *concurrentStorage) add(u url.URL) (bool) {
c.Lock()
defer c.Unlock()
if _, ok := c.urls[u]; ok{
return false
}
c.urls[u] = true
return true
}
Run Code Online (Sandbox Code Playgroud) 在构建自定义服务器应用程序时,最好有一个关闭机制,以确保所有正在运行的进程在服务器关闭之前停止,这也将有助于更好的内存管理。
我们如何利用 Golang 及其力量来构建这样的机制?Golang 中已经有一个 ,shutdown函数可用,我的目的是让开发人员跳出框框思考并创建多种方法来执行相同的操作。这将有助于让我们的golang社区变得更好、更强。下面我分享一下我的一个答案,希望大家多提建议和解答。
我正在尝试了解 golang频道和同步。当我运行我的程序与竞争检测器,它导致了比赛的检测。
func main() {
ch := make(chan int)
done := make(chan struct{})
wg := sync.WaitGroup{}
go func() {
defer close(ch)
defer close(done)
wg.Wait()
done <- struct{}{}
}()
for i := 0; i < 5; i++ {
x := i
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Value: ", x)
ch <- x
}()
}
loop:
for {
select {
case i := <-ch:
fmt.Println("Value: ", i)
case <- done:
break loop
}
} …Run Code Online (Sandbox Code Playgroud) 我正在阅读 The Go Programming Language 一书,书中有一个例子说明了 goroutine 泄漏
func mirroredQuery() string {
responses := make(chan string, 3)
go func() { responses <- request("asia.gopl.io") }()
go func() { responses <- request("europe.gopl.io") }()
go func() { responses <- request("americas.gopl.io") }()
return <-responses // return the quickest response
}
func request(hostname string) (response string) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
我试图解决泄漏,并得到以下代码
func request(url string) string {
res, err := http.Get(url)
if err == nil {
body, err := io.ReadAll(res.Body)
if err == nil { …Run Code Online (Sandbox Code Playgroud) 我已经看过这个,这个,这个和这个,但在这种情况下没有一个真正帮助我。如果通道中的值是针对该特定 goroutine 的,我有多个 goroutine 需要执行某些任务。
var uuidChan chan string
func handleEntity(entityUuid string) {
go func() {
for {
select {
case uuid := <-uuidChan:
if uuid == entityUuid {
// logic
println(uuid)
return
}
case <-time.After(time.Second * 5):
println("Timeout")
return
}
}
}()
}
func main() {
uuidChan = make(chan (string))
for i := 0; i < 5; i++ {
handleEntity(fmt.Sprintf("%d", i))
}
for i := 0; i < 4; i++ { …Run Code Online (Sandbox Code Playgroud) 继此答案之后,如果一个 goroutine 在两个通道上进行选择,是否可以保证以与发送通道相同的顺序选择通道?我对发件人是单线程的情况特别感兴趣。
例如,是否保证此代码始终产生相同的输出:
package main
import (
"fmt"
"time"
)
var x, y chan int
func worker() {
for {
select {
case v := <- x:
fmt.Println(v)
case v := <- y:
fmt.Println(v)
}
}
}
func main() {
x = make(chan int)
y = make(chan int)
go worker()
x <- 1
y <- 2
<- time.After(1 * time.Second)
}
Run Code Online (Sandbox Code Playgroud)
我的实验似乎表明,这对于无缓冲通道是有保证的,如图所示,但对于缓冲通道则不能保证。有人可以确认吗?