一、html渲染

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("static/templates/*")
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html",
			gin.H{"title": "golang web"})
	})
	r.Run(":8000")
}
static/templates/index.html

<html>
<h1>
    {{ .title }}
</h1>
</html>

二、表单绑定

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type LoginForm struct {
	User     string `form:"user" binding:"required"`
	Password string `form:"password" binding:"required"`
}

func main() {
	r := gin.Default()
	r.POST("/login", func(c *gin.Context) {
		// 你可以使用显式绑定声明绑定 multipart form:
		// c.ShouldBindWith(&form, binding.Form)
		// 或者简单地使用 ShouldBind 方法自动绑定:
		var form LoginForm
		// 在这种情况下,将自动选择合适的绑定
		if c.ShouldBindWith(&form, binding.Form) == nil {
			if form.User == "user" && form.Password == "password" {
				c.JSON(200, gin.H{"status": "you are logged in"})
			} else {
				c.JSON(401, gin.H{"status": "unauthorized"})
			}
		}
	})
	r.Run(":8000")
}

/**
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> POST /login HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.83.1
> Accept: */*
> Content-Length: 248
> Content-Type: multipart/form-data; boundary=------------------------e350eab01c4dd2e0
>
* We are completely uploaded and fine
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Mon, 24 Oct 2022 04:28:05 GMT
< Content-Length: 30
<
{"status":"you are logged in"}* Connection #0 to host localhost left intact
*/

三、xml/json/yaml/protobuf渲染

package main

import (
   "github.com/gin-gonic/gin"
   "github.com/gin-gonic/gin/testdata/protoexample"
   "net/http"
)

type message struct {
   Code int    `json:"code"`
   Msg  string `json:"msg"`
   Data string `json:"data"`
}

func main() {
   r := gin.Default()
   r.GET("/json", func(c *gin.Context) {
      c.SecureJSON(200, message{
         Code: 200,
         Msg:  "成功",
         Data: "{\"name\":\"小哥\"}",
      })
   })
   r.GET("/xml", func(c *gin.Context) {
      c.XML(http.StatusOK, gin.H{"message": "xml", "status": http.StatusOK})
   })

   r.GET("/yaml", func(c *gin.Context) {
      c.YAML(http.StatusOK, gin.H{"message": "yaml", "status": http.StatusOK})
   })

   r.GET("/protobuf", func(c *gin.Context) {
      reps := []int64{int64(1), int64(2)}
      label := "test"
      // protobuf 的具体定义写在 testdata/protoexample 文件中。
      data := &protoexample.Test{
         Label: &label,
         Reps:  reps,
      }
      // 请注意,数据在响应中变为二进制数据
      c.ProtoBuf(http.StatusOK, data)
   })
   r.Run(":8000")
}

四、文件上传

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func main() {
	r := gin.Default()
	r.MaxMultipartMemory = 8 << 20 // 8 MiB
	r.POST("/upload", func(c *gin.Context) {
		form, _ := c.MultipartForm()
		files := form.File["upload[]"]

		for _, file := range files {
			log.Println(file.Filename)
			dst := "./" + file.Filename
			// 上传文件至指定目录
			c.SaveUploadedFile(file, dst)
		}
		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
	})
	r.Run(":8000")

	/**
	curl -X POST http://localhost:8000/upload -F "upload[]=@./X_80.png"
	  -H "Content-Type: multipart/form-data"
	*/
}

五、从reader读取器中读取

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	r.GET("/someDataFromReader", func(c *gin.Context) {
		response, err := http.Get("https://www.linuxprobe.com/wp-content/uploads/2022/05/00SLU5M6ZFYOXWK_E2.png")
		if err != nil || response.StatusCode != http.StatusOK {
			c.Status(http.StatusServiceUnavailable)
			return
		}

		reader := response.Body
		contentLength := response.ContentLength
		contentType := response.Header.Get("Content-Type")

		extraHeaders := map[string]string{
			"Content-Disposition": `attachment; filename="gopher.png"`,
		}

		c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
	})
	r.Run(":8000")
}

六、优雅的关闭服务器

package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"
)

func main() {
	r := gin.Default()
	r.GET("/someDataFromReader", func(c *gin.Context) {
		response, err := http.Get("https://www.linuxprobe.com/wp-content/uploads/2022/05/00SLU5M6ZFYOXWK_E2.png")
		if err != nil || response.StatusCode != http.StatusOK {
			c.Status(http.StatusServiceUnavailable)
			return
		}

		reader := response.Body
		contentLength := response.ContentLength
		contentType := response.Header.Get("Content-Type")

		extraHeaders := map[string]string{
			"Content-Disposition": `attachment; filename="gopher.png"`,
		}

		c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
	})
	//r.Run(":8000")
	serve := &http.Server{
		Addr:    ":8000",
		Handler: r,
	}
	go func() {
		if err := serve.ListenAndServe(); err != nil {
			log.Fatalf("listen:%s\n", err)
		}
	}()
	q := make(chan os.Signal)
	signal.Notify(q, os.Interrupt, os.Kill)
	<-q
	log.Println("server shutdown...")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := serve.Shutdown(ctx); err != nil {
		log.Fatalf("server shutdown:%s",err)
	}
	

}

七、使用http restful 风格

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type message struct {
	Code int 
	Msg string
	Data string
}
func main() {
	r := gin.Default()
	r.GET("/get", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.POST("/post", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.PUT("/put", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.DELETE("/delete", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.PATCH("/patch", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.HEAD("/head", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.OPTIONS("/option", func(c *gin.Context) {
		c.JSON(http.StatusOK,message{
			Code: 200,
			Msg:  "成功",
			Data: "data ",
		})
	})
	r.Run(":8000")

}