go test的简单使用

news2024/11/15 22:40:03

go test

go 集成了比较好用的test测试命令,该命令可以测试Go代码的可用性。

前奏

该文所需的项目目录结构为:

    example
    |
    |---------function.go
    |
    |---------function_test.go
    |
    |---------go.mod

function.go文件是我们写用户代码的地方,function_test.go文件中写function.go的测试用例。
这是一种规范:xxx.go的测试文件为xxx_test.go。

Test 单元测试

向function.go文件中添加代码

func AddOne(num int) int {
	return num + 1
}

向function_test.go文件中添加代码

func TestAddOne(t *testing.T) {
	var (
		in       = 1
		expected = 2
	)

	actual := AddOne(in)
	if actual != expected {
		t.Errorf("AddOne(%d), expected = %d, actual = %d", in, expected, actual)
	}
}

若为goland,可以直接点击TestAddOne左侧的绿色三角按钮进行执行测试。执行结果如下:

=== RUN   TestAddOne
--- PASS: TestAddOne (0.00s)
PASS

将鼠标光标定位到左侧绿色三角按钮位置,单击一下,可以查看测试的一些指标

如以执行或调试的方式运行,测试代码覆盖率,CPU分析,内存分析,阻塞分析,锁分析。
代码覆盖率描述了方法中哪些片段执行到了,哪些片段没有执行到。
用命令行的方式测试代码覆盖率:

...\example>go test -coverprofile=coverage.out
PASS
coverage: 100.0% of statements
ok      example 0.295s

该命令要指定生成覆盖率数据的文件,若命令中的coverage.out。
执行完该命令,项目的目录结构为:

    example
    |
    |---------coverage.out
    |
    |---------function.go
    |
    |---------function_test.go
    |
    |---------go.mod

打开.out文件,有如下数据。

mode: set
example/function.go:3.26,5.2 1 1

该数据不方便查看,可以使用:
go tool cover -html=coverage.out 命令可视化查看上述指标。该命令会自动打开浏览器。
在这里插入图片描述
可以看出,左上角example/function.go (100.0%) 表示代码覆盖率为100%,若有多个测试文件,还可以选择其他文件查看。
not tracked可以先不看,它用于跟踪代码。
not covered表示未执行到的代码,会标红色。
covered表示执行过的代码,会标绿色。
向function.go文件中追加如下代码:

func AddOne2(num int) int {
	if 1 > 10 {
		fmt.Println("1 > 10")
	}
	return num + 1
}

if 1 > 10 的条件永远不会成立。
向function_test.go文件中追加如下代码:

func TestAddOne2(t *testing.T) {
	var (
		in       = 1
		expected = 2
	)

	actual := AddOne2(in)
	if actual != expected {
		t.Errorf("AddOne2(%d), expected = %d, actual = %d", in, expected, actual)
	}
}

然后执行如下命令:

...\example>go test -coverprofile=coverage.out
PASS
coverage: 75.0% of statements
ok      example 0.312s

用可视化的方式查看一下结果:
go tool cover -html=coverage.out
在这里插入图片描述
可以发现,整个if分支后的代码块都标记成了红色。

以表的形式,完成多组测试用例测试。
修改function_test.go文件的TestOne函数

func TestAddOne(t *testing.T) {
	testCase := []struct {
		in       int
		expected int
	}{
		{1, 2},
		{2, 3},
		{3, 4},
		{4, 5},
		{5, 6},
	}
	for _, tc := range testCase {
		actual := AddOne(tc.in)
		if actual != tc.expected {
			t.Errorf("AddOne(%d), expected = %d, actual = %d", tc.in, tc.expected, actual)
		}
	}
}

执行结果:

=== RUN   TestAddOne
--- PASS: TestAddOne (0.00s)
PASS

ExampleTest 示例测试

向function_test.go文件中追加代码:

func ExampleHello() {
	fmt.Println("hello")
	// Output: hello
}

执行结果为:

=== RUN   ExampleHello
--- PASS: ExampleHello (0.00s)
PASS

修改fmt.Println(“hello”) hello为hello world
执行结果为:

=== RUN   ExampleHello
--- FAIL: ExampleHello (0.00s)
got:
hello world
want:
hello

FAIL

可以发现,测试结果是与// Output: 之后的值是紧密相关的。

BenckmarkTest 基准测试

