使用方法
/users/name/users/:id"hello""hello/"gin.RedirectTrailingSlash = truev1 := router.Group("/v1")func(c *gin.Context)gin.Contextval := c.Query()val, ok := c.GetQuery()keyval := c.DefaultQuery(, )c.[Should]BindQuery(&)formjsonc.QueryArray()keyvalue?media=blog&media=wechatc.QueryMap()?ids[a]=123&ids[b]=456&ids[c]=789c.Param():"/user/:name"/user/john/user//user*"/user/:name/*action"/user/john//user/John/love/tom/user/john/sendc.Param("action")//love/tom/sendc.ShouldBindUri(&)uri:"" binding:"required"Content-Typetext/plainBindBindJSONBindXMLBindYAMLgo-playground/validator.v8binding:"required"ShouldBindShouldBindJSONShouldBindXMLShouldBindYAMLc.ShouldBindBodyWithc.PostForm()c.DefaultPostForm(, )c.FormFile()form, _ := c.MultipartForm(); files := form.File[]c.JSON(, gin.H{: })gin.Hmap[string]interface{}c.JSON(, )c.IndentedJSONAbortWithStatusJSON(, gin.H{: })c.Next()()r := gin.Default()r := gin.New()r.Use(())r.Group(,()… )r.GET(, ()…, )
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// 请求前操作
c.Next()
// 请求后操作
}
}
r.GET("/test", func(c *gin.Context) {
c.Request.URL.Path = "/test2"
r.HandleContext(c)
})
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()
engine.handleHTTPRequest(c)
engine.pool.Put(c)
}
func (c *Context) Copy() *Context {
var cp = *c
cp.writermem.ResponseWriter = nil
cp.Writer = &cp.writermem
cp.index = abortIndex
cp.handlers = nil
cp.Keys = map[string]interface{}{}
for k, v := range c.Keys {
cp.Keys[k] = v
}
return &cp
}
c.Setc.Get
// 禁用控制台颜色,将日志写入文件时不需要控制台颜色。
gin.DisableConsoleColor()
// 记录到文件。
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
// 同时将日志写入文件和控制台
gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
- 自定义HTTP配置
router := gin.Default()
s := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
源码阅读
参考
resty框架(http client)import "github.com/go-resty/resty/v2"
var client *resty.Client
fun init() {
client = resty.New().
SetTimeout(1 * time.Minute).
SetRetryCount(3).
SetRetryWaitTime(5 * time.Second). // 超时后等待5秒才重试
SetRetryMaxWaitTime(20 * time.Second).
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
ctx := r.Request.Context()
if err != nil {
logs.CtxWarn(ctx, "query retry on error: %v", err)
return true
}
if r.StatusCode() >= http.StatusInternalServerError {
logs.CtxWarn(ctx, "query retry on status code: %d", r.StatusCode())
return true
}
return false
}).
SetHeaders(map[string]string{
"Content-Type": "application/json",
"User-Agent": "My custom User Agent String",
}).
SetProxy("http://proxyserver:8888").
SetBasicAuth("myuser", "mypass").
OnAfterResponse(func(c *resty.Client, r *resty.Response) error {
ctx := r.Request.Context()
isGzip := r.Header().Get("Content-Encoding") == "gzip"
logs.CtxInfoKvs(ctx, "url", r.Request.URL, "latency", r.Time(), "size", r.Size(), "isGzip", isGzip)
return nil
})
}
func main() {
resp, err := client.R().
SetPathParams(map[string]string{
"id": id,
}).
SetQueryParams(map[string]string{
"name": "jack",
"gender": "male",
}).
Get(url)
fmt.Println("Error :", err)
fmt.Println("Status Code:", resp.StatusCode())
fmt.Println("Request URL:", resp.Request.URL)
_ = json.Unmarshal(resp.Body(), &res)
ti := resp.Request.TraceInfo()
fmt.Println("DNSLookup :", ti.DNSLookup)
fmt.Println("ConnTime :", ti.ConnTime)
fmt.Println("TotalTime :", ti.TotalTime)
}
标准库
server
handler
ServeHTTP(http.ResponseWriter, *http.Request)ServeHTTPhttp.ServeMuxhttp.ServeMux/article/123httprouterhttp.ServeMux///hello/hello/there//hello/hello//hello///
func(s * server)handleGreeting(format string)http.HandlerFunc {
return func(w http.ResponseWriter,r * http.Request){
fmt.Fprintf(w,format,"World")
}
}
mux.HandleFunc("/greeting", s.handleGreeting("Hello %s"))
client
request
- 添加URL参数
params := make(url.Values)
params.Add("key1", "value1")
params.Add("key2", "value2")
req, _ := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
req.URL.RawQuery = params.Encode()
fmt.Println(req.URL) // 输出:http://httpbin.org/get?key1=value1&key2=value2
- 设置请求代理
proxyUrl, err := url.Parse("http://127.0.0.1:8087")
if err != nil {
panic(err)
}
t := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := http.Client{ // 自定义client替换defaultClient
Transport: t,
Timeout: time.Duration(10 * time.Second),
}
// 使用
res, err := client.Get("https://google.com")
response
w.WriteHeader()w.Header().Set()
form
r.Formmap[string][]stringr.ParseForm()r.PostFormaplication/x-www-form-urlencodedmultipart/form-datar.Formmultipart/form-datar.ParseMultipartForm()r.MultipartFormr.FormFile()FromValue()PostFromValue()ParseFormParseMultipartForm
transport
- Transport字段代表向网络服务发送 HTTP 请求,并从网络服务接收 HTTP 响应的操作过程
- 该字段的方法RoundTrip应该实现单次 HTTP 交互需要的所有步骤
- 该字段的方法RoundTrip应该实现单次 HTTP 交互需要的所有步骤
conn
dialer
TODO
resolver
TODO