This is a creation in Article, where the information may have evolved or changed.
In the actual system project engineering, we write code to try to avoid unnecessary coupling, or you later in the update and maintenance of code will be found as deep in the mire, Whatever pity dorado things the whole system is going to change the acid cool will make you deeply regret why you had to write everything to a piece (I will not say that I just did this when I was an intern ...). )
So this article is mainly about how to design the internal logic of the sever, the part of the logic that the server processes the client to send the message and the Sevrer processing the socket connection logic to decouple ~
The realization of this piece of inspiration is mainly in reading an HTTP open source framework: Beego source code, the Beego of the entire architecture is highly decoupled, here to cite the author's introduction:
Beego is built on eight independent modules and is a highly decoupled framework. When the design of the Beego is to consider functional modularity, users can still use these standalone modules even if they do not use Beego HTTP logic, for example: You can use the cache module to do your caching logic; Use the log module to record your operation information; Module to parse your files in various formats. So beego can be used not only for the application development of the HTTP class, but also a useful module in the development of your socket game, which is one of the reasons why Beego is popular. If you have played Lego, you should know that a lot of high-level things are a piece of building blocks, and design beego, these modules are building blocks, high-level robot is beego.
Here's an architectural diagram of the Beego:
This is a typical MVC framework where you can see that when a user sends a request to Beego, the Beego internally filters through the routing parameters, and then the route determines which controller executes the relevant logic based on the parameters that the user sends. and the relevant module implementation function is called in the controller. In this way, Beego successfully made all modules independent, which is what Astaxie called "Lego Building".
Here, we can imitate the architecture of Beego, add a layer of router inside the server, through the router to the information through the socket through the rule line we set, call the relevant controller for task distribution processing. In this process, not only the controller is independent of each other, the matching rules and controllers are also independent of each other.
The following is the implementation code for router, where the structure of MSG corresponds to a JSON string, of course, considering the internship company is now using this, modified part, but the core idea is the same oh:
Import ("Utils" "FMT" "Encoding/json") type Msg struct {Conditions map[string]interface{} ' JSON: "meta" ' Content interface{} ' json: ' content ' '}type Controller interface {excute (message Msg) []byte}var routers [][2]interface{} Func Route (Judge interface{}, controller Controller) {switch judge. Type) {case func (entry Msg) Bool:{var arr [2]interface{}arr[0] = judgearr[1] = Controllerrouters = Append (Routers,arr)}cas E map[string]interface{}:{defaultjudge:= func (entry Msg) bool{for Keyjudge, Valjudge: = Range judge. ( map[string]interface{}) {val, OK: = entry. Meta[keyjudge]if!ok {return false}if val! = Valjudge {return false}}return true}var arr [2]interface{}arr[0] = Defaultjud GEARR[1] = Controllerrouters = Append (Routers,arr) fmt. PRINTLN (routers)}default:fmt. Println ("Something is wrong in Router")}}
By customizing the interface router, we encapsulate the matching rule judge and the corresponding controller, and then in the server side is responsible for receiving the socket send information function handleconnection there to implement router internal traversal can:
For _, V: = range routers{pred: = v[0]act: = V[1]var message Msgerr: = JSON. Unmarshal (postdata,&message) if err! = Nil {Log (err)}if pred. (Func (entry MSG) bool) (message) {Result: = act. Controller). Excute (MESSAGE) Conn. Write (Result) return}}
So that each time the client sends information, we can let the router automatically match the existing rules, and finally call the corresponding controller for the implementation of the logic, the following gives a controller to write an instance, The function of this controll is to send the JSON type as mirror, returning the message from the client as it is:
Type Mirrorcontroller struct {}func (this *mirrorcontroller) excute (Message Msg) []byte {mirrormsg,err: =json. Marshal (message) checkerror (ERR) return Mirrormsg}func init () {var mirror routers = make ([][2]interface{}, 0,) Route ( Func (Entry MSG) bool{if entry. meta["Msgtype"]== "Mirror" {return true}return false},&mirror)}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.