Go Test测试教程

这篇具有很好参考价值的文章主要介绍了Go Test测试教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

go中测试既有类似有pytest中的功能测试,也有benchMark的基准测试,以及单元测试(Unit TestsUT).这里从单元测试UT引入本篇的话题,单元测试的重要性不言而喻,尤其在大型项目中跨团队合作时,无法mr合格的代码,很容易影响整个团队的交付进度和质量。或者会说直接debug,但是当你的代码是几千行的时候,这个时候debug似乎也比较累,那单元测试就能覆盖上述情况。

如何写好单元测试呢?

测试用例编写是基础。比如如何编写单个测试函数和单个测试方法,如何做基准测试,如何Mock数据等等,对于可测试的代码,高内聚,低耦合是软件工程的基本要求。同样对于测试而言,函数和方法写法不同,测试难度也是不一样的,参数少且类型单一,与其他函数耦合度较低这种函数更容易测试,其他的比如入参较多,且耦合多较高,是输入参数较多这种情况,结合正交法,等价类划分等设计方法,可以大大较少case设计的难度和复杂度,且能提升测试覆盖面。

这里概述一下go中支持的三种测试类型,分别是单元/功能测试性能(压力)测试覆盖率测试

接下来介绍使用Go的标准测试库 testing 进行单元测试

1.单元测试

go语言中推荐测试文件和源代码文件放置在一起,测试文件以_test.go结尾,这里可以和pytest进行类比,当前的packagecalculate.go文件,向测试calculate.go中有AddMul函数,应该新建一个calculate_test.go测试文件,所以习惯会将测试文件命名为功能文件_test.go的形式。
go 测试类,go,golang,单元测试,开发语言

1.1 入门示例

编写go test测试函数时,如下所示,输入test,自动联想
go 测试类,go,golang,单元测试,开发语言
单元测试文件可以有多个测试用例组成,每个测试用例的名称前缀必须是Test开头

func TestXxx( t \*testing.T ){  
    //......  
}

函数和单测的文件如下:

# calculate.go
package calculate

func Add(a,b int) int {
	return a+b
}

func Mult(a,b int) int {
	return a *b
}
# calculate_test.go
package calculate

import "testing"

func TestAdd(t *testing.T) {
	if ans := Add(2,3); ans != 5{
		t.Errorf("2+3 expected be 5,but %d got",ans)
	}

	if ans := Add(-10, -20); ans != -30 {
		t.Errorf("-10 + -20 expected be -30, but %d got", ans)
	}
}

go 测试类,go,golang,单元测试,开发语言
在goland终端执行go test

xxx@yyy calculate % ls
calculate.go            calculate_test.go       go.mod
xxx@yyy calculate % go test -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      calculate       0.137s

go test -v-v 参数会显示每个用例的测试结果。如果继续编写mul的测试函数.此时calculate_test.go中两个测试函数,如果想仅仅指定其中一个测试用例,比如TestMul,可以使用-run参数

 go test -run TestMul -v
=== RUN   TestMul
--- PASS: TestMul (0.00s)
PASS
ok      calculate       0.531s

go test <module name>/<package name> 用来运行某个 package 内的所有测试用例。

运行当前 package 内的用例:go test calcuatego test .
运行子 package 内的用例: go test calcuate/<package name>go test ./<package name>
如果想递归测试当前目录下的所有的 package:go test ./...go test calcuate/...

该参数还支持通配符*,和部分正则表达式,如^$

1.2 子测试

这里就不得不提到子测试,即所谓的Subtests,该功能是go语言内置的支持的功能,可以在一个测试用例中,根据测试场景使用t.Run创建不同的子测试用例:

func TestMul(t *testing.T) {
	//if ans := Mul(2,3); ans != 6{
	//	t.Errorf("2*3 expected be 6,but %d got",ans)
	//}
	t.Run("pos", func(t *testing.T) {
		if Mul(2, 3) != 6{
			t.Fatalf("2*3 expected be 6, but %d got", Mul(2, 3))
		}
	})
	t.Run("neg", func(t *testing.T) {
		if Mul(2, -3) != -6{
			t.Fatalf("2*-3 expected be 6, but %d got", Mul(2, -3))
		}
	})
}

除了使用命令之后,可以使用golang中的如下符号
go 测试类,go,golang,单元测试,开发语言
输出如下所示