向function_test.go中追加如下代码:

func BenchmarkStringAppend(b *testing.B) {
	str := ""
	for i := 0; i < b.N; i++ {
		str += "hello"
	}
}

func BenchmarkStringBuilderAppend(b *testing.B) {
	bld := strings.Builder{}
	for i := 0; i < b.N; i++ {
		bld.WriteString("hello")
	}
}

其执行结果分别为:

goos: windows
goarch: amd64
pkg: example
cpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
BenchmarkStringAppend
BenchmarkStringAppend-4           152083            143699 ns/op
PASS

每次操作143699ns,共执行152083次

goos: windows
goarch: amd64
pkg: example
cpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
BenchmarkStringBuilderAppend
BenchmarkStringBuilderAppend-4          93936404                12.35 ns/op
PASS

每次操作12.35ns,共执行93936404次
可以发现,strings.Builder的追加性能要明显优于直接用"+"号进行string 的 追加

FuzzTest 模糊测试

func FuzzHex(f *testing.F) {
	for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {
		f.Add(seed)
	}
	f.Fuzz(func(t *testing.T, in []byte) {
		enc := hex.EncodeToString(in)
		out, err := hex.DecodeString(enc)
		if err != nil {
			t.Fatalf("%v: decode: %v", in, err)
		}
		if !bytes.Equal(in, out) {
			t.Fatalf("%v: not equal after round trip: %v", in, out)
		}
	})
}

建议阅读一下src/testing/testing.go文件中的注释

