使用Go的context包,可以使用特定于请求的数据传递给请求处理函数堆栈
func WithValue(parent Context, key, val interface{}) Context
Run Code Online (Sandbox Code Playgroud)
这将创建一个new Context,它是parent的副本,并包含可以使用key访问的值val.
如果我想在一个Context?中存储几个键值对,我该如何继续?我应该WithValue()多次拨打电话,每次Context从我上次拨打的电话都收到通话WithValue()?这看起来很麻烦.
或者我应该使用一个结构并将所有数据放在那里,我需要只传递一个值(结构),从中可以访问所有其他值?
或者有没有办法将几个键值对传递给WithValue()?
我的程序中有多个goroutine,每个都在fmt.Println没有任何显式同步的情况下进行调用.这是安全的(即,每条线路是否单独出现而没有数据损坏),或者我是否需要创建另一个带有同步的goroutine来专门处理打印?
Go的口号之一是不要通过共享记忆来沟通; 相反,通过沟通分享记忆.
我想知道Go是否允许在同一台机器上运行的两个不同的Go-compiled二进制文件相互通信(即客户端 - 服务器),以及与C++中的boost :: interprocess相比有多快?到目前为止,我看到的所有例子都只说明了相同程序例程之间的通信.
一个简单的Go示例(具有单独的客户端和服务器代码)将非常感谢!
我是新手,我正在尝试创建一个简单的聊天服务器,客户端可以向所有连接的客户端广播消息.
在我的服务器中,我有一个goroutine(无限循环)接受连接,所有连接都由一个通道接收.
go func() {
for {
conn, _ := listener.Accept()
ch <- conn
}
}()
Run Code Online (Sandbox Code Playgroud)
然后,我为每个连接的客户端启动一个处理程序(goroutine).在处理程序内部,我尝试通过迭代通道来广播所有连接.
for c := range ch {
conn.Write(msg)
}
Run Code Online (Sandbox Code Playgroud)
但是,我不能播放因为(我认为从阅读文档)通道需要在迭代之前关闭.我不确定何时应关闭频道,因为我想继续接受新的连接,关闭频道不会让我这样做.如果有人可以帮助我,或提供更好的方式向所有连接的客户广播消息,我们将不胜感激.
我想知道这个着名的引言最真实的解释是什么:
不要通过共享内存进行通信; 通过沟通分享记忆.(R. Pike)
在Go Go Memory Model中,我可以读到:
通道上的发送在该通道的相应接收完成之前发生.(Golang Spec)
还有一篇专门的golang文章解释了这句话.而关键的贡献也是Andrew G.的一个实例.
好.有时太多谈论....我从Memory Spec报价中得出,并且通过查看工作示例:
在goroutine1通过通道向goroutine2发送(任何内容)后,goroutine1完成的所有更改(内存中的任何位置)必须在通过相同通道接收到goroutine2后才可见.(Golang Lemma by Me :)
因此,我得出了着名引言的脚踏实地的解释:
要同步两个goroutine之间的内存访问,您不需要通过通道发送该内存.足够好的是从频道接收(甚至没有).您将看到goroutine发送(到频道)时发送的任何更改(在任何地方).(当然,假设没有其他goroutine写入相同的内存.)更新(2)8-26-2017
我实际上有两个问题:
1)我的结论是否正确?
2)我的解释有帮助吗?
更新(1) 我假设没有缓冲的频道.让我们首先限制自己,避免用太多的未知数来改造自己.
请注意,我们还要关注两个goroutine的简单用法,这两个goroutines通过单个通道和相关的记忆效应进行通信而不是最佳实践 - 这超出了本问题的范围.
为了更好地理解我的问题的范围,假设goroutine可以访问任何类型的内存结构 - 不仅是原始的 - 并且它可以是一个大的,它可以是字符串,映射,数组,等等.
请使用以下代码段:
func main() {
ch := make(chan int)
quit := make(chan int)
go func() {
for {
ch <- querySomePeriodicThing()
}
}()
// ...
loop:
for {
select {
case <-ch: handlePeriodicThing()
case <-quit: break loop
}
}
}
Run Code Online (Sandbox Code Playgroud)
goroutine应该在执行期间运行.当select语句从退出通道接收到某些内容时,它会跳出循环并且程序结束,而不会尝试停止goroutine.
我的问题:这会产生一次或两次不明显的间歇性不良反应吗?我知道在其他语言中,线程应该在程序结束之前清理(即退出),但是会有所不同吗?假设querySomePeriodicThing()不会打开文件描述符或套接字或任何不好的东西.
虽然SayHello()按预期执行,但goroutine没有打印任何内容.
package main
import "fmt"
func SayHello() {
for i := 0; i < 10 ; i++ {
fmt.Print(i, " ")
}
}
func main() {
SayHello()
go SayHello()
}
Run Code Online (Sandbox Code Playgroud) 是否有任何API让maingoroutine永远睡觉?
换句话说,我希望我的项目总是运行,除非我停止它.
我有一个包含要完成的工作的切片,以及在完成所有操作时将包含结果的切片.以下是我的一般过程的草图:
var results = make([]Result, len(jobs))
wg := sync.WaitGroup{}
for i, job := range jobs {
wg.Add(1)
go func(i int, j job) {
defer wg.Done()
var r Result = doWork(j)
results[i] = r
}(i, job)
}
wg.Wait()
// Use results
Run Code Online (Sandbox Code Playgroud)
它似乎工作,但我没有彻底测试,我不确定它是否安全.一般来说,让多个goroutine写入任何内容都不会让我感觉良好,但在这种情况下,每个goroutine都限制在切片中自己的索引,这是预先分配的.
我想替代方案是通过渠道收集结果,但由于结果顺序很重要,这似乎相当简单.以这种方式写入切片元素是否安全?
我最近很高兴看到关于Go Concurrency模式的Google IO谈话
虽然Go的并发方法(灌浆,通道上的通信)明显不同于Clojure(不变性,管理参考,STM),但似乎Go方法在Clojure上下文中的某些情况下仍然有用.
因此,在Clojure或Java中可以直接使用Go的并发原语(可能是库),特别是:
channel类似的对象阻塞,直到两端都有读写器select样构造,可以等待在多个通道的结果PS非常满意Java解决方案,因为它很容易从Clojure中使用
更新自问题最初被问到以来,Clojure现在拥有core.async,它提供了所有这些功能和更多功能.