/usr/local/Cellar/go/1.19.6/libexec/bin/go tool test2json -t /private/var/folders/cc/wn7xg4yx22d_qp96zw37rrl00000gp/T/___TestMul_in_calculate.test -test.v -test.paniconexit0 -test.run ^\QTestMul\E$
=== RUN   TestMul
=== RUN   TestMul/pos
=== RUN   TestMul/neg
--- PASS: TestMul (0.00s)
    --- PASS: TestMul/pos (0.00s)
    --- PASS: TestMul/neg (0.00s)
PASS

Process finished with the exit code 0

📢:之前的例子失败是使用的t.Error/t.Errorf,这里使用的是t.Fatal/Fatalf,区别在于前者遇到错误不会停止,还会继续执行其他的测试用例,后者遇到❎就会停止。
执行运行其中某个子测试

 calculate % go test -run TestMul/pos -v
=== RUN   TestMul
=== RUN   TestMul/pos
--- PASS: TestMul (0.00s)
    --- PASS: TestMul/pos (0.00s)
PASS
ok      calculate       1.002s

种类的Run()第一个参数是不是类似Pytest中的mark.tag标签,但是上面的写法发现冗余别较多,推荐使用如下的方法

func TestMul(t *testing.T) {
	//if ans := Mul(2,3); ans != 6{
	//	t.Errorf("2*3 expected be 6,but %d got",ans)
	//}
	//t.Run("pos", func(t *testing.T) {
	//	if Mul(2, 3) != 6{
	//		t.Fatalf("2*3 expected be 6, but %d got", Mul(2, 3))
	//	}
	//})
	//t.Run("neg", func(t *testing.T) {
	//	if Mul(2, -3) != -6{
	//		t.Fatalf("2*-3 expected be 6, but %d got", Mul(2, -3))
	//	}
	//})

	cases := []struct {
		Name           string
		A, B, Expected int
	}{
		{"pos", 2, 3, 6},
		{"neg", 2, -3, -6},
		{"zero", 0, 2, 0},
	}

	for _, c := range cases {
		t.Run(c.Name, func(t *testing.T) {
			if ans := Mul(c.A, c.B); ans != c.Expected {
				t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
			}
		})
	}
}

输出如下所示:

calculate % go test -run TestMul -v
=== RUN   TestMul
=== RUN   TestMul/pos
=== RUN   TestMul/neg
=== RUN   TestMul/zero
--- PASS: TestMul (0.00s)
    --- PASS: TestMul/pos (0.00s)
    --- PASS: TestMul/neg (0.00s)
    --- PASS: TestMul/zero (0.00s)
PASS
ok      calculate       0.343s

上面的用法和pytest中的@pytest.mark.parametrize(‘status’, [‘Pending’, ‘Running’, ‘Success’, ‘Failed’, ‘Timeout’])进行类比,所有用例的测试数据组织在切片cases中,借助于创建子测试,当然目前觉得pytest这样更方便些,go这样写的好处有:

  1. 新增用例非常简单,只需给 cases 新增一条测试数据即可。
  2. 测试代码可读性好,直观地能够看到每个子测试的参数和期待的返回值。
  3. 用例失败时,报错信息的格式比较统一,测试报告易于阅读。

如果数据量较大,或是一些二进制数据,推荐使用相对路径从文件中读取

所以编写测试用例可以抽象总结为以下几点:

  • 测试用例文件不会参与正常源码的编译,不会被包含到可执行文件中;
  • 测试用例的文件名必须以_test.go结尾;
  • 需要使用 import 导入 testing 包;
  • 测试函数的名称要以Test或Benchmark开头,后面可以跟任意字母组成的字符串,但第一个字母必须大写,例如 TestAbc(),一个测试用
  • 文件中可以包含多个测试函数;
  • 单元测试则以(t *testing.T)作为参数,性能测试以(t *testing.B)做为参数;
  • 测试用例文件使用go test命令来执行,源码中不需要 main() 函数作为入口,所有以_test.go结尾的源码文件内以Test开头的函数都会自动执行。

1.3 帮助函数helpers

我们知道在Pytest中公共的东西可以抽象出来放置在contest.py中,并设置使用级别,如session,function等,对于go中的testing,一些重复的逻辑可以抽出来作为公共的帮助函数helpers,这样的好处无需赘言,增加了测试代码的可维护性和可读性,且使得测试用例的逻辑更加紧凑和清晰,接着上面的示例

# calculate_test.go
package calculate

import "testing"

import "testing"

type calcCase struct {
	Name           string
	A, B, Expected int
}

func CreateMulTestCase(t *testing.T, c *calcCase, ) {
	//	t.helpers
	//	if ans := Mul(c.A, c.B); ans != c.Expected {
	//		t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
	//	}

	t.Helper()
	t.Run(c.Name, func(t *testing.T) {
		if ans := Mul(c.A, c.B); ans != c.Expected {
			t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
		}
	})
}

