当前位置: 首页 > news >正文

效果好企业营销型网站建设/网络营销的网站建设

效果好企业营销型网站建设,网络营销的网站建设,昆网站制作,做网站点击挣钱不?GO的并发模式Context 文章目录GO的并发模式Context一、介绍二、Context三、context的衍生四、示例:Google Web Search4.1 server程序4.2 userip 包4.3 google 包五、使用context包中程序实体实现sync.WaitGroup同样的功能(1)使用sync.WaitGro…

GO的并发模式Context

文章目录

  • GO的并发模式Context
    • 一、介绍
    • 二、Context
    • 三、context的衍生
    • 四、示例:Google Web Search
      • 4.1 server程序
      • 4.2 userip 包
      • 4.3 google 包
    • 五、使用context包中程序实体实现`sync.WaitGroup`同样的功能
      • (1)使用`sync.WaitGroup`实现一对多goroutine协作流程多同步工具
      • (2)使用context包中程序实体来实现
    • 六、Context的特点
      • (1)Context介绍:上下文、树、根节点
      • (2)四个延伸Context值的函数
      • (3)理解context包中“可撤销”和“撤销一个context”
      • (4)撤销信号在上下文树中的传播
      • (5)通过Context携带数据

一、介绍

参考:Go的并发模式Context。

在Go服务中,每一个传入进来的请求都将在它自己的goroutine中被处理。请求处理器通常启动额外的goroutines去访问后端(例如数据库和RPC服务)。基于请求进行工作的goroutines通常需要获取请求的特殊值,例如最终的用户身份、授权令牌、和请求的最后期限。当一个请求被取消或者超时,所有给予请求进行工作的goroutines应该立刻退出,以便于系统能够回收任何它们使用的资源。

在Google中,我们开发了一个context包,以便于更容易的传递请求范围的值、取消信号、和最终的读取API边界的期限,涉及处理请求中的所有goroutines。这个包是公开可用的,被称为context。这篇文章将详细描述如何使用这个包,并提供完成的工作示例。

二、Context

context包的核心代码是Context类型:

// 一个Context懈怠了终止日期、取消信号、和请求范围的值,读取API的边界。
// 它的方法对于多个goroutines同时使用是安全的。
type Context interface{// Done方法,返回一个通道。当Context被取消或者超时的时候,这个通道将被关闭。Done() <-chan struct{}// Err 用于表明为什么Context是被取消。通常是由于Done的通道被关闭Err() error// Deadline 当无论什么原因,这个context被取消的时候,返回一个时间,Deadline() (deadline time.Time, ok bool)// Value 返回与key对应的值,如果没有就返回nilValue(key interface{}) interface{}
}

Done方法返回一个通道,这个通道给那些代表Context运行函数的取消信号:当通道被关闭,当通道关闭,这些函数应该立刻放弃它们的工作并返回。Err函数返回一个错误,表明为什么Context 是被取消。在管道和消除这篇文件中更详细的探讨了Done 通道的完整用法。

一个Context没有一个Cancel方法,和Done通道仅用于接收的原因相同:函数通常是接收到一个取消信号,而不是发送一个信号。尤其是,当一个父操作为子操作启动goroutines,这些子操作不应该能够去取消父操作。相反,WithCancel函数(在下面描述)提供了一个方法用于取消一个新的Context值。

一个Context被多个goroutine同时使用时安全的。代码能够传统同一个Context给任何数量的goroutines,并取消Context以向所有goroutines发出信号。

Deadline方法允许函数去确定是否它们应该都开始工作;如果剩余的时间太少,它可能是没有价值的。代码也可以使用最后期限给I/O操作设置超时时间。

Value允许一个Context可以携带请求范围的值。这个数据对多个goroutines同时使用必须是安全的。

三、context的衍生

context包提供了一个函数用于从已经存在的Contexts里衍生新的Context值。这些值形成了树:当一个Context被取消,所有从它衍生出来的Context也将被取消。

Background是任何Context树的根,它永远不会被取消:

