英文:
Closing Channel Inside of a Struct
问题
我一直在尝试查看关于关闭通道的现有帖子,但似乎找不到我要找的确切内容。我在一个结构体中有两个通道。在创建完通道后,我尝试立即运行defer close(channelName)
,但通道立即关闭并出现错误。如果我不处理关闭通道的问题,代码可以正常运行,但无法正常关闭,我必须使用ctrl z来挂起程序,因为在使用ctrl c后程序仍在运行。以下是代码的重要部分:
总结一下,结构体KrakenClient
有一个类型为WebsocketClient
的字段,其中包含2个WebSockets和2个通道。在KrakenClient
结构体上调用InitWebSocketClient
函数会创建这两个通道并连接到WS服务器。一旦连接到服务器,我开始解组所有响应并将这些响应发送到一个通道中。然后,我订阅特定的端点,并开始“监听”响应(实际上是遍历数据并根据某些条件将其添加到传递给监听函数的ohlcMap变量中)。我只是不明白在哪里应该关闭这些通道。我是否需要在KrakenClient
结构体上创建一个Close
函数,在关闭通道时使用defer调用它?如果是这样,它应该放在哪里?感谢任何帮助!
英文:
I've been trying to look through existing posts about closing a channel, but I can't seem to find exactly what I'm looking for. I have two channels inside of a struct. After making the channels, I tried to run defer close(channelName)
immediately after, but the channels immediately closed and I got an error. If I don't deal with closing the channels, the code runs fine, but doesn't shut down gracefully and I have to use ctrl z to suspend the program, since it's still running after using ctrl c. Here are the important parts of the code:
type WebsocketClient struct {
pubSocket ws_client.Socket
privSocket ws_client.Socket
pubChan chan interface{}
privChan chan interface{}
}
type KrakenClient struct {
WebSocket WebsocketClient
Testing bool
}
func (client *KrakenClient) initChannels() {
client.WebSocket.pubChan = make(chan interface{})
client.WebSocket.privChan = make(chan interface{})
//defer close(client.WebSocket.pubChan)
//defer close(client.WebSocket.privChan)
}
func (client *KrakenClient) InitWebSocketClient(wg *sync.WaitGroup, testing bool) {
client.initTesting(testing)
client.initChannels()
client.startWebSocketConnection(wg)
}
func (client *KrakenClient) PubDecoder(wg *sync.WaitGroup, ctx context.Context) {
wg.Add(1)
defer wg.Done()
defer client.WebSocket.pubSocket.Close()
if err := PubSocketGuard(client.WebSocket); err != nil { // guard clause checker. makes sure i'm actually using a public WebSocket
panic(err)
}
var res interface{}
ws_client.ReceiveLocker(&client.WebSocket.pubSocket)
client.WebSocket.pubSocket.OnTextMessage = func(message string, socket ws_client.Socket) {
res = ws_client.PubJsonDecoder(message, client.Testing)
client.WebSocket.pubChan <- res
}
ws_client.ReceiveUnlocker(&client.WebSocket.pubSocket)
<-ctx.Done()
log.Println("closing public socket")
return
}
func (client *KrakenClient) PubListen(wg *sync.WaitGroup, ctx context.Context, ohlcMap *types.OHLCVals) {
wg.Add(1)
defer wg.Done()
for c := range client.WebSocket.pubChan {
switch v := c.(type) {
// More code here. Not important to the channel problem
}
<-ctx.Done()
}
func main() {
var testing bool = true
comms := make(chan os.Signal, 1)
signal.Notify(comms, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
kraken := &kraken_client.KrakenClient{}
kraken.InitWebSocketClient(&wg, testing)
go kraken.PubDecoder(&wg, ctx)
kraken.SubscribeToOHLC(&wg, []string{"BTC/USD"}, 5)
ohlcMap := types.OHLCVals{}
go kraken.PubListen(&wg, ctx, &ohlcMap)
<-comms
cancel()
wg.Wait()
}
In summary, struct KrakenClient
has a type WebsocketClient
, which holds 2 WebSockets and 2 channels. Calling the InitWebSocketClient
func on the KrakenClient
struct creates the two channels and connects to the WS server. Once connected to the server, I start to unmarshal all responses and send those responses to a channel. I then subscribe to a specific endpoint, and start to "listen" to the responses (actually go through the data and add it to the ohlcMap variable that's passed to the listen func depending on certain circumstances). I just don't understand where I should be closing the channels. Do I need to create a Close
function on my KrakenClient
struct that defers when the channels are closed? If so, where would it even go? Appreciate any help!
答案1
得分: 1
你必须在主函数中调用defer,因为当你在initChannels函数中调用defer时,它会在创建完通道后立即关闭通道。
defer语句总是在函数(在你的代码中是initChannels函数)返回后执行。
你可以编写一个关闭函数来关闭通道,并在主函数中调用它,如下所示:
func (client *KrakenClient) closeChannels() {
close(client.WebSocket.pubChan)
close(client.WebSocket.privChan)
}
func (client *KrakenClient) initChannels() {
client.WebSocket.pubChan = make(chan interface{})
client.WebSocket.privChan = make(chan interface{})
}
func main() {
...
kraken.InitWebSocketClient(&wg, testing)
defer kraken.closeChannels()
...
}
英文:
You must call defer in main func because when you call defer in initChannels func it's immediately close your channels after making.
The defer always execute when the function (initChannels in your code) has been return.
you can write a closing function for close the channels and call it on main func like as:
func (client *KrakenClient) closeChannels() {
close(client.WebSocket.pubChan)
close(client.WebSocket.privChan)
}
func (client *KrakenClient) initChannels() {
client.WebSocket.pubChan = make(chan interface{})
client.WebSocket.privChan = make(chan interface{})
}
func main() {
...
kraken.InitWebSocketClient(&wg, testing)
defer kraken.closeChannels()
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论