func TestMul(t *testing.T) {
	//if ans := Mul(2,3); ans != 6{
	//	t.Errorf("2*3 expected be 6,but %d got",ans)
	//}
	//t.Run("pos", func(t *testing.T) {
	//	if Mul(2, 3) != 6{
	//		t.Fatalf("2*3 expected be 6, but %d got", Mul(2, 3))
	//	}
	//})
	//t.Run("neg", func(t *testing.T) {
	//	if Mul(2, -3) != -6{
	//		t.Fatalf("2*-3 expected be 6, but %d got", Mul(2, -3))
	//	}
	//})

	//cases := []struct {
	//	Name           string
	//	A, B, Expected int
	//}{
	//	{"pos", 2, 3, 6},
	//	{"neg", 2, -3, -6},
	//	{"zero", 0, 2, -1},
	//}
	//
	//for _, c := range cases {
	//	t.Run(c.Name, func(t *testing.T) {
	//		if ans := Mul(c.A, c.B); ans != c.Expected {
	//			t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
	//		}
	//	})
	//}

	//CreateMulTestCase(t,&calcCase{2,3,6})
	//CreateMulTestCase(t,&calcCase{2,-3,-6})
	//CreateMulTestCase(t,&calcCase{0,2,1})

	CreateMulTestCase(t, &calcCase{"pos", 2, 3, 6})
	CreateMulTestCase(t, &calcCase{"neg", 2, -3, -6})
	CreateMulTestCase(t, &calcCase{"zero", 0, 2, 1})
}

# 这里给出了所以的代码,方便对比查阅,感觉其中演进变化之处

执行结果如下

calculate % go test -run TestMul -v                         
=== RUN   TestMul
    calculate_test.go:12: 0 * 2 expected 1, but 0 got
--- FAIL: TestMul (0.00s)
FAIL
exit status 1
FAIL    calculate       0.779s

发现有一个失败了,检查一下发现错误❎定位是第12行,我们回溯下
go 测试类,go,golang,单元测试,开发语言
但是这里有三个case都调用了,具体是哪个case有问题还需要一个个排查,这样也太麻烦了吧。因此go 1.9版本中引入了t.Helper(),用于标注该函数是帮助函数,报错时将输出帮助函数调用者的信息,而不是帮助函数内部的信息。检查本机的go版本

calculate % go version
go version go1.19.6 darwin/amd64

然后修改CreateMulTestCase,调用t.Helper()

func CreateMulTestCase(c *calcCase, t *testing.T) {
//	t.helpers
//	if ans := Mul(c.A, c.B); ans != c.Expected {
//		t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
//	}

	t.Helper()
	t.Run(c.Name, func(t *testing.T) {
		if ans := Mul(c.A, c.B); ans != c.Expected {
			t.Fatalf("%d * %d expected %d, but %d got", c.A, c.B, c.Expected, ans)
		}
	})
}

输出如下所示:

calculate % go test -run TestMul -v
=== RUN   TestMul
=== RUN   TestMul/pos
=== RUN   TestMul/neg
=== RUN   TestMul/zero
    calculate_test.go:61: 0 * 2 expected -1, but 0 got
--- FAIL: TestMul (0.00s)
    --- PASS: TestMul/pos (0.00s)
    --- PASS: TestMul/neg (0.00s)
    --- FAIL: TestMul/zero (0.00s)
FAIL
exit status 1
FAIL    calculate       0.397s

对于使用t.Helper(),有两点要注意:

  1. 不要返回错误, 帮助函数内部直接使用 t.Error 或 t.Fatal 即可,在用例主逻辑中不会因为太多的错误处理代码,影响可读性。
  2. 调用 t.Helper() 让报错信息更准确,有助于定位。

1.4 setup和teardown

一般我们编写自动化测试用例时,非业务检查逻辑会放置前者准备中诸如数据准备,抽象出一部分公共逻辑写在 setup 和 teardown 函数中。例如执行前需要实例化待测试的对象,如果这个对象比较复杂,很适合将这一部分逻辑提取出来;执行后,可能会做一些资源回收类的工作,例如关闭网络连接,释放文件等。标准库 testing 提供了这样的机制。


2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func setup() {
	fmt.Println("Before all tests")
}

func teardown() {
	fmt.Println("After all tests")
}

func Test1(t *testing.T) {
	fmt.Println("I'm test1")
}

func Test2(t *testing.T) {
	fmt.Println("I'm test2")
}

