gin web(http) server

  • 源代码
package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"repro_go/gin_webserver/pool"
	"repro_go/gin_webserver/view"
	"time"

	"github.com/gin-gonic/gin"
	_ "github.com/lib/pq"
	"github.com/redigo-master/redis"
)

var redisPtr redis.Conn //redis句柄
var errg error          //全局变量
var pgDB *sql.DB        //pgsql句柄

func init() {
	//若不能打开redis以及pgsql则直接退出
	//打开redis
	redisPtr, errg = redis.Dial("tcp", "127.0.0.1:6379") //向本机链接
	if errg != nil {
		log.Println(errg)
		os.Exit(0)
	}
	//打开pgsql
	//用户是postgres 密码 root
	pgDB, errg = sql.Open("postgres", "host=localhost port=5432 user=postgres password=root dbname=postgres sslmode=disable")
	if errg != nil {
		log.Println(errg)
		os.Exit(0)
	}

}

//Loggeer中间件
func Logger() gin.HandlerFunc { //感觉现在没啥用
	return func(c *gin.Context) {
		t := time.Now()
		// 设置 example 变量
		c.Set("example", "12345")
		// 请求前
		c.Next()
		// 请求后
		latency := time.Since(t)
		log.Print(latency)
		// 获取发送的 status
		status := c.Writer.Status()
		log.Println(status)
	}
}
func main() {
	//日志写入文件+控制台
	// gin.DisableConsoleColor()
	// f, _ := os.Create("/gin.log")
	// gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

	//新建中间件
	r := gin.New() //r := gin.Default() //使用默认中间件
	r.Use(Logger())

	r.LoadHTMLGlob("../view/*") //载入html
	//静态文件
	r.StaticFile("/favicon.png", "./static/zu.png")

	//GET /
	r.GET("/", func(c *gin.Context) {

		c.HTML(http.StatusOK, "view/root.htm", gin.H{
			"doc":    "Hello gin",
			"status": http.StatusOK,
		})
	})
	//GET ping
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	//设置 获取 Cookie
	r.GET("/cookie", func(c *gin.Context) {
		cookie, err := c.Cookie("gin_cookie")
		if err != nil {
			cookie = "NotSet"
			c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true)
		}
		fmt.Printf("Cookie value is : %v\n", cookie)
	})
	//GET 匹配 /user/jojo/ola
	r.GET("/user/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")
		message := name + " is " + action
		c.String(http.StatusOK, message)
	})

	//GET 匹配 /welcome?firstname=jojo&lastname=DIO
	r.GET("/welcome", func(c *gin.Context) {
		firstname := c.DefaultQuery("firstname", "Guest")
		lastname := c.Query("lastname") // 是 c.Request.URL.Query().Get("lastname") 的简写
		c.String(http.StatusOK, "Hello %v : %v", firstname, lastname)
	})

	//上传多文件
	r.MaxMultipartMemory = 8 << 20 //最大 8 MB
	r.POST("/upload", func(c *gin.Context) {
		cCp := c.Copy() //并发 必须使用副本
		go func() {
			form, _ := cCp.MultipartForm()
			files := form.File["upload[]"]
			for _, file := range files {
				log.Println(file.Filename)

				//写入文件
				fileName := "D:\\#test/" + file.Filename //配置路径
				if err := cCp.SaveUploadedFile(file, fileName); err != nil {
					c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
					log.Println(err)
				}
			}
			cCp.String(http.StatusOK, "%d files uploaded!", len(files))
		}()
	})

	//http重定向
	r.GET("/test", func(c *gin.Context) {
		c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
	})
	//路由重定向
	r.GET("/test1", func(c *gin.Context) {
		c.Request.URL.Path = "/test2"
		r.HandleContext(c)
	})
	r.GET("/test2", func(c *gin.Context) {
		c.JSON(200, gin.H{"hello": "world"})
	})

	//查询数据库
	r.GET("/query", func(c *gin.Context) {

		c.HTML(http.StatusOK, "view/query.htm", gin.H{
			"doc": "Hello gin",
		})

	})
	r.POST("/query", func(c *gin.Context) {
		mm := make(map[string]string)
		sqlcontent := `select  "name","password" from public.stu `
		row, err := pgDB.Query(sqlcontent)
		if err != nil {
			log.Println(err)
		}
		for row.Next() {
			var name string
			var pwd string
			err = row.Scan(&name, &pwd)
			mm[name] = pwd
		}
		c.JSON(http.StatusOK, mm)
	})
	// Example for binding a HTML form (user=manu&password=123)

	//加载html文件
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "view/login.htm", gin.H{
			"title": http.StatusOK,
		})

	})
	r.POST("/login", func(c *gin.Context) {
		var form view.Login

		// This will infer what binder to use depending on the content-type header.
		if err := c.ShouldBind(&form); err != nil {
			/*
				c.ShouldBindBodyWith 会在绑定之前将 body 存储到上下文中。 这会对性能造成轻微影响,如果调用一次就能完成绑定的话,那就不要用这个方法
			*/
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		online, _ := UserOnline(form.User)
		if !online { //redis中没有该用户

			/*
				pgsql注册
					1.已存在 直接redis添加id
					2.不存在 pgsql添加用户id redis添加id
			*/

			//1.已存在 直接redis添加
			//线程池

			//初始化task结构体
			var ms pool.Myservice
			ms = form
			job := pool.Job{Ms: ms, PGSQLPointer: pgDB}
			pool.Buff <- job //工作加入线程池

			// sqlcontent := `select  "name" from public.stu where name=` + form.User
			// row := pgDB.QueryRow(sqlcontent)
			// err := row.Scan(&name)
			// if err != nil {
			// 	//2.name不存在于pgsql
			// 	// pgsql添加用户name  redis添加name
			// 	sqlcontent = `insert into public.stu (name,password) values ($1,$2)`
			// 	stmt, err := pgDB.Prepare(sqlcontent)
			// 	_, err = stmt.Exec(form.User, form.Password)
			// 	if err != nil {
			// 		//status = "add user error"
			// 		log.Println(err)
			// 	}
			// }
			redisPtr.Do("SADD", "sessionID", form.User)
			//重定向
			//暂时先返回主页
			c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/")
			//c.JSON(http.StatusUnauthorized, gin.H{"status": status})
			return
		}
		//暂时先返回主页
		c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/")
		//c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})

	})

	//优雅的关闭服务器
	srv := &http.Server{
		Addr:    ":8080",
		Handler: r,
	}
	go func() {
		// 服务连接
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	log.Println("Shutdown Server ...")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	//关闭所有句柄

	defer cancel()
	defer redisPtr.Close()
	defer pgDB.Close()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")
	//r.Run() // listen and serve on 0.0.0.0:8080
}

//UserOnline... 用户是否在redis缓存中
func UserOnline(username string) (online bool, err error) {
	id, err := redisPtr.Do("SISMEMBER", "sessionID", username)
	if id.(int64) == 0 { //用户不在线
		return false, err
	}
	return true, err
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值