// Package testing provides support for automated testing of Go packages.
// It is intended to be used in concert with the "go test" command, which automates
// execution of any function of the form
//
//	func TestXxx(*testing.T)
//
// where Xxx does not start with a lowercase letter. The function name
// serves to identify the test routine.
//
// Within these functions, use the Error, Fail or related methods to signal failure.
//
// To write a new test suite, create a file whose name ends _test.go that
// contains the TestXxx functions as described here. Put the file in the same
// package as the one being tested. The file will be excluded from regular
// package builds but will be included when the "go test" command is run.
// For more detail, run "go help test" and "go help testflag".
//
// A simple test function looks like this:
//
//	func TestAbs(t *testing.T) {
//	    got := Abs(-1)
//	    if got != 1 {
//	        t.Errorf("Abs(-1) = %d; want 1", got)
//	    }
//	}
//
// # Benchmarks
//
// Functions of the form
//
//	func BenchmarkXxx(*testing.B)
//
// are considered benchmarks, and are executed by the "go test" command when
// its -bench flag is provided. Benchmarks are run sequentially.
//
// For a description of the testing flags, see
// https://golang.org/cmd/go/#hdr-Testing_flags.
//
// A sample benchmark function looks like this:
//
//	func BenchmarkRandInt(b *testing.B) {
//	    for i := 0; i < b.N; i++ {
//	        rand.Int()
//	    }
//	}
//
// The benchmark function must run the target code b.N times.
// During benchmark execution, b.N is adjusted until the benchmark function lasts
// long enough to be timed reliably. The output
//
//	BenchmarkRandInt-8   	68453040	        17.8 ns/op
//
// means that the loop ran 68453040 times at a speed of 17.8 ns per loop.
//
// If a benchmark needs some expensive setup before running, the timer
// may be reset:
//
//	func BenchmarkBigLen(b *testing.B) {
//	    big := NewBig()
//	    b.ResetTimer()
//	    for i := 0; i < b.N; i++ {
//	        big.Len()
//	    }
//	}
//
// If a benchmark needs to test performance in a parallel setting, it may use
// the RunParallel helper function; such benchmarks are intended to be used with
// the go test -cpu flag:
//
//	func BenchmarkTemplateParallel(b *testing.B) {
//	    templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
//	    b.RunParallel(func(pb *testing.PB) {
//	        var buf bytes.Buffer
//	        for pb.Next() {
//	            buf.Reset()
//	            templ.Execute(&buf, "World")
//	        }
//	    })
//	}
//
// A detailed specification of the benchmark results format is given
// in https://golang.org/design/14313-benchmark-format.
//
// There are standard tools for working with benchmark results at
// https://golang.org/x/perf/cmd.
// In particular, https://golang.org/x/perf/cmd/benchstat performs
// statistically robust A/B comparisons.
//
// # Examples
//
// The package also runs and verifies example code. Example functions may
// include a concluding line comment that begins with "Output:" and is compared with
// the standard output of the function when the tests are run. (The comparison
// ignores leading and trailing space.) These are examples of an example:
//
//	func ExampleHello() {
//	    fmt.Println("hello")
//	    // Output: hello
//	}
//
//	func ExampleSalutations() {
//	    fmt.Println("hello, and")
//	    fmt.Println("goodbye")
//	    // Output:
//	    // hello, and
//	    // goodbye
//	}
//
// The comment prefix "Unordered output:" is like "Output:", but matches any
// line order:
//
//	func ExamplePerm() {
//	    for _, value := range Perm(5) {
//	        fmt.Println(value)
//	    }
//	    // Unordered output: 4
//	    // 2
//	    // 1
//	    // 3
//	    // 0
//	}
//
// Example functions without output comments are compiled but not executed.
//
// The naming convention to declare examples for the package, a function F, a type T and
// method M on type T are:
//
//	func Example() { ... }
//	func ExampleF() { ... }
//	func ExampleT() { ... }
//	func ExampleT_M() { ... }
//
// Multiple example functions for a package/type/function/method may be provided by
// appending a distinct suffix to the name. The suffix must start with a
// lower-case letter.
//
//	func Example_suffix() { ... }
//	func ExampleF_suffix() { ... }
//	func ExampleT_suffix() { ... }
//	func ExampleT_M_suffix() { ... }
//
// The entire test file is presented as the example when it contains a single
// example function, at least one other function, type, variable, or constant
// declaration, and no test or benchmark functions.
//
// # Fuzzing
//
// 'go test' and the testing package support fuzzing, a testing technique where
// a function is called with randomly generated inputs to find bugs not
// anticipated by unit tests.
//
// Functions of the form
//
//	func FuzzXxx(*testing.F)
//
// are considered fuzz tests.
//
// For example:
//
//	func FuzzHex(f *testing.F) {
//	  for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {
//	    f.Add(seed)
//	  }
//	  f.Fuzz(func(t *testing.T, in []byte) {
//	    enc := hex.EncodeToString(in)
//	    out, err := hex.DecodeString(enc)
//	    if err != nil {
//	      t.Fatalf("%v: decode: %v", in, err)
//	    }
//	    if !bytes.Equal(in, out) {
//	      t.Fatalf("%v: not equal after round trip: %v", in, out)
//	    }
//	  })
//	}
//
// A fuzz test maintains a seed corpus, or a set of inputs which are run by
// default, and can seed input generation. Seed inputs may be registered by
// calling (*F).Add or by storing files in the directory testdata/fuzz/<Name>
// (where <Name> is the name of the fuzz test) within the package containing
// the fuzz test. Seed inputs are optional, but the fuzzing engine may find
// bugs more efficiently when provided with a set of small seed inputs with good
// code coverage. These seed inputs can also serve as regression tests for bugs
// identified through fuzzing.
//
// The function passed to (*F).Fuzz within the fuzz test is considered the fuzz
// target. A fuzz target must accept a *T parameter, followed by one or more
// parameters for random inputs. The types of arguments passed to (*F).Add must
// be identical to the types of these parameters. The fuzz target may signal
// that it's found a problem the same way tests do: by calling T.Fail (or any
// method that calls it like T.Error or T.Fatal) or by panicking.
//
// When fuzzing is enabled (by setting the -fuzz flag to a regular expression
// that matches a specific fuzz test), the fuzz target is called with arguments
// generated by repeatedly making random changes to the seed inputs. On
// supported platforms, 'go test' compiles the test executable with fuzzing
// coverage instrumentation. The fuzzing engine uses that instrumentation to
// find and cache inputs that expand coverage, increasing the likelihood of
// finding bugs. If the fuzz target fails for a given input, the fuzzing engine
// writes the inputs that caused the failure to a file in the directory
// testdata/fuzz/<Name> within the package directory. This file later serves as
// a seed input. If the file can't be written at that location (for example,
// because the directory is read-only), the fuzzing engine writes the file to
// the fuzz cache directory within the build cache instead.
//
// When fuzzing is disabled, the fuzz target is called with the seed inputs
// registered with F.Add and seed inputs from testdata/fuzz/<Name>. In this
// mode, the fuzz test acts much like a regular test, with subtests started
// with F.Fuzz instead of T.Run.
//
// See https://go.dev/doc/fuzz for documentation about fuzzing.
//
// # Skipping
//
// Tests or benchmarks may be skipped at run time with a call to
// the Skip method of *T or *B:
//
//	func TestTimeConsuming(t *testing.T) {
//	    if testing.Short() {
//	        t.Skip("skipping test in short mode.")
//	    }
//	    ...
//	}
//
// The Skip method of *T can be used in a fuzz target if the input is invalid,
// but should not be considered a failing input. For example:
//
//	func FuzzJSONMarshaling(f *testing.F) {
//	    f.Fuzz(func(t *testing.T, b []byte) {
//	        var v interface{}
//	        if err := json.Unmarshal(b, &v); err != nil {
//	            t.Skip()
//	        }
//	        if _, err := json.Marshal(v); err != nil {
//	            t.Error("Marshal: %v", err)
//	        }
//	    })
//	}
//
// # Subtests and Sub-benchmarks
//
// The Run methods of T and B allow defining subtests and sub-benchmarks,
// without having to define separate functions for each. This enables uses
// like table-driven benchmarks and creating hierarchical tests.
// It also provides a way to share common setup and tear-down code:
//
//	func TestFoo(t *testing.T) {
//	    // <setup code>
//	    t.Run("A=1", func(t *testing.T) { ... })
//	    t.Run("A=2", func(t *testing.T) { ... })
//	    t.Run("B=1", func(t *testing.T) { ... })
//	    // <tear-down code>
//	}
//
// Each subtest and sub-benchmark has a unique name: the combination of the name
// of the top-level test and the sequence of names passed to Run, separated by
// slashes, with an optional trailing sequence number for disambiguation.
//
// The argument to the -run, -bench, and -fuzz command-line flags is an unanchored regular
// expression that matches the test's name. For tests with multiple slash-separated
// elements, such as subtests, the argument is itself slash-separated, with
// expressions matching each name element in turn. Because it is unanchored, an
// empty expression matches any string.
// For example, using "matching" to mean "whose name contains":
//
//	go test -run ''        # Run all tests.
//	go test -run Foo       # Run top-level tests matching "Foo", such as "TestFooBar".
//	go test -run Foo/A=    # For top-level tests matching "Foo", run subtests matching "A=".
//	go test -run /A=1      # For all top-level tests, run subtests matching "A=1".
//	go test -fuzz FuzzFoo  # Fuzz the target matching "FuzzFoo"
//
// The -run argument can also be used to run a specific value in the seed
// corpus, for debugging. For example:
//
//	go test -run=FuzzFoo/9ddb952d9814
//
// The -fuzz and -run flags can both be set, in order to fuzz a target but
// skip the execution of all other tests.
//
// Subtests can also be used to control parallelism. A parent test will only
// complete once all of its subtests complete. In this example, all tests are
// run in parallel with each other, and only with each other, regardless of
// other top-level tests that may be defined:
//
//	func TestGroupedParallel(t *testing.T) {
//	    for _, tc := range tests {
//	        tc := tc // capture range variable
//	        t.Run(tc.Name, func(t *testing.T) {
//	            t.Parallel()
//	            ...
//	        })
//	    }
//	}
//
// Run does not return until parallel subtests have completed, providing a way
// to clean up after a group of parallel tests:
//
//	func TestTeardownParallel(t *testing.T) {
//	    // This Run will not return until the parallel tests finish.
//	    t.Run("group", func(t *testing.T) {
//	        t.Run("Test1", parallelTest1)
//	        t.Run("Test2", parallelTest2)
//	        t.Run("Test3", parallelTest3)
//	    })
//	    // <tear-down code>
//	}
//
// # Main
//
// It is sometimes necessary for a test or benchmark program to do extra setup or teardown
// before or after it executes. It is also sometimes necessary to control
// which code runs on the main thread. To support these and other cases,
// if a test file contains a function:
//
//	func TestMain(m *testing.M)
//
// then the generated test will call TestMain(m) instead of running the tests or benchmarks
// directly. TestMain runs in the main goroutine and can do whatever setup
// and teardown is necessary around a call to m.Run. m.Run will return an exit
// code that may be passed to os.Exit. If TestMain returns, the test wrapper
// will pass the result of m.Run to os.Exit itself.
//
// When TestMain is called, flag.Parse has not been run. If TestMain depends on
// command-line flags, including those of the testing package, it should call
// flag.Parse explicitly. Command line flags are always parsed by the time test
// or benchmark functions run.
//
// A simple implementation of TestMain is:
//
//	func TestMain(m *testing.M) {
//		// call flag.Parse() here if TestMain uses flags
//		os.Exit(m.Run())
//	}
//
// TestMain is a low-level primitive and should not be necessary for casual
// testing needs, where ordinary test functions suffice.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣(LeetCode)388. 文件的最长绝对路径(2023.01.21)

