Go为什么要写封闭频道?
虽然可以使用这个value, ok := <-channel成语从频道中读取,因此可以测试ok结果是否可以打开一个封闭的频道:
// reading from closed channel
package main
import "fmt"
func main() {
ch := make(chan int, 1)
ch <- 2
close(ch)
read(ch)
read(ch)
read(ch)
}
func read(ch <-chan int) {
i,ok := <- ch
if !ok {
fmt.Printf("channel is closed\n")
return
}
fmt.Printf("read %d from channel\n", i)
}
Run Code Online (Sandbox Code Playgroud)
输出:
read 2 from channel
channel is closed
channel is closed
Run Code Online (Sandbox Code Playgroud)
在Playground上运行"从封闭频道阅读"
写入可能关闭的频道更复杂,因为如果您只是在频道关闭时尝试写,Go会感到恐慌:
//writing to closed channel
package main
import (
"fmt"
) …Run Code Online (Sandbox Code Playgroud) 我总是读到"goto"的可怕之处.但今天,阅读有关谷歌编程语言Go的消息,我看到它支持Coroutines(Goroutines).
问题是:
Coroutine == GoTo
Run Code Online (Sandbox Code Playgroud)
要么
Coroutine != GoTo?
Run Code Online (Sandbox Code Playgroud)
为什么?
我正在学习Go现在正在使用,我的第一个项目之一就是一个简单的ping脚本.基本上我想ping一堆网址,并在每个网站的响应中等待XXX秒,然后再次ping.这是删节代码:
func main() {
// read our text file of urls
f, err := ioutil.ReadFile(urlFile)
if err != nil {
log.Print(err)
}
urlStrings := []string{}
urlStrings = strings.Split(string(f), "\n")
for _, v := range urlStrings {
go ping(v)
}
// output logs to the terminal
// channel is global
for i := range c {
fmt.Println(i)
}
}
func ping(url string) {
// for our lag timer
start := time.Now()
// make our request
_, err := http.Get(url)
if err …Run Code Online (Sandbox Code Playgroud) 考虑这个功能:
func doAllWork() error {
var wg sync.WaitGroup
wg.Add(3)
for i := 0; i < 2; i++ {
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
result, err := work(j)
if err != nil {
// can't use `return err` here
// what sould I put instead ?
os.Exit(0)
}
}
}()
}
wg.Wait()
return nil
}
Run Code Online (Sandbox Code Playgroud)
在每个goroutine中,该函数work()被调用10次.如果一个调用work()在任何正在运行的goroutine中返回错误,我希望所有goroutine立即停止,并退出程序.可以os.Exit()在这里使用吗?我该怎么处理?
编辑:这个问题不同于如何停止goroutine,因为我需要关闭所有goroutine如果一个错误发生
我在golang做ut的时候,有时候需要在goroutine里面测试一下结果,我是用time.Sleep来测试的,不知道有没有更好的测试方式。
假设我有一个这样的示例代码
func Hello() {
go func() {
// do something and store the result for example in db
}()
// do something
}
Run Code Online (Sandbox Code Playgroud)
然后当我测试 func 时,我想在 goroutine 中测试这两个结果,我这样做:
func TestHello(t *testing.T) {
Hello()
time.Sleep(time.Second) // sleep for a while so that goroutine can finish
// test the result of goroutine
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来测试这个?
基本上,在真正的逻辑中,我不在乎 goroutine 中的结果,我不需要等待它完成。但在测试中,我想在完成后检查。
正如我们所知道- core.async 采用 CSP,类似于够程从去浪.现在对于像select和alt 这样的场景来说,这很有道理.
大卫·诺伦在这里做了一个惊人的演示,在Clojure中展示了Clojure中的core.async.
然而,我可以通过简单的for循环复制类似的功能.你可以在这里看到一个演示.
function animationLoop() {
for (var i =0;i<100;i++) {
for (var j= 0; j<100;j++) {
//decision to animate or hold off
var decisionRange = randomInt(0,10);
if (decisionRange < 1) {
var cell = document.getElementById('cell-' + i + j);
cell.innerHTML = randomInt(0,9);
cell.setAttribute('class','group' + randomInt(0,5));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是在'10,000进程动画场景'中core.async的实际好处是什么?
据我所知,如果他们太忙,goroutines会阻止其他goroutines运行.对我来说,这意味着我的应用程序的性能和响应性可能取决于我知道哪些库方法将控制其他goroutine(例如通常是Read()和Write())
有什么方法我可以确切地知道不同的库方法将如何控制其他goroutine,即实际上没有阻止?
有没有办法可以实现一个调用第三方代码的新方法(包括依赖于waitforsingleobject或waitformultipleobjects的异步Win32 API,如findnextchangenotification),并且对Go调度程序表现"不错"?在这个特定的例子中,系统调用将在完成后发出信号,我需要等到它完成后不会耗尽所有其他goroutine.
是否还有另一个"最佳实践",如何处理Go中的第三方阻止操作,以便它们不会耗尽其他goroutines?
我假设Go运行时可能在后台线程上内部运行某种IO循环,以便"暂停"阻止goroutine操作,直到它们完成IO.如果情况确实如此,那么我认为能够在此基础上进行新的阻塞操作可能是有用的.
我想知道解决这个问题的惯用方法(目前抛出死锁错误),递归分支未知次数,所以我不能简单地关闭通道.
http://play.golang.org/p/avLf_sQJj_
我通过将指针传递给一个数字并递增它来使它工作,我已经研究过使用同步等待组.我没有感觉(我可能错了),我想出了一个优雅的解决方案.我见过的Go示例往往简单,聪明,简洁.
这是Tour of Go的最后一个练习,https://tour.golang.org/#73
你知道'Go程序员怎么会'管理这个?任何帮助,将不胜感激.我想从一开始就学好.
首先,我将描述我的情况.我必须从我的应用程序对多个API执行HTTPS请求,它们应该同时运行.我想知道我是否应该每个goroutine使用一个单独的HTTP客户端,或者我可以在所有goroutine中共享一个客户端.当然我想享受HTTP客户端提供的连接重用/池化,但我担心它是线程(又名goroutine)-safe,如果客户端将同时运行请求或者它们实际上将被排序?
已经厌倦了这个人为的例子:
package main
import "fmt"
func printElo() {
fmt.Printf("Elo\n")
}
func printHello() {
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
go printElo()
go printHello()
i++
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序的输出只是"这将打印".输出goroutine printElo()并且printHello不会被发出因为,我猜,main()函数线程将在goroutines甚至有机会开始执行之前完成.
在Golang中使类似代码工作而不是过早终止的惯用方法是什么?