前端程序员学习 Golang gin 框架实战笔记之二分析 context

上一节: 前端程序员学习 Golang gin 框架实战笔记之一开始玩 gin

之前讲到了如何使用 gin,这一节我们来分析和调试一下它的代码。

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第1张图片

New()

第一行的 gin.New() ,其实还有一种写法:

gin.Default()

有什么区别呢?

你很容易查看:

你的鼠标在 New 方法停留,然后会弹出如下的窗口:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第2张图片

这个编辑器会告诉你这个方法的意义。

就是返回一个没有带中间件的 gin 实例。

关于中间件以后再来讲。

那么你可以点进去看 New 方法,苹果系统,按住键盘上的 command,再单击就可以进去:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第3张图片

进去后,可以查看它源码:

*Engine 这个是它的返回值,是个指针。

golang 也是有指针的,有点仿照 c。

关于指针,可以运行下面的地址看看:

package main

import "fmt"

func main() {

    var count int = 4
    fmt.Println(count)

    var pv = &count
    *pv = 3
    fmt.Println(pv)
    fmt.Println(*pv)

    var pv2 *int = &count
    *pv = 2
    fmt.Println(pv2)
    fmt.Println(*pv2)

    pv3 := &count
    *pv = 1
    fmt.Println(pv3)
    fmt.Println(*pv3)
}

我的理解就是指向值或对象的内存地址,如果要改对象或结构体内容,就传指针。

我们传结构体的时候,你不用指针,会把值传过去,可能相当于 copy 一份数据传过去,那么无法对结构体修改,只有传指针才行。

你在这个文件搜索一下 Default 方法:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第4张图片

我们可以比较一下,就是调了上面的 New 方法之外,多加了两个中间件:

engine.Use(Logger(), Recovery())

一个日志用的,另一个是来恢复程序用的。

Context

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第5张图片

我们再来看下这个 Context 是个啥。

你可以在网上找到它的概念,其他语言或框架也有,只是跟 Golang 的有些区别。

我对它的理解不是很深,先说下:

它首先是个结构体:

type Context interface {
	Deadline() (deadline time.Time, ok bool)
	Done() <-chan struct{}
	Err() error
	Value(key interface{}) interface{}
}

我看别人对它的解释是这样的:

context是一个带有截止时间,取消信号和key,value的上下文对象。

首先它有值。

到底体现在哪呢?

我们来调试一下:

先退出之前的 go run main.go 进程,用 control + c 即可。

我这里用 GoLang 编辑器:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第6张图片

我们用 Debug 模式来运行。

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第7张图片

然后你用 postman 访问一下:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第8张图片

这个 Context 有啥值呀,就是有参数,请求这些东西,路径啥的,比如可以从 postman 得到请求的参数。

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第9张图片

举例

还有个例子是这样的:

package main

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

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	go handle(ctx, 500*time.Millisecond)
	select {
	case <-ctx.Done():
		fmt.Println("main", ctx.Err())
	}
}

func handle(ctx context.Context, duration time.Duration) {
	select {
	case <-ctx.Done():
		fmt.Println("handle", ctx.Err())
	case <-time.After(duration):
		fmt.Println("process request with", duration)
	}
}

你执行下,看它会输出啥:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第10张图片

我们在写协程,或其他语言,写线程进程的时候,我们这个主协程要对这个协程的状态进行控制,不然你主协程都退出了,协程还在运行就不太好。

或者我们要共享或传一些变量,其他语言可能会用共享内存,队列,信号量啥的。

这里我们就可以传一个 Context 过去。

handle 协程中,我们通过 ctx.Done() 判断主程是不是执行完成,那主程要一秒后才完成,协程才 500 ms,最后肯定是先输出

fmt.Println("process request with", duration)

handle 方法就结束了,再过了 500 ms, 就输出:

fmt.Println("main", ctx.Err())

整个世界就结束了。

在协程中是可以知道主协的运行状态的,至少能知道是不是结束了。

你不用 context 的话,可能就像下面这样:

func main() {
	fmt.Println("main is start")
	go Test("value")
	fmt.Println("main is finish")
	time.Sleep(3 * time.Second)
}

func Test(value string) {
	fmt.Println("test is start")
	time.Sleep(5 * time.Second)
	fmt.Println("test is finish")
}

你执行你的,我执行我的,无法获得主程和协程的状态。

这个叫“同步信号”。

我们还可以传值:

func main() {
	fmt.Println("main is start")
	ctx := context.WithValue(context.Background(), "key", "value")
	go TestValue(ctx)
	time.Sleep(1 * time.Second)
}

func TestValue(ctx context.Context) {
	fmt.Println("=======:", ctx.Value("key"))
	select {
	case <-ctx.Done():
		fmt.Println("[TestContext] and value is ", ctx.Value("key"))
	}
}

使用 context.WithValue 就可以把值传给协程。

这样就共享数据了呀。

关于 Background 方法 ,可以看:

// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
	return background
}

// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter).
func TODO() Context {
	return todo
}

它返回非空的 context, 主要用于主线程来用。

网上有大佬是这样解释的:

前端程序员学习 Golang gin 框架实战笔记之二分析 context_第11张图片

你可能感兴趣的:(文章分享,前端,学习,golang)