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

微网站访问量/seo综合查询工具下载

微网站访问量,seo综合查询工具下载,wordpress文章两端对齐,建网站要备案原文来自:https://golangbot.com/defer/ 什么是defer defer语句的作用:在有defer语句的函数结束之前调用另外一个函数。定义看起来很复杂,我们通过一个例子就很容易理解。 package mainimport ( "fmt" )func finished() { fmt…

原文来自:https://golangbot.com/defer/

什么是defer

defer语句的作用:在有defer语句的函数结束之前调用另外一个函数。定义看起来很复杂,我们通过一个例子就很容易理解。

package mainimport (  "fmt"
)func finished() {  fmt.Println("Finished finding largest")
}func largest(nums []int) {  defer finished()    fmt.Println("Started finding largest")max := nums[0]for _, v := range nums {if v > max {max = v}}fmt.Println("Largest number in", nums, "is", max)
}func main() {  nums := []int{78, 109, 2, 563, 300}largest(nums)
}

在playground运行

上述函数的功能是找出指定切片中的最大数。largest函数有一个int型切片作为参数,功能是打印输入切片中最大的数,函数第一行包含一个defer finished()语句。这意味着,函数finished()将在函数largest结束前被调用。运行程序结果如下:

Started finding largest  
Largest number in [78 109 2 563 300] is 563  
Finished finding largest  

largest 函数开始执行后,会打印上面的两行输出。而就在 largest将要返回的时候,又调用了我们的延迟函数(Deferred Function),打印出 Finished finding largest 的文本。

延迟方法(Defered methods)

defer 不仅限于函数的调用,调用方法也是合法的。我们写一个小程序来测试一下。

package mainimport (  "fmt"
)type person struct {  firstName stringlastName string
}func (p person) fullName() {  fmt.Printf("%s %s",p.firstName,p.lastName)
}func main() {  p := person {firstName: "John",lastName: "Smith",}defer p.fullName()fmt.Printf("Welcome ")  
}

在playground运行

在上面的例子中,我们在第 22 行延迟了一个方法调用。其他的代码很直观,这里不再解释。该程序输出:

Welcome John Smith  

实参取值(Arguments Evaluation)

在 Go 语言中,并非在调用延迟函数的时候才确定实参,而是当执行 defer 语句的时候,就会对延迟函数的实参进行求值。

我们通过一个例子来理解下:

package mainimport (  "fmt"
)func printA(a int) {  fmt.Println("value of a in deferred function", a)
}
func main() {  a := 5defer printA(a)a = 10fmt.Println("value of a before deferred function call", a)}

在playground运行

在上面的程序里的第 11 行,a 的初始值为 5。在第 12 行执行 defer 语句的时候,由于 a 等于 5,因此延迟函数 printA 的实参也等于 5。接着我们在第 13 行将 a 的值修改为 10。下一行会打印出 a 的值。该程序输出:

value of a before deferred function call 10  
value of a in deferred function 5  

从上面的输出,我们可以看出,在调用了 defer 语句后,虽然我们将 a 修改为 10,但调用延迟函数 printA(a)后,仍然打印的是 5。

defer栈

当一个函数多次调用defer语句,这些defer语句的调用放入到一个栈中,按照先进后出(LIFO)的顺序执行。

下面我们编写一个小程序,使用 defer 栈,将一个字符串逆序打印:

package mainimport (  "fmt"
)func main() {  name := "Naveen"fmt.Printf("Orignal String: %s\n", string(name))fmt.Printf("Reversed String: ")for _, v := range []rune(name) {defer fmt.Printf("%c", v)}
}

在playground运行

在上述程序中的第 11 行,for range 循环会遍历一个字符串,并在第 12 行调用了 defer fmt.Printf("%c", v)。这些延迟调用会添加到一个栈中,按照后进先出的顺序执行,因此,该字符串会逆序打印出来。该程序会输出:

Orignal String: Naveen  
Reversed String: neevaN  

defer的应用

到目前为止,我们看到的代码示例都是没有实用性的。这一届我们将学习一些defer的实际应用。

defer使用的情况:当一个函数执行与当前代码流无关。我们通过一个使用 WaitGroup 代码的示例来理解这句话的含义。我们首先会写一个没有使用 defer 的程序,然后我们会用 defer 来修改,看到 defer 带来的好处。

package mainimport (  "fmt""sync"
)type rect struct {  length intwidth  int
}func (r rect) area(wg *sync.WaitGroup) {  if r.length < 0 {fmt.Printf("rect %v's length should be greater than zero\n", r)wg.Done()return}if r.width < 0 {fmt.Printf("rect %v's width should be greater than zero\n", r)wg.Done()return}area := r.length * r.widthfmt.Printf("rect %v's area %d\n", r, area)wg.Done()
}func main() {  var wg sync.WaitGroupr1 := rect{-67, 89}r2 := rect{5, -67}r3 := rect{8, 9}rects := []rect{r1, r2, r3}for _, v := range rects {wg.Add(1)go v.area(&wg)}wg.Wait()fmt.Println("All go routines finished executing")
}

在playground运行