假设有一个同时存储文件和目录的文件系统。下图展示了文件系统的一个示例&#xff1a; 这里将 dir 作为根目录中的唯一目录。dir 包含两个子目录 subdir1 和 subdir2 。subdir1 包含文件 file1.ext 和子目录 subsubdir1&#xff1b;subdir2 包含子目录 subsubdir2&#xff0c;…

架构设计中的布隆过滤器与布谷鸟过滤器

场景: 某业务后端涉及数据库&#xff0c;当请求消息查询某些信息时&#xff0c;可能先检查缓存中是否有相关信息&#xff0c;有的话返回&#xff0c;如果没有的话可能就要去数据库里面查询&#xff0c;这时候有一个问题&#xff0c;如果很多请求是在请求数据库根本不存在的数据…

活动星投票中国青年好网民网络评选微信的投票方式线上免费投票

“中国青年好网民”网络评选投票_投票微信搭建程序_微信多项免费投票_如何利用微信群投票如果通过一个小程序免费制作一个微信投票活动呢&#xff1f;文章详细讲解如何利用一款免费好用的微信小程序“活动星投票”小程序来制作投票活动&#xff0c;无需注册即可免费制作&#x…

“华为杯”研究生数学建模竞赛2005年-【华为杯】A题:高速公路行车时间估计及最优路径选择问题(附获奖论文)

