GO 重新进阶学习(五)

这个context 之前没有接触。现在开始重新学习
web 框架的gin
http
json
protocol buffer
gob
RPC
6
那天有空再仔细看一下

https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-context/

context

context

https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-context/
https://segmentfault.com/a/1190000040917752
https://pkg.go.dev/context@go1.7beta1#Background
https://www.cnblogs.com/qcrao-2018/p/11007503.html
https://segmentfault.com/a/1190000039294140

context 包
多个协程之间进行信息传递,包括层层的递进顺序传递
当顶层context被取消或者超时的时候,所有从这个顶层创建的context也应该结束。

context包实现了在程序协程直接共享状态变量的方法,在被调用程序单元的外部,通过上写完变量ctx ,讲过期或取消信号传递给调用的程序单元

go 中开启协程很简单,但是操作起来不容易
sync包可以进行原子操作
用channel可以进行PV操作。可以进行多个协程之间的通讯。

context的结构

type context struct{
Done() <-chan struct
Err() error
deadline()(deadline time ,ok bool )
value(key interface{}) interface{}
}

Done 返回一个close 的channel
err 差错检测
deadline 返回结束的时间,和是否有效
value是共享数据

顶层会创建context

var ctx, cancel = context.WithCancel(context.Background())
var ctxTwo, cancelTwo = context.WithTimeout(context.Background(), 7*1e9)

设置共享参数

ctx = context.WithValue(ctx, 1, 12345)

可以看一下注释return 的结果
完整代码

package main

import (
	"context"
	"errors"
	"fmt"
	"time"
)

func childrenGoroutine(ctx context.Context) {
	var value = ctx.Value(1)
	fmt.Println(value)
	var errorContext = ctx.Err()
	for {
		time.Sleep(1e9)
		select {
		case <-ctx.Done():
			fmt.Printf("this is over ")
			errorContext = errors.New("channel shut down")
			fmt.Println(errorContext)
			return
		default:
			if deadTime, ok := ctx.Deadline(); ok {
				fmt.Println(deadTime)
			} else {
				fmt.Println("time is arrived")
			}
		}
	}
}

/*
所以在大多数情况下,我们都使用context.Background作为起始的上下文向下传递。
上面的两种方式是创建根context,不具备任何功能
*/

func initContext() {

	var ctx, cancel = context.WithCancel(context.Background())
	ctx = context.WithValue(ctx, 1, 12345)
	go childrenGoroutine(ctx)

	var ctxTwo, cancelTwo = context.WithTimeout(context.Background(), 7*1e9)
	go childrenGoroutine(ctxTwo)

	time.Sleep(8 * 1e9)
	cancel()
	cancelTwo()
}

func main() {
	initContext()
	time.Sleep(10 * 1e9)
}

http

主要几点

  1. 基本HTTP
  2. HTTPS原理和实现
  3. gin框架

最后提醒一句,重点是服务端。客户端我会尽量使用andorid 去处理。因为前端也很卷了

https://gin-gonic.com/zh-cn/docs/quickstart/
https://www.bilibili.com/video/BV13g41157hK?p=3&vd_source=aa1af4ac07546d4eabfe89e8a6128265
https://www.bilibili.com/video/BV1Ti4y1w7Um?spm_id_from=333.337.search-card.all.click&vd_source=aa1af4ac07546d4eabfe89e8a6128265
https://www.bilibili.com/video/BV1gJ411p7xC?p=3&vd_source=aa1af4ac07546d4eabfe89e8a6128265
https://juejin.cn/post/6952340347280162852

首先是基本的HTTP
然后是gin框架
ORM框架
学习redis

首先是GIN的基本部分
GIN是很高效的一个框架
零分配路由。
仍然是最快的 http 路由器和框架。
完整的单元测试支持。
实战考验。
API 冻结,新版本的发布不会破坏你的代码。

然后写的时候尽量去满足RESTful风格

	GET用来获取资源
	POST用来新建资源
	PUT用来更新资源
	DELETE用来删除资源。
router.GET("/AsciiJSON", BackASCIIOnlyJSON)
	router.GET("/login", HTMLRendering)
	router.POST("/postMethod", PostMethod)
	router.POST("/uploadOneFile", multipleFilesUpload)
	router.PUT("/putMethod")
	router.DELETE("/deleteMethod")

