英文:
How to reply to the sender of a channel and manage state
问题
我想知道如何在Go中直接回复通道的发送者。更有趣的是如何标识发送者以供以后使用。
我正在将此与Elixir的GenServer进行比较,我可以直接回复给发送者或广播给所有人。在Go中是否缺少此功能?
在我阅读关于Go中通道的所有地方,我找不到如何做到这一点的方法。
此外,Elixir中的GenServer保持状态,因为它是一个无限运行的进程。Go是否有类似的机制来保持和传递状态?如果没有,那么如何实现这一点?
英文:
I would like to know how to reply directly to the sender of a channel in Go. More interesting is how to identify the sender for later use.
I am comparing this to Elixir GenServer where I can reply to the sender directly or broadcast to everyone. Is this feature missing in Go?
Everywhere I read about channels in Go I cannot find how to do this.
Also, GenServers in Elixir hold states becomes it is a infinite running process. Does Go have semething similar to hold and pass state? If not how is this accomplished?
答案1
得分: 2
与通道发送者通信
如前所述,通道的通道是一种直接响应通道发送者的方式。以下是一个示例:
package main
func main() {
// 通过创建一个通道的通道来创建一个通信通道
c := make(chan chan struct{})
// 使用通信通道启动一个发送者
go sender(c)
// 从发送者接收一条消息,这里的消息本身是一个通道
r := <-c
// 在发送者给我们的通道上发送响应
r <- struct{}{}
}
func sender(c chan chan struct{}) {
// 创建一个接收者将用来响应我们的通道
r := make(chan struct{})
// 将通道发送给接收者
c <- r
// 这是接收者收到消息后收到的响应
<-r
}
至于你关于识别特定发送者的第二个问题,你可以尝试使用类似 goroutinemap 的东西,它允许你管理具有名称的 goroutine 的生命周期。然而,这种模式并不常见,如果你需要识别特定的通道发送者,可能你可以(并且应该)重新设计你的解决方案。
管理应用程序状态
这完全取决于你的应用程序及其功能。根据 OP 的说法,该应用程序是一个通过 WebSockets 进行的国际象棋游戏。你可以考虑创建一个数据结构,其中包含对两个玩家 WebSocket 连接的引用,以及玩家之间的游戏状态。当游戏开始时,将创建此数据结构,然后该数据结构可以在玩家之间管理消息的传递和游戏状态的更新。可能类似于以下内容:
type GameState struct {
Player1 *websocket.Conn
Player2 *websocket.Conn
// 在这里添加所需的任何游戏状态
}
func (s *GameState) run(ctx context.Context) {
// 在这里在 WebSocket 连接之间发送消息,并相应地更新游戏状态
}
英文:
Communicating with a channel sender
As already mentioned, a channel of channels is a way to respond directly to the channel sender. Here is an example:
package main
func main() {
// Make a communication channel by creating a channel of channels
c := make(chan chan struct{})
// Start a sender with the communication channel
go sender(c)
// Receive a message from the sender, in this case the message is a channel itself
r := <- c
// Send response to the sender on the channel given to us by the sender
r <- struct{}{}
}
func sender(c chan chan struct{}) {
// Create a channel the receiver will use to respond to us
r := make(chan struct{})
// Send the channel to the receiver
c <- r
// This is the response received after the received got the message
<- r
}
As to your second question about identifying a specific sender, you may be able to use something like goroutinemap which allows you to manage the lifecycle of named go-routines. This pattern isn't common however, and if you need to identify a specific channel sender, it's possible you could (and should) re-design your solution.
Managing application state
This depends entirely on your application and what it does. Edit: according to OP, the application is a chess game over websockets. You could consider creating a data structure with references to both player's websocket connections, as well as the game state between the players. This data structure would get created when a game is started, then the data structure could manage the messages back and forth between the players and the updating of the game state internally. Perhaps something like
type GameState struct {
Player1 *websocket.Conn
Player2 *websocket.Conn
// Add any game state needed here
}
func (s *GameState) run(ctx context.Context) {
// Send messages between websocket connections here and update game state accordingly
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论