赛题描述 A: Highway Traveling time Estimate and Optimal Routing Ⅰ Highway traveling time estimate is crucial to travelers. Hence, detectors are mounted on some of the US highways. For instance, detectors are mounted on every two-way six-lane highways o…

创建者模式-建造者模式

1.概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某个对象的构建过程复杂的情况。由于实现了构建和装配的解耦…

idea启动java项目报错——error:java: 无效的源发行版: 10

问题背景 今天在新建了一个项目的后&#xff0c;项目搭建好以后&#xff0c;想要看一下是否能够正常启动。但是在启动项目的时候&#xff0c;控制台报错如下&#xff1a;error:java: 无效的源发行版: 10。脑残审核&#xff0c;你告诉我哪个是广告&#xff1f;&#xff1f;&…

Linux下进程以及相关概念理解

目录 一、进程概念 二、描述进程PCB 三、查看进程 3.1 通过系统目录查看 3.2 通过ps命令查看 四、进程状态 运行状态R 睡眠状态S 磁盘休眠状态D 暂停状态T 僵尸状态Z 死亡状态X 五、僵尸进程与孤儿进程 5.1 僵尸进程 5.1.1 僵尸进程的概念 5.1.2 僵尸进程的危害…

【C++】从0到1入门C++编程学习笔记 - 核心编程篇:类和对象(上)

文章目录一、封装1.1 封装的意义1.2 struct和class区别1.3 成员属性设置为私有二、对象的初始化和清理2.1 构造函数和析构函数2.2 构造函数的分类及调用2.3 拷贝构造函数调用时机2.4 构造函数调用规则2.5 深拷贝与浅拷贝2.6 初始化列表2.7 类对象作为类成员2.8 静态成员三、C对…

day27-单元测试/日志

1.管理系统与服务器集成 1.1准备工作【应用】 需求 对之前写过的信息管理系统进行改进,实现可以通过浏览器进行访问的功能 准备工作 将资料中的管理系统代码拷贝到当前模块下 导包的代码可能报错,因为之前的包路径可能和当前代码不一致,将导包的代码修改下 业务分析 解…

【Linux】Linux下的调试器-gdb的使用

目录1.debug和release拓展2.如何使用gdb调试3.指令集我们平常调试C/C代码大多实在Windows平台下的VS中&#xff0c;在LInux中&#xff0c;我们通常使用gdb来调试代码&#xff0c;虽然我们很少在LInux上对代码进行调试&#xff0c;gdb在实际的使用中用的较少&#xff0c;但我们必…