func TestMain(m *testing.M) {
	setup()
	code := m.Run()
	teardown()
	os.Exit(code)
}
  • 在这个测试文件中,包含有2个测试用例,Test1 和 Test2。
  • 如果测试文件中包含函数 TestMain,那么生成的测试将调用 TestMain(m),而不是直接运行测试。
  • 调用 m.Run() 触发所有测试用例的执行,并使用 os.Exit() 处理返回的状态码,如果不为0,说明有用例失败。
  • 因此可以在调用 m.Run() 前后做一些额外的准备(setup)和回收(teardown)工作。

执行 go test,将会输出

$ go test
Before all tests
I'm test1
I'm test2
PASS
After all tests
ok      example 0.006s

2.性能测试

对于性能测试,Go语言标准库内置的testing测试框架提供了基准测试benchmark的能力,可以很容易的对一段代码进行性能测试。性能测试受环境的影响很大,为了保证测试的可重复性,在进行性能测试时,尽可能地保持测试环境的稳定。

  • 机器处于闲置状态,测试时不要执行其他任务,也不要和其他人共享硬件资源。
  • 机器是否关闭了节能模式,一般笔记本会默认打开这个模式,测试时关闭。
  • 避免使用虚拟机和云主机进行测试,一般情况下,为了尽可能地提高资源的利用率,虚拟机和云主机 CPU 和内存一般会超分配,超分机器的性能表现会非常地不稳定。

2.1 入门示例

还是从一个简单的示例开始介绍,使用斐波那契数列,接着上面的calculate.go中新增Fib
go 测试类,go,golang,单元测试,开发语言

func Fib(n int) int {
	if n == 0 || n == 1 {
		return n
	}
	return Fib(n-2) + Fib(n-1)
}

calculate_test.go中实现一个benchmark用例,和单元测试一样,输入test会快捷联想出来

func BenchmarkFib(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Fib(30)
	}
}
  • benchmark 和普通的单元测试用例一样,都位于 _test.go 文件中。
  • 函数名以 Benchmark 开头,参数是 b *testing.B。和普通的单元测试用例很像,单元测试函数名以 Test 开头,参数是 t *testing.T

运行示例

go test <module name>/<package name> 用来运行某个 package 内的所有测试用例。

运行当前 package 内的用例:go test calculatego test .
运行子 package 内的用例: go test calculate/<package name>go test ./<package name>
如果想递归测试当前目录下的所有的 package:go test ./...go test calculate/...
go test 命令默认不运行 benchmark 用例的,如果我们想运行 benchmark 用例,则需要加上 -bench 参数。

calculate % go test -bench .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-12              327           3546075 ns/op
PASS
ok      calculate       1.887s

-bench 参数支持传入一个正则表达式,匹配到的用例才会得到执行,例如,只运行以 Fib 结尾的 benchmark

calculate % go test -bench="Fib$" .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-12              325           3589261 ns/op
PASS
ok      calculate       2.174s

2.3 benchmark是如何工作的

benchmark 用例的参数 b *testing.B,有个属性 b.N 表示这个用例需要运行的次数。b.N 对于每个用例都是不一样的。

那这个值是如何决定的呢?b.N 从 1 开始,如果该用例能够在 1s 内完成,b.N 的值便会增加,再次执行。b.N 的值大概以 1, 2, 3, 5, 10, 20, 30, 50, 100 这样的序列递增,越到后面,增加得越快。我们仔细观察上述例子的输出:

BenchmarkFib-12               202           5980669 ns/op

BenchmarkFib-12 中的 -12 即 GOMAXPROCS,默认等于 CPU 核数。可以通过 -cpu 参数改变 GOMAXPROCS-cpu 支持传入一个列表作为参数,例如

calculate % go test -bench="Fib$" -cpu=2,4 .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-2               332           3557771 ns/op
BenchmarkFib-4               343           3512955 ns/op
PASS
ok      calculate       3.460s

在这个例子中,改变 -cpu 的核数对结果几乎没有影响,因为这个 Fib 的调用是串行的。

3323557771 ns/op 表示用例执行了 343 次,每次花费约 0.006s。总耗时比 1s 略多

3.3 提升准确度

