Gin是go语言的Web框架,结合go自带的第三方库net/http,性能不错。
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
name := c.DefaultQuery("name", "张三")
c.String(http.StatusOK, fmt.Sprintf("你好 %s", name))
})
// 8080端口
r.Run(":8080")
}
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
r.GET("/user/:name/*action", func(c *gin.Context) {
name := c.Param("name")
action := c.Param("action")
c.String(http.StatusOK, fmt.Sprintf("你好 %s %s", name, action))
})
// 8080端口
r.Run(":8080")
}

package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
r.POST("/form", func(c *gin.Context) {
types := c.DefaultPostForm("type", "post")
username := c.PostForm("username")
password := c.PostForm("password")
c.String(http.StatusOK, fmt.Sprintf("用户名:%s 密码:%s type:%s", username, password, types))
})
// 8080端口
r.Run(":8080")
}

package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
// 限制上传最大尺寸
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
c.String(http.StatusServiceUnavailable, "上传文件出错")
}
c.SaveUploadedFile(file, file.Filename)
c.String(http.StatusOK, file.Filename)
})
// 8080端口
r.Run(":8080")
}

package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
// 限制上传最大尺寸
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest,
fmt.Sprintf("Error: %s", err.Error()))
}
files := form.File["files"]
for _, file := range files {
if err := c.SaveUploadedFile(file, file.Filename); err != nil {
c.String(http.StatusBadRequest, "上传文件出错 %s", err.Error())
}
}
c.String(http.StatusOK, "上传%d文件成功", len(files))
})
// 8080端口
r.Run(":8080")
}

httproter会将所有路由规则构造一颗前缀树。
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由
r := gin.Default()
v1 := r.Group("v1")
{
v1.GET("/rout1", rout1)
}
{
v1.GET("/rout2", rout2)
}
v2 := r.Group("v2")
{
v2.POST("rout1", rout1)
v2.POST("rout2", rout2)
}
// 8080端口
r.Run(":8080")
}
func rout1(c *gin.Context) {
name := c.DefaultQuery("name", "张三")
c.String(http.StatusOK, fmt.Sprintf("你好! %s", name))
}
func rout2(c *gin.Context) {
name := c.DefaultQuery("name", "李四")
c.String(http.StatusOK, fmt.Sprintf("你好! %s", name))
}