这里是基本的流程
想一下context的创建流程
创建顶部的context 然后进行向下传播
但顶部取消后,所有的都要取消

虽然我也不知道gin.context里面到底封装了什么
等会看一下源码吧

最基本的JOSN

	这里提一嘴
	gin.H里面实现的也是go原生的包
	如果直接传struct gin会自动转换为JSON
func BackJSON(ctx *gin.Context) {
	var myself = PersonInfo{
		Name: "wyx",
		Age:  21,
		Info: "this is sister of dc",
	}
	/*
			ctx.JSON(http.StatusOK, gin.H{
				"name": "sisterOfDc",
				"age":  "21",
			})
	*/
	ctx.JSON(http.StatusOK, myself)
}

这里我对HTML的搭建进行一些省略。因为
现在前后端都分离了
前端网页是VUE
安卓是直接请求JSON回来
微信也是直接请求JSON回去

当然肯定还是有点的

请求,拿到参数

如果是POST请求
拿到参数的主要为几个函数

var personInfo = ctx.PostForm("Name")
var personInfo.Name=ctx.DefaultPostForm()

	第二个参数是没有输入默认返回的值
func PostMethod(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "login.html", gin.H{
		"name": "ok",
	})

	var personInfo = new(Person)
	personInfo.Name = ctx.PostForm("Name")
	/*
			personInfo.Name=ctx.DefaultPostForm()
		第二个参数是没有输入默认返回的值
	*/

	personInfo.Info = ctx.PostForm("Info")
	fmt.Println(personInfo)
}

这里是拿GIT请求的

函数是
query
queryfault

func HTMLRendering(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "login.html", gin.H{
		"name": "sister of dc",
	})
	var personInfo = new(Person)
	personInfo.Name = ctx.Query("Name")
	personInfo.Info = ctx.Query("Info")
	fmt.Println(personInfo)

	//SecureJSON
}

如果是拿到文件的。
需要设置内存限制,默认32MB MaxMultipartMemory
单个文件

func uploadOneFile(ctx *gin.Context) {
	var file, ErrorFile = ctx.FormFile("file")
	if ErrorFile != nil {
		ErrorFile = errors.New("file is filed")
		fmt.Println(ErrorFile)
	}
	var dst = "./" + file.Filename
	fmt.Println(file.Filename)
	var ErrorSava = ctx.SaveUploadedFile(file, dst)
	if ErrorSava != nil {
		ErrorSava = errors.New("save is filed")
		fmt.Println(ErrorSava)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"fileName": file.Filename,
	})
}

多个文件中。是file。看传过来的key是什么
多个文件也不能超过内存限制
大文件上传看一下

func multipleFilesUpload(ctx *gin.Context) {
	var form, ErrorForm = ctx.MultipartForm()
	if ErrorForm != nil {
		ErrorForm = errors.New("form read is filed")
		fmt.Println(ErrorForm)
	}
	var files = form.File["file"]
	for _, file := range files {
		fmt.Println(file.Filename)
	}
}

在for循环中拿到file中再去开单个文件的读写

简单的HTML的部分

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form action="" method="get">
    <a>this is get Method</a>
    <label>
        First name:
        <input type="text" name="Name"/>
    </label>
    <label>
        Last name:
        <input type="text" name="Info"/>
    </label>
    <input type="submit" value="Submit" />
</form>

<form action="http://192.168.240.131:8090/postMethod" method="POST">
    <a>this is post Method</a>
    <label>
        First name:
        <input type="text" name="Name"/>
    </label>
    <label>
        Last name:
        <input type="text" name="Info"/>
    </label>
    <input type="submit" value="Submit" />
</form>

<form action="http://192.168.240.131:8090/uploadOneFile" method="post" enctype="multipart/form-data">
    <div>
        <label for="file">Choose file to upload</label>
        <input type="file" id="file" name="file" multiple>
    </div>
    <div>
        <input type="submit" value="Submit" />
    </div>
</form>

</body>
</html>

get post put delete 是前端的事情了

中间件

中间件的作用
对一组接口进行统一的操作
实现类似于横切的关注点
记录Log,错误handler 对部分接口进行鉴权

gin中间件中使用goroutine
当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。

这个问题在context中也说了。gin.context是gin自定义的。必须要去看源码

绑定

路由

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值