【C++】从0到1入门C++编程学习笔记 - 核心编程篇:类和对象(下)

文章目录五、运算符重载5.1 加号运算符重载5.2 左移运算符重载5.3 递增运算符重载5.4 赋值运算符重载5.5 关系运算符重载5.6 函数调用运算符重载六、继承6.1 继承的基本语法6.2 继承方式6.3 继承中的对象模型6.4 继承中构造和析构顺序6.5 继承同名成员处理方式6.6 继承同名静态…

Java练习:面向对象进阶(上)

Java练习&#xff1a;面向对象进阶&#xff08;上&#xff09;一、定义数组工具类a. 工具类b. 测试类c. 输出结果二、定义学生工具类a. 学生类b. 工具类c. 测试类d. 输出结果三、继承和多态综合练习a. 动物类b. 饲养员类c. 狗类d. 猫类e. 测试类f. 输出结果一、定义数组工具类 …

S60v3固件备份

清理老硬盘 该删资料了 以前的N年前备份的帖子放在CSDN备份吧 没啥用的 以后用来讲故事的 大家不要介意. RM-632102.002 E5-00极限版 RM-566031.023 6730c极限固件 RM-469091.004 E52极限固件 E5-00 一代神机 RM-632 WIFI 横屏 500MP 内存256 S60V3FP2E5的ROM估计现在太难找…

Special Weekly | 瑞兔送福,Live Long and Prosper

SOFAWish 送虎迎兔各位 SOFAStack 社区的朋友好&#xff1a;我是 SOFAStack 社区的负责人鲁直&#xff0c;度过了令人难忘的虎年&#xff0c;我们即将迈入充满希望的兔年&#xff0c;在这里给大家拜个早年&#xff0c;祝大家兔年吉祥。虎年虽然有诸多的不便与艰难&#xff0c;…

ROS2机器人编程简述humble-第二章-SIMULATED ROBOT SETUP .4

ROS2机器人编程简述新书推荐-A Concise Introduction to Robot Programming with ROS2ROS2机器人编程简述humble-第二章-Executors .3.5书中没有使用几乎所有教程都会采用的turtlesim。美美的圣诞树画出来-CoCube如何将数学曲线变为机器人轨迹-花式show爱心代码-turtlesim篇直接…

Ribbon集成Nacos实现权重配置(本篇暂未支持spring gateway)

1场景&#xff1a;本篇&#xff0c;是师范 ribbon 与nacos 的权重测试&#xff0c;ribbon读取 nacos内权重设置。在调用端增加配置文件代码如下&#xff1a;&#xff08;1&#xff09; 本次测试nacos 1.4.1&#xff1b;&#xff08;2&#xff09; spring cloud 版本&#xff1a…

趣味三角——第2章——弦

目录 2.1 三角学的雏形与和弦表的产生 2.2 解读残缺粘土板“Plimpton 322”上的三角学 “知识来自影子&#xff0c;影子来自 磬折形(The knowledge comes from the shadow, and the shadow comes from the gnomon)” ——摘自<<Chou-pei Suan-king>>(周髀(b)算经…

while循环——求100以内偶数和

1 问题 求100以内的偶数和。 2 方法 public class EvenNumber{ public static void main(String[] args){ int i 1; int sum 0; while(i < 100){ if(i % 2 0){ System.out.println(i); sum sum i; } i; } System.out.println("100以内的偶数和为&#xff1a;"…

Java-线程基础

Java 线程详解 一个程序至少需要一个进程&#xff0c;而一个进程至少需要一个线程&#xff0c;它也被称为主线程。 线程是程序执行流的最小单位&#xff0c;而进程是系统进行资源分配和调度的一个最小单位。 在单个进程中&#xff0c;可以拥有多个并发执行的线程&#xff0c…

MYSQL分页查询时没有用ORDER BY出现数据重复的问题

背景 产品反馈&#xff0c;用户在使用分页列表时&#xff0c;出现数据重复的问题&#xff0c;查看代码后发现对应的分页SQL并没有使用order by进行排序&#xff0c;但是印象中Mysql的InnoDB引擎会默认按照主键id进行排序&#xff0c;本地测试了一下的确出现了部分数据在不同的页…