I was hit by one of these “you didn’t know this, now suffer” moments today. I was working on a websocket server and was gradually adding new functionality. Out of nowhere, the server started disconnecting the client. Without any error whatsoever. I even wasted some time thinking maybe the client was doing something wrong.
Then with no luck with anything I tried, I tried to use the debugger. The debugger would execute the last line of a function and then the client would disconnect. This is the exact function
|
|
This function was called from the handleMove
function and there are other steps after it. But the client would disconnect and not run anything after this function. So, I added logs, logs and more logs. I disabled the whole function and found out it was fine. Then I added logs and found everything was printed except the last line (after the g.State.PlayerDecks[player] = original[4:]
was executed.
This is even stranger since both the PlayerHands and PlayerDecks are exact same type. And I would have loved to see the panic message. But, nothing. Then after some googling and ChatGPT, I found out the problem was this.
A struct field that is declared as a map in Go will be nil by default. If you try to read from a nil map, it will not panic, but if you try to write to it, it will panic with a runtime error.
And where was my error/panic going? The net/http package in Go has a default recovery middleware that recovers from panics and logs them. However, if you are using a custom handler or if the panic occurs outside of the HTTP request context (like in a goroutine), it will not be caught by this middleware.
|
|
Lesson learnt, I guess!