一、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")
}