The main difference is that you can access the current player using Spark.getPlayer() in a user message but you can't access the current player in a global message Cloud Code script.
It is possible to subscribe to both a global and user message and in fact this is how these scripts function out of the box. When a message is triggered; first the Global Message script is executed (without player context), after which the corresponding User Message script is executed once for each player receiving the message, in the context of that player.
So if you were to add some player-specific script data to the message in the Player Message script (e.g. Spark.setScriptData({"myHand": Spark.getPlayer().getScriptData("hand")}), the data added to the message will be specific to the player receiving it.
It is possible to subscribe to both a global and user message and in fact this is how these scripts function out of the box. When a message is triggered; first the Global Message script is executed (without player context), after which the corresponding User Message script is executed once for each player receiving the message, in the context of that player.
So if you were to add some player-specific script data to the message in the Player Message script (e.g. Spark.setScriptData({"myHand": Spark.getPlayer().getScriptData("hand")}), the data added to the message will be specific to the player receiving it.