package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Login struct {
User string `json:"user"`
Password string `json:"password"`
}
func main() {
r := gin.Default()
r.POST("loginJson", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if json.User != "root" || json.Password != "admin" {
c.JSON(http.StatusForbidden, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
// 8080端口
r.Run(":8080")
}


package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Login struct {
User string `form:"username" json:"user"`
Password string `form:"password" json:"password"`
}
func main() {
r := gin.Default()
r.POST("loginForm", func(c *gin.Context) {
var form Login
if err := c.Bind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.User != "root" || form.Password != "admin" {
c.JSON(http.StatusForbidden, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
// 8080端口
r.Run(":8080")
}

package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Login struct {
// binding:"required"的字段,是必须字段,否则报错
User string `uri:"username" binding:"required"`
Password string `uri:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("/:username/:password", func(c *gin.Context) {
var uri Login
if err := c.ShouldBindUri(&uri); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if uri.User != "root" || uri.Password != "admin" {
c.JSON(http.StatusForbidden, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8080")
}

package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/testdata/protoexample"
)
func main() {
r := gin.Default()
r.GET("json", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{"data": "[1]", "status": 200})
})
r.GET("struct", func(ctx *gin.Context) {
var msg struct {
Data string
Status int
}
msg.Data = "[2]"
msg.Status = 200
ctx.JSON(http.StatusOK, msg)
})
r.GET("xml", func(ctx *gin.Context) {
ctx.XML(http.StatusOK, gin.H{"data": "[3]", "status": 200})
})
r.GET("yaml", func(ctx *gin.Context) {
ctx.YAML(http.StatusOK, gin.H{"data": "[4]", "status": 200})
})
r.GET("protobuf", func(ctx *gin.Context) {
reps := []int64{int64(5)}
label := "label"
data := &protoexample.Test{
Label: &label,
Reps: reps,
}
ctx.ProtoBuf(http.StatusOK, data)
})
r.Run(":8080")
}





package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/index", func(ctx *gin.Context) {
ctx.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")
})
r.Run(":8080")
}

package main
import (
"log"
"time"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/async", func(ctx *gin.Context) {
context := ctx.Copy() // 必须使用上下文副本,不能使用原始上下文
// 启动新的goroutine
go func() {
time.Sleep(3 * time.Second)
log.Println("异步执行:" + context.Request.URL.Path)
}()
})
r.GET("sync", func(ctx *gin.Context) {
time.Sleep(3 * time.Second)
log.Println("同步执行:" + ctx.Request.URL.Path)
})
r.Run(":8080")
}

package main
import (
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.Use(MiddleWare())
// {}只是为了代码规范
{
r.GET("/ce", func(ctx *gin.Context) {
req, _ := ctx.Get("request")
fmt.Println("request:", req)
ctx.JSON(http.StatusOK, gin.H{"reqeust": req})
})
}
r.Run(":8080")
}
func MiddleWare() gin.HandlerFunc {
return func(ctx *gin.Context) {
t := time.Now()
fmt.Println("中间件开始执行")
// 设置request到上下文,可以通过Get获取
ctx.Set("request", "中间件")
status := ctx.Writer.Status()
// 执行函数
ctx.Next()
fmt.Println("中间件执行完毕", status)
t2 := time.Since(t)
fmt.Println("time:", t2)
}
}


package main
import (
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 全局中间件
// r.Use(MiddleWare())
// 局部中间件
r.GET("/ce", MiddleWare(), func(ctx *gin.Context) {
req, _ := ctx.Get("request")
fmt.Println("request:", req)
ctx.JSON(http.StatusOK, gin.H{"reqeust": req})
})
r.Run(":8080")
}
func MiddleWare() gin.HandlerFunc {
return func(ctx *gin.Context) {
t := time.Now()
fmt.Println("中间件开始执行")
// 设置request到上下文,可以通过Get获取
ctx.Set("request", "中间件")
status := ctx.Writer.Status()
// 执行函数
ctx.Next()
fmt.Println("中间件执行完毕", status)
t2 := time.Since(t)
fmt.Println("time:", t2)
}
}
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 全局中间件
// r.Use(MiddleWare())
// 局部中间件
r.GET("/cookie", func(ctx *gin.Context) {
cookie, err := ctx.Cookie("key_cookie")
if err != nil {
cookie = "Cookie未设置"
ctx.SetCookie("key_cookie", "value_cookie", 60, "/", "localhost", false, true)
}
fmt.Println("Cookie:", cookie)
})
r.Run(":8080")
}
package main
import (
"bytes"
"net/http"
"time"
"github.com/dchest/captcha"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 全局中间件
r.Use(Session("sectet"))
r.GET("/captcha", func(ctx *gin.Context) {
Captcha(ctx, 4)
})
r.GET("/captcha/verify/:value", func(ctx *gin.Context) {
value := ctx.Param("value")
if CaptchaVerify(ctx, value) {
ctx.JSON(http.StatusOK, gin.H{"status": 0, "msg": "success"})
} else {
ctx.JSON(http.StatusOK, gin.H{"status": 1, "msg": "failed"})
}
})
r.Run(":8080")
}
func Session(keyPairs string) gin.HandlerFunc {
store := SessionConfig()
return sessions.Sessions(keyPairs, store)
}
func SessionConfig() sessions.Store {
sessionMaxAge := 3600
sessionSectet := "sectet"
store := cookie.NewStore([]byte(sessionSectet))
store.Options(sessions.Options{
MaxAge: sessionMaxAge,
Path: "/",
})
return store
}
func Captcha(c *gin.Context, length ...int) {
l := captcha.DefaultLen
w, h := 107, 36
if len(length) == 1 {
l = length[0]
}
if len(length) == 2 {
w = length[1]
}
if len(length) == 3 {
h = length[2]
}
captchaId := captcha.NewLen(l)
session := sessions.Default(c)
session.Set("captcha", captchaId)
_ = session.Save()
_ = Serve(c.Writer, c.Request, captchaId, ".png", "zh", false, w, h)
}
func CaptchaVerify(c *gin.Context, code string) bool {
session := sessions.Default(c)
if captchaId := session.Get("captcha"); captchaId != nil {
session.Delete("captcha")
_ = session.Save()
if captcha.VerifyString(captchaId.(string), code) {
return true
} else {
return false
}
} else {
return false
}
}
func Serve(w http.ResponseWriter, r *http.Request, id, ext, lang string, download bool, width, height int) error {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
var content bytes.Buffer
switch ext {
case ".png":
w.Header().Set("Content-Type", "image/png")
_ = captcha.WriteImage(&content, id, width, height)
case ".wav":
w.Header().Set("Content-Type", "audio/x-wav")
_ = captcha.WriteAudio(&content, id, lang)
default:
return captcha.ErrNotFound
}
if download {
w.Header().Set("Content-Type", "application/octet-stream")
}
http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes()))
return nil
}


注意:cookie要一致,表示同一个会话。