1.启动服务 1.1 服务源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport "github.com/gin-gonic/gin" func main () { engine := gin.Default() engine.GET("/" , func (ctx *gin.Context) { ctx.JSON(200 ,gin.H{ "msg" :"请求成功" , }) }) _ = engine.Run() }
1.2 启动输出 1 2 3 4 5 6 7 8 9 10 [lepeng@centos ~] [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] Environment variable PORT is undefined. Using port :8080 by default [GIN-debug] Listening and serving HTTP on :8080
2.代码分析 在引入Gin
框架时,包内相关的init()
方法都会被执行;经查找发现下面两个init
方法;
a. 第一个init方法
方法位置: github.com/gin-gonic/gin/context_appengine.go
1 2 3 4 5 package ginfunc init () { defaultAppEngine = true }
b. 第二个init方法
方法位置: github.com/gin-gonic/gin/mode.go
1 2 3 4 5 6 func init () { mode := os.Getenv(EnvGinMode) SetMode(mode) }
2.2 gin.Default() gin.Default源码如下:
1 2 3 4 5 6 7 8 9 func Default () *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine }
@注意: Gin框架中注册中间件是通过 engine.Use(xx)的方式。
2.3 engine.GET(“/“,…) 1.源码 1 2 3 4 5 func (group *RouterGroup) GET (relativePath string , handlers ...HandlerFunc) IRoutes { return group.handle(http.MethodGet, relativePath, handlers) }
在上述示例代码中我们注册了一个匹配根目录("/"
)的路由,处理handlers
是匿名函数,直接调用ctx.JSON
返回json
格式的数据;
1 2 3 4 5 6 engine.GET("/" , func (ctx *gin.Context) { ctx.JSON(200 ,gin.H{ "msg" :"请求成功" , }) })
2. 多种返回格式 在gin.Context
支持多种返回格式,整理常用的返回格式如下:
方法名
描述
ctx.XML(code int, obj interface{})
返回xml
ctx.AsciiJSON(code int, obj interface{})
返回json
,将使特殊字符编码
ctx.PureJSON(code int, obj interface{})
返回json
,有html
的不转义。
3.Json、AsciiJSON、PureJSON 对比 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package mainimport "github.com/gin-gonic/gin" func main () { engine := gin.Default() engine.GET("/" , func (ctx *gin.Context) { key, _ := ctx.GetQuery("key" ) msgBody := gin.H{ "msg" : "请求成功" , "html" :"<span>我是一段html代码</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" : "请求失败" , }) } return }) _ = engine.Run() }
请求返回:
1 2 3 4 5 6 7 8 ➜ ~ curl http://127.0.0.1:8080/\?key\=1 {"html" :"\u003cspan\u003e我是一段html代码\u003c/span\u003e" ,"method" :"ctx.JSON" ,"msg" :"请求成功" }% ➜ ~ curl http://127.0.0.1:8080/\?key\=2 {"html" :"<span>我是一段html代码</span>" ,"method" :"ctx.PureJSON" ,"msg" :"请求成功" } ➜ ~ curl http://127.0.0.1:8080/\?key\=3 {"html" :"\u003cspan\u003e\u6211\u662f\u4e00\u6bb5html\u4ee3\u7801\u003c/span\u003e" ,"method" :"ctx.AsciiJSON" ,"msg" :"\u8bf7\u6c42\u6210\u529f" }%
总结
方法
现象
ctx.JSON
默认会把html
转成unicode
字符,对汉字不做额外处理
ctx.PureJSON
会把html
原样返回,,对汉字不做额外处理
ctx.AsciiJSON
会对汉字和html
都做处理。
2.4 engine.Run() 1.Run
源码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func (engine *Engine) Run (addr ...string ) (err error) { defer func () { debugPrintError(err) }() trustedCIDRs, err := engine.prepareTrustedCIDRs() if err != nil { return err } engine.trustedCIDRs = trustedCIDRs address := resolveAddress(addr) debugPrint("Listening and serving HTTP on %s\n" , address) err = http.ListenAndServe(address, engine) return }
2.为什么默认监听是”:8080” 在Run
方法中调用 resolveAddress(addr)
,该方法源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func resolveAddress (addr []string ) string { 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 :8080 by default" ) return ":8080" case 1 : return addr[0 ] default : panic ("too many parameters" ) } }