Start the service
// Gin service startup code
package main
// Introduce gin framework
import "github.com/gin-gonic/gin"
func main() {
// Create a default routing engine
engine := gin.Default()
// Register Get route
engine.GET("/", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"msg": "request succeeded",
})
})
// The default listener is 0.0.0.0:9090
_ = engine.Run(":9090")
}
Start output
$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET / --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :9090
Code Analysis
Analysis of Gin service startup code.
import “github.com/gin-gonic/gin”
When you initiate the Gin
framework, the related init()
methods in the package will be executed; the following two init
methods are found:
a. The first init
method
package gin
func init() {
// Set up AppEngine = true
defaultAppEngine = true
}
b. The second init
method
func init() {
// Set the running mode of the service, the default is DebugMode
// There are three modes: DebugMode=0 (development mode), releaseCode=1 (production mode), testCode=2 (test mode)
mode := os.Getenv(EnvGinMode)
SetMode(mode)
}
gin.Default()
The source code of gin.Default is as follows:
func Default() *Engine {
// print gin-debug information
debugPrintWARNINGDefault()
// Create a new engine with no routing and no intermediate
engine := New()
// Register global logging and exception catch middleware
engine.Use(Logger(), Recovery())
return engine
}
Middleware is registered in the Gin framework through engine.
engine.GET(“/”,…)
// Register a Get request route with a matching path (relativePath)
// handlers is the corresponding processing logic
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle(http.MethodGet, relativePath, handlers)
}
"/"
In the above example code, we registered a route that matches the root directory ( ), the processing handlers
is an anonymous function, and the data in the ctx.JSON
returned json
format is called directly.
// Register Get route
engine.GET("/", func(ctx *gin.Context) {
ctx.JSON(200,gin.H{
"msg":"request succeeded",
})
})
Multiple return formats
In the gin.Context
support of multiple return formats, the commonly used return formats are as follows:
Method Name | Describe |
---|---|
ctx.XML(code int, obj interface{}) |
return xml |
ctx.AsciiJSON(code int, obj interface{}) |
return json , will encode special characters |
ctx.PureJSON(code int, obj interface{}) |
returns json , and html some are not escaped. |
Comparison of Json, AsciiJSON, PureJSON
package main
import "github.com/gin-gonic/gin"
func main() {
// Create a default routing engine
engine := gin.Default()
// Register Get route
engine.GET("/", func(ctx *gin.Context) {
key, _ := ctx.GetQuery("key")
msgBody := gin.H{
"msg": "request succeeded",
"html": "<span>🤖: I am a piece of html code!</span>",
}
switch key {
case "1":
msgBody["method"] = "ctx.JSON"
ctx.JSON(200, msgBody)
case "2":
msgBody["method"] = "ctx.PureJSON"
ctx.PureJSON(200, msgBody)
case "3":
msgBody["method"] = "ctx.AsciiJSON"
ctx.AsciiJSON(200, msgBody)
default:
ctx.JSON(500, gin.H{
"msg": "request failed",
})
}
return
})
// The default listener is 0.0.0.0:9090
_ = engine.Run(":9090")
}
The request returns:
$ curl http://127.0.0.1:9090/\?key\=1
{"html":"\u003cspan\u003e🤖: I am a piece of html code!\u003c/span\u003e","method":"ctx.JSON","msg":"request succeeded"}%
$ curl http://127.0.0.1:9090/\?key\=2
{"html":"<span>🤖: I am a piece of html code!</span>","method":"ctx.PureJSON","msg":"request succeeded"}
$ curl http://127.0.0.1:9090/\?key\=3
{"html":"\u003cspan\u003e\u1f916: I am a piece of html code!\u003c/span\u003e","method":"ctx.AsciiJSON","msg":"request succeeded"}%
Summarize
Method | Phenomenon |
---|---|
ctx.JSON |
By default, html will be converted into unicode characters, and no additional processing will be performed on special characters. |
ctx.PureJSON |
html returned as it is, and no additional processing will be done to special characters. |
ctx.AsciiJSON |
Special characters and html processed together. |
engine.Run()
The source code is as follows
func (engine *Engine) Run(addr ...string) (err error) {
// Delay close the output of ERROR type log information
defer func() { debugPrintError(err) }()
// Set CIDR (Typeless Inter-Domain Routing) information, default return: 0.0.0.0/0
trustedCIDRs, err := engine.prepareTrustedCIDRs()
if err != nil {
return err
}
engine.trustedCIDRs = trustedCIDRs
// Set the listening IP and port information, the default is ":9090"
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
// Start the service
err = http.ListenAndServe(address, engine)
return
}
Why the default monitor is “:9090”
Run
Called in resolveAddress(addr)
the method, the source code of the method is as follows:
// Receives a string slice parameter
func resolveAddress(addr []string) string {
// If the parameter length is 0, the default listening 9090
switch len(addr) {
case 0:
if port := os.Getenv("PORT"); port != "" {
debugPrint("Environment variable PORT=\"%s\"", port)
return ":" + port
}
debugPrint("Environment variable PORT is undefined. Using port :9090 by default")
return ":9090"
case 1:
// If the parameter length is 1, listen on IP and port
return addr[0]
default:
// If the parameter length is greater than 1, an error will be reported
panic("too many parameters")
}
}