在上面的程序里,我们在第 8 行创建了 rect 结构体,并在第 13 行创建了 rect 的方法 area,计算出矩形的面积。area 检查了矩形的长宽是否小于零。如果矩形的长宽小于零,它会打印出对应的提示信息,而如果大于零,它会打印出矩形的面积。

main 函数创建了 3 个 rect 类型的变量:r1r2和 r3。在第 34 行,我们把这 3 个变量添加到了 rects 切片里。该切片接着使用 for range 循环遍历,把 area 方法作为一个并发的 Go 协程进行调用(第 37 行)。我们用 WaitGroup wg 来确保 main函数在其他协程执行完毕之后,才会结束执行。WaitGroup 作为参数传递给 area 方法后,在第 16 行、第 21 行和第 26 行通知 main 函数,表示现在协程已经完成所有任务。如果你仔细观察,会发现 wg.Done() 只在 area 函数返回的时候才会调用。wg.Done() 应该在 area 将要返回之前调用,并且与代码流的路径(Path)无关,因此我们可以只调用一次 defer,来有效地替换掉 wg.Done() 的多次调用。

我们来用 defer 来重写上面的代码。

在下面的代码中,我们移除了原先程序中的 3 个 wg.Done 的调用,而是用一个单独的 defer wg.Done() 来取代它(第 14 行)。这使得我们的代码更加简洁易懂。

package mainimport (  "fmt""sync"
)type rect struct {  length intwidth  int
}func (r rect) area(wg *sync.WaitGroup) {  defer wg.Done()if r.length < 0 {fmt.Printf("rect %v's length should be greater than zero\n", r)return}if r.width < 0 {fmt.Printf("rect %v's width should be greater than zero\n", r)return}area := r.length * r.widthfmt.Printf("rect %v's area %d\n", r, area)
}func main() {  var wg sync.WaitGroupr1 := rect{-67, 89}r2 := rect{5, -67}r3 := rect{8, 9}rects := []rect{r1, r2, r3}for _, v := range rects {wg.Add(1)go v.area(&wg)}wg.Wait()fmt.Println("All go routines finished executing")
}

在playground运行

程序执行结果:

rect {8 9}'s area 72  
rect {-67 89}'s length should be greater than zero  
rect {5 -67}'s width should be greater than zero  
All go routines finished executing 

在上面的程序中,使用 defer 还有一个好处。假设我们使用 if 条件语句,又给 area 方法添加了一条返回路径(Return Path)。如果没有使用 defer 来调用 wg.Done(),我们就得很小心了,确保在这条新添的返回路径里调用了 wg.Done()。由于现在我们延迟调用了 wg.Done(),因此无需再为这条新的返回路径添加 wg.Done() 了。

本节课程到此结束。祝您愉快。

ps:新手翻译,欢迎大家指正!

下一节 Golang教程第30节--错误处理

 

http://www.lbrq.cn/news/1321525.html

相关文章:

  • wordpress插件改名/平台优化是什么意思
  • 静态网站源码下载/今日头条10大新闻
  • python做网站难么/青海网站seo
  • 邢台做wap网站费用/抖音搜索引擎推广
  • 网络公司是做什么/怎么做优化
  • 毕设做网站需要买域名么/网站推广策略有哪些
  • 旅游网站的功能/高级搜索技巧
  • 网站编辑如何做/营销软文范文
  • 日本亲子游哪个网站做的好/百度指数下载
  • 做静态网站的软件/中文域名交易平台
  • wordpress网页设计步骤/国内做seo最好公司
  • 花卉网站建设项目策划书/seo搜索引擎优化实训报告
  • 广德县住房和城乡建设网站/如何做网站网页
  • wordpress本地运行速度慢/西安专业seo
  • 综合返利商城网站建设/软文案例
  • 通辽做网站制作/外包网络推广公司怎么选
  • 怀化汽车网站/百度网站快速优化
  • java怎么做网站多语言/鲜花网络营销推广方案
  • 江门找人做网站排名/搜索引擎优化包括哪些内容
  • 芜湖炎黄做的网站/秦洁婷seo博客
  • wordpress360收录插件/关键词排名优化系统
  • 个人网站 模版 后台管理系统/网络推广的渠道
  • 我的电脑做网站服务器吗/免费网页在线客服系统
  • 环球资源网站什么时候做的/互联网推广有哪些方式
  • 公司网站建设征稿令/中国科技新闻网
  • 西宁网站建设哪家好/独立站网站
  • 静态网站开发课程相关新闻/专业排名优化工具
  • 用html制作旅游网站/seo网站搭建是什么
  • 设计做任务的网站/cps广告是什么意思
  • 做网站怎么上词/广东病毒感染最新消息
  • 开箱即用的Next.js SSR企业级开发模板
  • 【LeetCode 热题 100】394. 字符串解码
  • 24黑马SpringCloud安装MybatisPlus插件相关问题解决
  • SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:日志管理(四)集成Spring Security
  • Python 程序设计讲义(45):组合数据类型——集合类型:集合的常用操作
  • 30道JS高频经典笔试题集合+详解(一)