对于性能测试来说,提升测试准确度是一个重要手段就是增加测试的次数,即所谓的常稳测试,可以使用-benchtime-count,其中-benchtime默认为1s,可以设置指定-benchtime=5s`,如:

 calculate % go test -bench="Fib$" -benchtime=5s .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-12             1712           3466178 ns/op
PASS
ok      calculate       6.855s

实际执行的时间是 6.8s,比 benchtime 的 5s 要长,测试用例编译、执行、销毁等是需要时间的。 `-benchtime` 设置为 5s,用例执行次数也变成了原来的 5倍,每次函数调用时间仍为 0.6s,几乎没有变化。

`-benchtime` 的值除了是时间外,还可以是具体的次数。例如,执行 30 次可以用 `-benchtime=50x`

 calculate % go test -bench="Fib$" -benchtime=30x .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-12               30           3683029 ns/op
PASS
ok      calculate       1.113s

Fib调用了30次,花费1.1s。接着使用-count设置执行benchmark的论数,有点类似pytest中的repeat,例如进行5轮测试文章来源地址https://www.toymoban.com/news/detail-551200.html

 calculate % go test -bench="Fib$"  -benchtime=10s -count=5 .
goos: darwin
goarch: amd64
pkg: calculate
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkFib-12             3358           3493746 ns/op
BenchmarkFib-12             3330           3466845 ns/op
BenchmarkFib-12             3472           3440367 ns/op
BenchmarkFib-12             3442           3431086 ns/op
BenchmarkFib-12             3379           3429828 ns/op
PASS
ok      calculate       61.065s

到了这里,关于Go Test测试教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Go Test测试教程

    go中测试既有类似有 pytest 中的功能测试,也有 benchMark 的基准测试,以及单元测试( Unit Tests , UT ).这里从单元测试UT引入本篇的话题,单元测试的重要性不言而喻,尤其在大型项目中跨团队合作时,无法mr合格的代码,很容易影响整个团队的交付进度和质量。或者会说直接

    2024年02月15日
    浏览(42)
  • Go语言单元测试

    Go语言中的测试依赖 go test 命令,go test 命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录 内,所有以 _test.go 为后缀名的源代码文件都是 go test 测试的一部分,不会被 go build 编译到最终的可执行 文件中。 在 *_test.go 文件中有三种类型的函数, 单元测试函数

    2024年02月11日
    浏览(49)
  • Go语言测试——【单元测试 | Mock测试 | 基准测试】

    作者 :非妃是公主 专栏 :《Golang》 博客主页 :https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 软件测试 :软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测

    2024年02月10日
    浏览(59)
  • Go语言的单元测试与基准测试详解

    单元测试 以一个加法函数为例,对其进行单元测试。 首先编写add.go文件: 其次编写add_test.go文件,在go语言中,测试文件均已_test结尾,这里只需要在被测试的文件后加上_test即可。并且测试文件与要被测试的文件需要放在同一个包中,并不像 Java 那样需要将所有的测试文件

    2024年02月03日
    浏览(51)
  • 【go语言】3.3.1 单元测试和基准测试

    Go 语言的 testing 包为编写单元测试和基准测试提供了强大的支持。单元测试用于验证代码的正确性,基准测试用于测量代码的性能。 在Go语言中,单元测试和基准测试是两种常用的测试方法,用于测试和评估代码的质量和性能。 单元测试是一种针对代码中最小可测试单元(函

    2024年02月08日
    浏览(45)
  • 【GoLang入门教程】Go语言工程结构详述

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能 前言 当创建一个Go语言项目时,良好的工程结构是确保项目可维护性、可扩展性和清晰性的关键。 虽然Go本身没有强制性的项目结构要求,但是采用一致性

    2024年01月24日
    浏览(80)
  • 【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?

    Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。 然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。 先看一段代码示例: 当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。 首先,Go 语言

    2024年02月14日
    浏览(69)
  • 【Golang】Golang进阶系列教程--Go 语言数组和切片的区别

    在 Go 语言中,数组和切片看起来很像,但其实它们又有很多的不同之处,这篇文章就来说说它们到底有哪些不同。 数组和切片是两个常用的数据结构。它们都可以用于存储一组相同类型的元素,但在底层实现和使用方式上存在一些重要的区别。 Go 中数组的长度是不可改变的

    2024年02月15日
    浏览(61)
  • 【Golang】Golang进阶系列教程--Go 语言切片是如何扩容的?

    在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。 切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。 切片是一种引用类型,它有三个属性:指针,长度和容量。 底层源码定义如下: 指针: 指向

    2024年02月14日
    浏览(70)
  • 【Go语言】Golang保姆级入门教程 Go初学者chapter2

    setting的首选项 一个程序就是一个世界 变量是程序的基本组成单位 变量的使用步骤 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuxG8imp-1691479164956)(https://cdn.staticaly.com/gh/hudiework/img@main/image-20230726152905139.png)] 变量表示内存中的一个存储区 注意:

    2024年02月14日
    浏览(129)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包