/// Background 返回一个空的context。它绝不会被取消,没有最后期限,不带值。
//  Background 通常在main、init、test中使用,作为请求顶层的Context。
func Background() Context

WithCancelWithTimeout返回衍生的Context值。它能比它父Context更早的取消。

关联一个传入请求的Context,当请求处理返回的时候,它通常能够被取消。

当使用多个副本的时候,WithCancel对于·取消冗余的请求也很有用。

WithTimeout对于设置后台服务请求的截止日期很有用。

// WithCancel 返回一个父Context的拷贝,它的Done通道在父级关闭时立即关闭。
// Done 完成关闭或取消
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
// 一个CancelFunc 取消一个Context
type CancelFunc func()// WithTimeout 返回一个父级的副本,它的Done 通道在父级关闭时立即关闭。
// 关闭 Done、调用取消或超时。
// 新Context的最后期限,是现在+超时时间 和 父的截止日期(如果有的话)中较早的一个。
// 如果计时器仍在运行,取消函数将释放其资源。
func WithTimeout(parent Context, timeout time.Duration) (context, CancelFunc)

WithContext 提供了一个方法,去将请求范围的值和Context进行关联。

// WithValue 返回一个父Context的副本, 它的Value方法返回key对应的val。
func WithValue(parent Context, key interface{}, value interface{}) Context 

最好查看如何使用context包的方法是通过工作示例。

四、示例:Google Web Search

我们的示例是一个HTTP服务,它处理像/search?q=golang&timeout=1s这样的URL,通过转发"golang" 的查询,到Google Web Search API并展示结果。这个timeout参数告诉服务端在一段时间后取消请求。

代码被分到三个包中:

  • server 提供main函数,并处理/search请求;
  • userip 提供用于从请求中提取用户ip地址的函数,并将它和Context进行关联;
  • google 提供查询函数用于发送请求到 Google;

4.1 server程序

server程序处理像/search?q=golang的请求,通过提供前几个对golang在Google上的查询结果。它注册handleSearch来处理/search端点。这个处理创建了一个初始的Context称之为ctx,当处理返回的时候,安排它取消。如果请求包含timeoutURL参数,当超时时间通过Context将自动被取消:

func main() {// 注册 handleSearch 来处理 /search 端点http.HandleFunc("/search", handleSearch)
}func handleSearch(w http.ResponseWriter, req *http.Request) {// ctx 是 这个处理器的 Context。// 调用 cancel 关闭ctx.Done 的通道。这是对这个请求的取消信号,被处理器启动。var (ctx    context.Contextcancel context.CancelFunc)// 获取超时时间timeout, err := time.ParseDuration(req.FormValue("timeout"))if err == nil {//  请求有超时时间,因此创建一个context,当超时时间到期后它将自动取消ctx, cancel = context.WithTimeout(context.Background(), timeout)} else {ctx, cancel = context.WithCancel(context.Background())}// handleSearch返回之后,立刻取消ctxdefer cancel()

处理器从请求中提取查询,并通过调用userip包提取客户端的IP地址。客户端的IP地址对后端是需要的,因此handleSearch将它绑定到ctx上:

	// 检查查询请求query := req.FormValue("q")if query == "" {http.Error(w, "no query", http.StatusBadRequest)return}userIP, err := userip.FromRequest(req)if err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}ctx = userip.NewContext(ctx, userIP)

handle调用google.Search方法,带有ctx和query:

	// 运行Google 搜索,并打印结果start := time.Now()results, err := google.Search(ctx, query)elapsed := time.Since(start)

如果查询成功,处理器渲染结果

	if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}if err := resultsTemplate.Execute(w, struct {Results          google.ResultsTimeout, Elapsed time.Duration}{Results: results,Timeout: timeout,Elapsed: elapsed,}); err != nil {log.Print(err)return}

4.2 userip 包

userip包提供了用于从请求中提取用户ip地址的函数,并将它关联到Context中。一个Context提供了键-值对的映射,在这里键和值都是interface{}类型。键的类型必须支持判等操作,值在被多个goroutine同时使用多时候必须是安全的。像userip包,隐藏了这个映射的细节,并提供了抢类型用于读取一个特定的Context值。

