当前位置:   article > 正文

最全(九)Go------捕获异常(defer,panic,revover)单元测试,2024年最新终获offer_go 测试 defer 100次

go 测试 defer 100次

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

1.文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码

2.你必须import testing这个包

3.所有的测试用例函数必须是Test开头

4.测试用例会按照源代码中写的顺序依次执行

5.测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态

6.测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,

但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。

7.函数中通过调用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。

练习


1. 数字阶乘


一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。

package main

import “fmt”

func factorial(i int) int {

if i <= 1 {

return 1

}

return i * factorial(i-1)

}

func main() {

var i int = 7

fmt.Printf(“Factorial of %d is %d\n”, i, factorial(i))

}

//输出结果:

Factorial of 7 is 5040

2. 斐波那契数列(Fibonacci)


这个数列从第3项开始,每一项都等于前两项之和。

package main

import “fmt”

func fibonaci(i int) int {

if i == 0 {

return 0

}

if i == 1 {

return 1

}

return fibonaci(i-1) + fibonaci(i-2)

}

func main() {

var i int

for i = 0; i < 10; i++ {

fmt.Printf(“%d\n”, fibonaci(i))

}

}

//输出结果:

0

1

1

2

3

5

8

13

21

34

三. Go defer 延迟

=================================================================================

程序开发中经常要创建资源(数据库初始化连接,文件句柄,锁等),在程序执行完毕都必须得释放资源,Go提供了defer(延时机制)更方便、更及时的释放资源。

  1. 内置关键字defer 用于延迟调用

  2. defer在return前执行,常用于资源释放

  3. 多个defer按 先进后出 的机制执行

  4. defer语句的变量,在defer声明时定义

  5. 显式 return 返回前,会先修改命名返回参数

defer用途

  1. 关闭文件句柄

  2. 资源释放

  3. 数据库连接释放

defer 是先进后出

后面的语句会依赖前面的资源,因此如果先前面的资源先释放了,后面的语句就没法执行了。

package main

import “fmt”

func main() {

var whatever [5]struct{}

for i := range whatever {

defer fmt.Println(i)

}

}

//结果

4

3

2

1

0

package main

import (

“fmt”

)

func testDefer1() {

//defer机制 先入后出,如同羽毛球筒

defer fmt.Println(“hello v1”) //顺序5

defer fmt.Println(“hello v2”) //顺序4

defer fmt.Println(“hello v3”) //顺序3

fmt.Println(“aaaaa”) // 顺序1

fmt.Println(“bbbb”) //顺序2

}

func testDefer2() {

for i := 0; i < 5; i++ {

//每次循环,defer将后入的语句压到defer栈

//依旧先入后出

defer fmt.Printf(“i=%d\n”, i)

}

fmt.Printf(“running\n”) //顺序1

fmt.Printf(“return\n”) //顺序2

}

func testDefer3() {

var i int = 0

//defer是声明时定义好的,之后再修改无效,因此i=0

defer fmt.Printf(“defer i=%d\n”, i)

i = 1000

fmt.Printf(“i=%d\n”, i)

}

func main() {

//testDefer1()

//testDefer2()

testDefer3()

}

1. 遇到了闭包


如果defer遇到了闭包

package main

import “fmt”

func main() {

var whatever [3]struct{}

for i := range whatever {

defer func() { fmt.Println(i) }()

}

}

//相当于

i结果最后为2,因为闭包原因,所以i最终为2

//结果,

2

2

2

package main

import “fmt”

type Test struct {

name string

}

func (t *Test) Close() {

fmt.Println(t.name, " closed")

}

func main() {

ts := []Test{{“a”}, {“b”}, {“c”}}

for _, t := range ts {

defer t.Close()

}

}

//预计的输出c b a,而是输出c c c

//结果

c closed

c closed

c closed

将defer t.Close()改为defer Close(t)

输出结果:

c closed

b closed

a closed

省去函数,可以用t.Close()

package main

import “fmt”

type Test struct {

name string

}

func (t *Test) Close() {

fmt.Println(t.name, " closed")

}

func main() {

ts := []Test{{“a”}, {“b”}, {“c”}}

for _, t := range ts {

t2 := t

defer t2.Close()

}

}

c closed

c closed

c closed

结论:

defer后面的语句在执行的时候,函数调用的参数会被保存起来,但是不执行。也就是复制了一份。但是并没有说struct这里的this指针如何处理,通过这个例子可以看出go语言并没有把这个明确写出来的this指针当作参数来看待。

多个 defer 注册,按 FILO 次序执行 ( 先进后出 )。

异常也会输出

package main

func test(x int) {

defer println(“a”)

defer println(“b”)

defer func() {

println(100 / x) // div0 异常未被捕获,逐步往外传递,最后终止进程。

}()

defer println(“c”)

}

func main() {

test(0)

}

//结果

c

b

a

panic: runtime error: integer divide by zero

*延迟调用参数在注册时求值或复制,可用指针或闭包 “延迟” 读取。

package main

func test() {

x, y := 10, 20

defer func(i int) {

println(“defer:”, i, y) // y 闭包引用

}(x) // x 被复制

x += 10

y += 100

println(“x =”, x, “y =”, y)

}

func main() {

test()

}

输出结果:

x = 20 y = 120

defer: 10 120

*滥用 defer 可能会导致性能问题,例如:在一个 “大循环” 里。

package main

import (

“fmt”

“sync”

“time”

)

var lock sync.Mutex

func test() {

lock.Lock()

lock.Unlock()

}

func testdefer() {

lock.Lock()

defer lock.Unlock()

}

func main() {

func() {

t1 := time.Now()

for i := 0; i < 10000; i++ {

test()

}

elapsed := time.Since(t1)

fmt.Println("test elapsed: ", elapsed)

}()

func() {

t1 := time.Now()

for i := 0; i < 10000; i++ {

testdefer()

}

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

unc test() {

lock.Lock()

lock.Unlock()

}

func testdefer() {

lock.Lock()

defer lock.Unlock()

}

func main() {

func() {

t1 := time.Now()

for i := 0; i < 10000; i++ {

test()

}

elapsed := time.Since(t1)

fmt.Println("test elapsed: ", elapsed)

}()

func() {

t1 := time.Now()

for i := 0; i < 10000; i++ {

testdefer()

}

[外链图片转存中…(img-9J3q4oOt-1715566616639)]
[外链图片转存中…(img-94hdXjKD-1715566616640)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/1001022
推荐阅读
相关标签
  

闽ICP备14008679号