为了避免键的冲突,userip定义了一个不对外开放的类型key,并使用这个类型的值作为context的键。

// 密钥类型未导出以防止与其他包中定义的上下文密钥发生冲突。
type key int// userIPKey 是一个context key,用于用户的IP地址。它的零值是随意定的。
// 如果这个包定义了其它的context key。它们应该是不同的数值。
const userIPKey key = 0

FromRequest从一个http.Request中提取一个userIP:

func FromRequest(req *http.Request) (net.IP, error) {ip, _, err := net.SplitHostPort(req.RemoteAddr)if err != nil {return nil, fmt.Errorf("userip: %q is not IP:port", req.RemoteAddr)}

NewContext返回一个新的Context,携带了一个提供的userIP值。

// 如果ip地址存在, FromContext 从ctx中提取用户的ip地址,
func FromContext(ctx context.Context) (net.IP, bool) {// 如果 ctx 没有针对key的值,ctx.Value 将返回 nil// net.IP 类型的断言 将对 nil 返回 ok=falseuserIP, ok := ctx.Value(userIPKey).(net.IP)return userIP, ok
}

4.3 google 包

google.Search函数创建一个HTTP请求给Google Web Search API,并解析JSON编码的结果。它接受一个Context参数,在请求被处理期间,如果ctx.Done被关闭,它将立即返回。

Google Web Search API请求,包含了查询请求,并使用IP作为请求参数。

// Search 发送查询到 Google 搜索,并返回结果
func Search(ctx context.Context, query string) (Results, error) {// 准备Google 搜索 API 请求req, err := http.NewRequest("GET", "https://ajax.googleapis.com/ajax/services/search/web?v=1.0", nil)if err != nil {return nil, err}q := req.URL.Query()q.Set("q", query)// 如果 ctx 懈怠了用户的IP地址,将它转发给服务器。// Google APIs 使用用户的IP地址来区分服务器发起的请求和最终用户的请求if userIP, ok := userip.FromContext(ctx); ok {q.Set("userip", userIP.String())}req.URL.RawQuery = q.Encode()

Search使用一个有用的函数,httpDo,用于发出http请求,并在请求或响应在处理期间,如果ctx.Done 被关闭,那么就取消它们。Search将一个闭包传递给httpDo,用于处理http响应。

	// 发出HTTP请求,并处理响应。// 如果 ctx.Done 是被取消, httpDo 函数将取消请求。var results Resultserr = httpDo(ctx, req, func(resp *http.Response, err error) error {if err != nil {return err}defer resp.Body.Close()// 解析JSON格式的查询结果// https://developers.google.com/web-search/docs/#fonjevar data struct {ResponseData struct {Results []struct {TitleNoFormatting stringURL               string}}}if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {return err}for _, res := range data.ResponseData.Results {results = append(results, Result{Title: res.TitleNoFormatting, URL: res.URL})}return nil})// httpDo 等待我们提供的闭包返回,所以在这里读取结果是安全的。return results, err

httpDo 函数返回http请求,并在一个新的goroutine中处理它的响应。在goroutine离开之前,如果ctx.Done被关闭,它将取消请求。

// httpDo 发起 HTTP 请求, 并使用响应调用 f 。
//  如果 ctx.Done 在请求或f函数运行期间被关闭,httpDo取消那个请求,等待f离开,并返回ctx.Err。
// 否则 返回 f 的 error
func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {// 在一个goroutine中 运行HTTP请求, 并传递响应给 fc := make(chan error, 1)req = req.WithContext(ctx)go func() { c <- f(http.DefaultClient.Do(req)) }()select {case <-ctx.Done():<-c // 为了等待f 函数返回return ctx.Err()case err := <-c:return err}
}

五、使用context包中程序实体实现sync.WaitGroup同样的功能

(1)使用sync.WaitGroup实现一对多goroutine协作流程多同步工具

package mainimport ("fmt""sync""sync/atomic"
)func main() {coordinateWithWaitGroup()
}func coordinateWithWaitGroup() {total := 12stride := 3var num int32fmt.Printf("The number: %d [with sync.WaitGroup]\n", num)var wg sync.WaitGroupfor i := 1; i <= total; i += stride {wg.Add(stride)for j := 0; j < stride; j++ {go addNum(&num, i+j, wg.Done)}wg.Wait()}
}func addNum(numP *int32, id int, deferFunc func()) {defer func() {deferFunc()}()for i := 0; ; i++ {currNum := atomic.LoadInt32(numP)newNum := currNum + 1if atomic.CompareAndSwapInt32(numP, currNum, newNum) {fmt.Printf("The number: %d [%d-%d]\n", newNum, id, i)break} else {fmt.Printf("The CAS option failed. [%d-%d]\n", id, i)}}
}

(2)使用context包中程序实体来实现

func coordinateWithContext() {total := 12var num int32fmt.Printf("The number: %d [with context.Context]\n", num)cxt, cancelFunc := context.WithCancel(context.Background())for i := 1; i <= total; i++ {go addNum(&num, i, func() {// 如果所有的addNum函数都执行完毕,那么就立即分发子任务的goroutine// 这里分发子任务的goroutine,就是执行 coordinateWithContext 函数的goroutine.if atomic.LoadInt32(&num) == int32(total) {// <-cxt.Done() 针对该函数返回的通道进行接收操作。// cancelFunc() 函数被调用,针对该通道的接收会马上结束。// 所以,这样做就可以实现“等待所有的addNum函数都执行完毕”的功能cancelFunc()}})}<-cxt.Done()fmt.Println("end.")
}
$ go run demo01.go
The number: 0 [with context.Context]
The number: 1 [12-0]
The number: 3 [6-0]
The number: 4 [7-0]
The number: 5 [8-0]
The number: 6 [9-0]
The number: 2 [5-0]
The number: 8 [10-0]
The number: 10 [11-0]
The number: 11 [1-0]
The number: 9 [3-0]
The number: 7 [2-0]
end.

执行发现,有时候结果并不对。

六、Context的特点

(1)Context介绍:上下文、树、根节点

Context类型是一种非常通用的同步工具,它的值不但可以任意扩散,还可以被用来传递额外的信息和信号。

Context类型可以提供一类代表上下文的值。此类值是并发安全的,也就是说它可以被传播给多个goroutine。

Context类型的值可以繁衍,这意味着可以通过一个Context值产生任意个子值。这些子值可以携带其父值的属性和数据,也可以响应我们通过父值传递的信号。

所有的Context值共同构成了一颗代表上下文全貌的树形结构。这棵树的树根(或称上下文的根节点)是一个已经在context包中预定义好的Context值,它是全局唯一的。通过context.Background函数可以取到它。

上下文根节点仅仅是一个最基本的支点,它不提供任何额外的功能。也就是说它既不可以被撤销,也不能携带任何数据。

(2)四个延伸Context值的函数

在context包中,包含四个用于繁衍Context值的函数,即WithCancel 、WithDeadline、WithTimeout、WithValue。

  • 四个函数的第一个参数的类型都是context.Context,名称都为parent。

    顾名思义,这个位置上的参数对应的都是它们将会产生的Context 值的父值。

  • WithCancel用于产生一个可撤销的parent的子值;

    通过调用该函数,可以得到一个衍生自上下文根节点的Context值,和一个用于发送撤销信号的函数。

    cxt, cancelFunc := context.WithCancel(context.Background())
    
  • WithDeadlineWithTimeout函数都是用来产生一个会定时撤销的parent的子值。

  • WithValue函数可以用来产生一个会携带额外数据的parent的子值。

(3)理解context包中“可撤销”和“撤销一个context”

在Context接口中,有两个与撤销息息相关的方法:

  • Done方法会返回一个元素类型为struct{}的接收通道。(让使用方感知撤销信号)

    这个接收通道的用途并不是传递元素值,而是让调用方法感知“撤销”当前Context值的那个信号。

    一旦当前的Contex值被撤销,这里的接收通道会立刻关闭。对于一个未包含任何元素值的通道来说,它的关闭会使任何针对它的接收操作立即结束。

  • Err方法。让使用方得到撤销的具体原因。

    Context的Err方法的结果是error类型,并且其值值可能等于context.Canceled变量的值,或者context.DeadlineExceeded 变量的值。

    context.Canceled 表示手动撤销;context.DeadlineExceeded 表示由于给定的过期时间已到,而导致的撤销。

对“撤销“和”可撤销“对理解:

  • 如果把”撤销“当作名词理解:指的是用来表达“撤销”状态的信号;
  • 如果把“撤销”当作动词理解:指的是对撤销信号的表达;
  • “可撤销”:指的是具有传达这种撤销信号的能力;

理解context.WithCancel

  • 通过调用context.WithCancel可以产生一个可撤销的Context值,还会获得一个用于触发撤销信号的函数。

  • 通过调用这个用于触发撤销信号的函数, 撤销信号会被传达给这个Context值,并由它的Done方法的结果值(一个接收通道)表达出来;

  • 撤销函数只负责触发信号,而对应的可撤销的Context值也只负责传达信号。它们都不会去管后面具体的“撤销”操作。

    实际上,我们的代码在感知到撤销操作以后,可以任意的操作,Context对此并没有任何的约束。

(4)撤销信号在上下文树中的传播

在contex包中,包含四个用于繁衍Context值的函数,其中WithCancelWithDeadlineWithTimeout都是被用于基于给定的Context值产生可撤销的子值的。

context.WithValue函数得到的Context值可不撤销,撤销信号在被传播时,若遇到它们则会直接跨过,并试图将信号直接传给它们的子值。

context 包的WithCancel函数在被调用后会产生两个结果值,第一个结果值就是那个可撤销的Context值,而第二个则是用于触发撤销信号的函数。

撤销函数被调用之后,对应的Context值会先关闭它内部的接收通道,也就是它的Done方法会返回的那个通道。然后,它会向它的所有子值(或者说子节点)传达撤销信号。这些子值会如法炮制,把撤销信号继续传播下去。最后这个Context值会断开它与其父值之间的关联。

通过调用context包中的WithDealline函数,或者WithTimeout函数生成的Context值也是可撤销的。它们不但可以被手动撤销,还会依据在生成时被给定的过期时间,自动地进行撤销。

这里的定时撤销,是借助内部的计时器来做。

当过期时间到达时,WithDeadlineWithTimeout这两个Context值当行为与Context值被手动撤销时的行为几乎是一致的。只不过WithDeadlineWithTimeout会在最后停止并释放掉其内部的计时器。

(5)通过Context携带数据

WithValue函数在产生新的Context值的时候需要三个参数:父值、键、值。

与字典对于键的约束类似,这里键的类型必须是可判等的。原因很简单,我们从中获取数据的时候,它需要根据给定的键来查找对应的值。只不过,这种Context值并不是用字典来存储键和值的,只是简单的存储在响应的字段中。

Context类型的Value方法就是用来获取数据的。在我们调用含数据的Context值的Value方法时,它会先判断给定的键,是否与当前值中存储的键相等。如果相等就把该值中的存储的值直接返回,否则就到父值中继续寻找。如果父值中仍然未存储相等的键,那么该方法就会沿着上下文根节点的方向一路查找下去。

注意,除了含数据的Context值以外,其它几种Context值都无法携带数据。因此,Context值的Value方法在沿路查找的时候,会直接跨过那几种值。

Context接口并没有提供改变数据的方法。因此,在通常情况下,我们只能通过在上下文树中添加含数据的Context值来存储新的数据,或者通过撤销此种值的父值丢弃掉相应的数据。如果你存储在这里的数据可以从外部改变,那么必须自行保证安全。

相关文章:

GO的并发模式Context

GO的并发模式Context 文章目录GO的并发模式Context一、介绍二、Context三、context的衍生四、示例&#xff1a;Google Web Search4.1 server程序4.2 userip 包4.3 google 包五、使用context包中程序实体实现sync.WaitGroup同样的功能&#xff08;1&#xff09;使用sync.WaitGro…...

《Redis实战篇》六、秒杀优化

6、秒杀优化 6.0 压力测试 目的&#xff1a;测试1000个用户抢购优惠券时秒杀功能的并发性能~ ①数据库中创建1000用户 这里推荐使用开源工具&#xff1a;https://www.sqlfather.com/ &#xff0c;导入以下配置即可一键生成模拟数据 {"dbName":"hmdp",…...

《C++ Primer Plus》第16章:string类和标准模板库(11)

其他库 C 还提供了其他一些类库&#xff0c;它们比本章讨论前面的例子更为专用。例如&#xff0c;头文件 complex 为复数提供了类模板 complex&#xff0c;包含用于 float、long 和 long double 的具体化。这个类提供了标准的复数运算及能够处理复数的标准函数。C11 新增的头文…...

声明和定义

前言 很多编程语言的语法中都有关于声明和定义的概念&#xff0c;这种概念一般会应用于函数或变量的创建和使用中&#xff0c;但是为什么要这么做&#xff1f; 以C语言为例&#xff0c;一些书籍或教程会要求读者在程序文件开头写上函数和变量的声明&#xff0c;然后再在后面对…...

Python获取最小路径,查找元素在list中的坐标

# codingutf-8__author__ Jeff.xiedef t(li):pass获取最小路径def minPathSum(grid):if not grid:return 0m len(grid) #m列n len(grid[0]) #n行print(grid[0])print("m: ",m)print("n: ",n)#创建一个二维数组dp [[0]*n for _ in range(m)]print(dp) #这…...

数据采集协同架构,集成马扎克、西门子、海德汉、广数、凯恩帝、三菱、海德汉、兄弟、哈斯、宝元、新代、发那科、华中各类数控以及各类PLC数据采集软件

文章目录 前言一、采集协同架构是什么&#xff1f;可以做什么&#xff08;数控、PLC配置采集&#xff09;&#xff1f;二、使用步骤 1.打开软件&#xff0c;配置MQTT或者数据库&#xff08;支持sqlserver、mysql等&#xff09;存储转发消息规则2.配置数控系统所采集的参数、转…...

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容 在做PCB设计的时候,在1MM中心间距的BGA背面放置电容,是非常常见的设计,如何快速把电容等距放在BGA下方,除了借助辅助工具外,在Allegro升级到了172版本的时候,可以借助本身自带的功能实现快速放置,以下图…...

一种简单的统计pytorch模型参数量的方法

nelememt()函数Tensor.nelement()->引自Tensor.numel()->引自torch.numel(input)三者的作用是相同的Returns the total number of elements in the inputtensor.返回当前tensor的元素数量利用上面的函数刚好可以统计模型的参数数量parameters()函数Module.parameters(rec…...

【PyTorch】教程:对抗学习实例生成

ADVERSARIAL EXAMPLE GENERATION 研究推动 ML 模型变得更快、更准、更高效。设计和模型的安全性和鲁棒性经常被忽视&#xff0c;尤其是面对那些想愚弄模型故意对抗时。 本教程将提供您对 ML 模型的安全漏洞的认识&#xff0c;并将深入了解对抗性机器学习这一热门话题。在图像…...

中国区使用Open AI账号试用Chat GPT指南

最近推出强大的ChatGPT功能&#xff0c;各大程序员使用后发出感叹&#xff1a;程序员要失业了 不过在国内并不支持OpenAI账号注册&#xff0c;多数会提示&#xff1a; OpenAI’s services are not available in your country. 经过一番搜索后&#xff0c;发现如下方案可以完…...

STM32开发(9)----CubeMX配置外部中断

CubeMX配置外部中断前言一、什么是中断1.STM32中断架构体系2.外部中断/事件控制器&#xff08;EXTI&#xff09;3.嵌套向量中断控制器&#xff08;NIVC&#xff09;二、实验过程1.CubeMX配置2.代码实现3.硬件连接4.实验结果总结前言 本章介绍使用STM32CubeMX对引脚的外部中断进…...

Nextjs了解内容

目录Next.jsnext.js的实现1&#xff0c;nextjs初始化2&#xff0c; 项目结构3&#xff0c; 数据注入getInitialPropsgetServerSidePropsgetStaticProps客户端注入3&#xff0c;CSS Modules4&#xff0c;layout组件5&#xff0c;文件式路由6&#xff0c;BFF层的文件式路由7&…...

从事功能测试1年,裸辞1个月,找不到工作的“我”怎么办?

做功能测试一年多了裸辞职一个月了&#xff0c;大部分公司都要求有自动化测试经验&#xff0c;可是哪来的自动化测试呢&#xff1f; 我要是简历上写了吧又有欺诈性&#xff0c;不写他们给的招聘又要自动化优先&#xff0c;将项目带向自动化不是一个容易的事情&#xff0c;很多…...

机器学习基本原理总结

本文大部分内容参考《深度学习》书籍&#xff0c;从中抽取重要的知识点&#xff0c;并对部分概念和原理加以自己的总结&#xff0c;适合当作原书的补充资料阅读&#xff0c;也可当作快速阅览机器学习原理基础知识的参考资料。 前言 深度学习是机器学习的一个特定分支。我们要想…...

JVET-AC0315:用于色度帧内预测的跨分量Merge模式

ECM采用了许多跨分量的预测&#xff08;Cross-componentprediction&#xff0c;CCP&#xff09;模式&#xff0c;包括跨分量包括跨分量线性模型&#xff08;CCLM&#xff09;、卷积跨分量模型&#xff08;CCCM&#xff09;和梯度线性模型&#xff08;GLM&#xff09;&#xff0…...

Session与Cookie的区别(二)

脸盲症的困扰 小明身为杂货店的店长兼唯一的店员&#xff0c;所有大小事都是他一个人在处理。传统杂货店跟便利商店最大的差别在哪里&#xff1f;在于人情味。 就像是你去菜市场买菜的时候会被说帅哥或美女&#xff0c;或者是去买早餐的时候老板会问你&#xff1a;「一样&#…...

疫情开发,软件测试行情趋势是怎么样的?

如果说&#xff0c;2022年对于全世界来说&#xff0c;都是一场极大的挑战的话&#xff1b;那么&#xff0c;2023年绝对是机遇多多的一年。众所周知&#xff0c;随着疫情在全球范围内逐步得到控制&#xff0c;无论是国际还是国内的环境&#xff0c;都会呈现逐步回升的趋势&#…...

Java中间件描述与使用,面试可以用

myCat 用于切分mysql数据库&#xff08;为什么要切分&#xff1a;当数据量过大时&#xff0c;mysql查询效率变低&#xff09; ActiveMQ 订阅&#xff0c;消息推送 swagger 前后端分离&#xff0c;后台接口调式 dubbo 阿里的面向服务RPC框架&#xff0c;为什么要面向服务&#x…...

[OpenMMLab]AI实战营第七节课

语义分割代码实战教学 HRNet 高分辨率神经网络 安装配置 # 选择分支 git branch -a git switch 3.x # 配置环境 conda create -n mmsegmentation python3.8 conda activate mmsegmentation pip install torch1.11.0cu113 torchvision0.12.0cu113 torchaudio0.11.0 --extra-i…...

面向对象的设计模式

"万丈高楼平地起&#xff0c;7种模式打地基"&#xff0c;模式是一种规范&#xff0c;我们应该站在巨人的肩膀上越看越远&#xff0c;接下来&#xff0c;让我们去仔细了解了解面向对象的7种设计模式7种设计模式设计原则的核心思想&#xff1a;找出应用中可能需要变化之…...

里氏替换原则|SOLID as a rock

文章目录 意图动机:违反里氏替换原则解决方案:C++中里氏替换原则的例子里氏替换原则的优点1、可兼容性2、类型安全3、可维护性在C++中用好LSP的标准费几句话本文是关于 SOLID as Rock 设计原则系列的五部分中的第三部分。 SOLID 设计原则侧重于开发 易于维护、可重用和可扩展…...

【C++】右左法则,指针、函数与数组

右左法则——判断复杂的声明对于一个复杂的声明&#xff0c;可以用右左法则判断它是个什么东西&#xff1a;1.先找到变量名称2.从变量名往右看一个部分&#xff0c;再看变量名左边的一个部分3.有小括号先看小括号里面的&#xff0c;一层一层往外看4.先看到的东西优先级大&#…...

打通数据价值链,百分点数据科学基础平台实现数据到决策的价值转换 | 爱分析调研

随着企业数据规模的大幅增长&#xff0c;如何利用数据、充分挖掘数据价值&#xff0c;服务于企业经营管理成为当下企业数字化转型的关键。 如何挖掘数据价值&#xff1f;企业需要一步步完成数据价值链条的多个环节&#xff0c;如数据集成、数据治理、数据建模、数据分析、数据…...

C++之多态【详细总结】

前言 想必大家都知道面向对象的三大特征&#xff1a;封装&#xff0c;继承&#xff0c;多态。封装的本质是&#xff1a;对外暴露必要的接口&#xff0c;但内部的具体实现细节和部分的核心接口对外是不可见的&#xff0c;仅对外开放必要功能性接口。继承的本质是为了复用&#x…...

ThingsBoard-RPC

1、使用 RPC 功能 ThingsBoard 允许您将远程过程调用 (RPC) 从服务器端应用程序发送到设备,反之亦然。基本上,此功能允许您向/从设备发送命令并接收命令执行的结果。本指南涵盖 ThingsBoard RPC 功能。阅读本指南后,您将熟悉以下主题: RPC 类型;基本 RPC 用例;RPC 客户端…...

java分治算法

分治算法介绍 分治法是一种很重要的算法。字面上的解释是“分而治之”&#xff0c;就是把一个复杂的问题分成两个或更多的相同或 相似的子问题&#xff0c;再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解&#xff0c;原问题的解即子问题 的解的合并。这个技…...

【Flutter】【Unity】使用 Flutter + Unity 构建(AR 体验工具包)

使用 Flutter Unity 构建&#xff08;AR 体验工具包&#xff09;【翻译】 原文&#xff1a;https://medium.com/potato/building-with-flutter-unity-ar-experience-toolkit-6aaf17dbb725 由于屡获殊荣的独立动画工作室 Aardman 与讲故事的风险投资公司 Fictioneers&#x…...

MC0108白给-MC0109新河妇荡杯

MC0108白给 小码哥和小码妹在玩一个游戏&#xff0c;初始小码哥拥有 x的金钱&#xff0c;小码妹拥有 y的金钱。 虽然他们不在同一个队伍中&#xff0c;但他们仍然可以通过游戏的货币系统进行交易&#xff0c;通过互相帮助以达到共赢的目的。具体来说&#xff0c;在每一回合&a…...

求职(JAVA程序员的面试自我介绍)

背景 在找工作的过程中&#xff0c;在面试的环节&#xff0c;大多数面试官首先都会叫你自我介绍一下。一般是3到5分钟内。不过经过我面试的无数的公司还有曾经也面试过大多数的求职者。国内很多的程序员面试都极其不专业。有一种很随心所欲的感觉。所以经常遇到求职者吐槽遇到了…...

金三银四季节前端面试题复习来了

vue3和vue2的区别有哪些 Diff算法的改进Tree Sharing优化主要的API双向绑定改为es6的proxy原生支持tscomposition API移除令人头疼的this 说说CSS选择器以及这些选择器的优先级 !important 内联样式&#xff08;1000&#xff09; ID选择器&#xff08;0100&#xff09; 类选…...