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

golang入门笔记——测试

测试类型:

在这里插入图片描述

单元测试:

在这里插入图片描述

规则:

1.所有测试文件以_test.go结尾
2.func Testxxx(*testing.T)
3.初始化逻辑放到TestMain中

运行:

go test [flags][packages]

Go语言中的测试依赖go test命令。
go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中
测试函数:
每个测试函数必须导入testing包,测试函数名必须以Test开头,测试函数的基本格式(签名)如下:
在这里插入图片描述

覆盖率:

显示代码覆盖率的命令

go test [flags][packages] --cover

1.一般覆盖率:50%~60%,较高覆盖率80%+
2.测试分支相互独立、全面覆盖
3.测试单元粒度足够小,函数单一职责

依赖:

在这里插入图片描述

Mock

1.快速mock函数:
为一个函数打桩
为一个方法打桩

monkey打桩实例:
在这里插入图片描述

代码实例:

package split_stringimport ("strings"
)//切割字符串
//example:
//abc,b=>[a c]
func Split(str string, sep string) []string {var ret=make([]string,0,strings.Count(str,sep)+1)//预先分配好内存index := strings.Index(str, sep)for index >= 0 {ret = append(ret, str[:index])str = str[index+len(sep):]index = strings.Index(str, sep)}if str != "" {ret = append(ret, str)}return ret
}func TestMain(m *testing.M){
//测试前:数据装载、配置初始化等前置工作code:=m.Run()//测试后,释放资源等收尾工作
os.Exist(code)
}
package split_stringimport ("reflect""testing"
)func TestSplit(t *testing.T) {ret := Split("babcbef", "b")want := []string{"", "a", "c", "ef"}if !reflect.DeepEqual(ret, want) {//测试用例失败了t.Errorf("want:%v but got:%v\n", want, ret)}
} //测试用例一func Test2Split(t *testing.T) {ret := Split("a:b:c", ":")want := []string{"a", "b", "c"}if !reflect.DeepEqual(ret, want) {t.Fatalf("want:%v but get:%v\n", want, ret)}
} //测试用例二//一次测试多个
func Test3Split(t *testing.T) {type testCase struct {str  stringsep  stringwant []string}testGroup := []testCase{testCase{"babcbef", "b", []string{"", "a", "c", "ef"}},testCase{"a:b:c", ":", []string{"a", "b", "c"}},testCase{"abcdef", "bc", []string{"a", "def"}},testCase{"沙河有沙又有河", "有", []string{"沙河", "沙又", "河"}},}for _, test := range testGroup {got := Split(test.str, test.sep)if !reflect.DeepEqual(got, test.want) {t.Fatalf("want:%#v got:%#v\n", test.want, got)}}
}//子测试
func Test4Split(t *testing.T) {if testing.Short(){t.Skip("short模式下会跳过测试用例")}type testCase struct {str  stringsep  stringwant []string}testGroup := map[string]testCase{"case 1": testCase{"babcbef", "b", []string{"", "a", "c", "ef"}},"case 2": testCase{"a:b:c", ":", []string{"a", "b", "c"}},"case 3": testCase{"abcdef", "bc", []string{"a", "def"}},"case 4": testCase{"沙河有沙又有河", "有", []string{"沙河", "沙又", "河"}},}for name, test := range testGroup {t.Run(name, func(t *testing.T) {t.Parallel()	//将每个测试用例标记为能够彼此并行运行got := Split(test.str, test.sep)if !reflect.DeepEqual(got, test.want) {t.Fatalf("want:%#v got:%#v\n", test.want, got)}})}
} //会把每个map中的样例试结果都打印出来
func TestMain(m *testing.M) {//测试的入口函数m.Run()//测试开始
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//在split_string终端下
go test //进行测试
go test -v//查看测试细节
go test -cover//语句覆盖率
go test -cover -coverprofile=cover.out//将测试结果生成文件
go tool -cover -html=cover.out  //生成html文件来分析cover.out,绿色覆盖,红色未覆盖
//好的测试,测试函数覆盖率:100%  测试覆盖率:60%
go test -run=Sep -v  //只运行测试函数名中带有Sep的测试
go test -short //会跳过某些耗时的测试用例

基准测试:

func BenchmarkSplit(b *testing.B){for i:=0;i<b.N;i++{//N不是一个固定的数,是使Split跑够1秒钟的一个数Split("a:b:c:d:e",":")}
}
go test -bench=Split
//goos: windows windows平台
// goarch: amd64  amd64位
// pkg: test/split_string
// cpu: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
// BenchmarkSplit-12  12核   3869991    执行次数      307.2 ns/op 307.2ns/次
// PASS
// ok      test/split_string       1.539s
go test -bench=Split -benchmem //增加了查看对内存的申请情况

网络测试:

func TestHelloHandler(t *testing.T) {ln, err := net.Listen("tcp", "localhost:0")handleError(t, err)defer ln.Close()http.HandleFunc("/hello", HelloHandler)go http.Serve(ln, nil)resp, err := http.Get("http://" + ln.Addr().String() + "hello")handleError(t, err)defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)handleError(t, err)if string(body) != "hello world!" {t.Fatal("expected hello world,but got", string(body))}
}

1.优化代码,需要对当前代码分析
2.内置的测试框架提供了基准测试的能力

func BenchmarkSelect(b *testing.B) {InitServerIndex()b.ResetTimer() //定时器重置for i := 0; i < b.N; i++ {Select()}
}func BenchmarkSelectParallel(b *testing.B) {InitServerIndex()b.ResetTimer()b.RunParallel(func(pb *testing.PB) {for pb.Next() {Select()}})
}

SqlMock

mock的核心在于屏蔽上游细节,使用一些实现设定好的数据来模拟上游返回的数据
sqlmock就是在测试过程中,指定你期望(Expectations)执行的查询语句,以及假定的返回结果(WillReturnResult)

sqlmock库的安装:

go get github.com/DATA-DOG/go-sqlmock

sqlmock.New()返回一个标准的sql.DB结构体实例指针,这是一个数据库连接句柄。除此之外还返回了一个sqlmock.Sqlmock结构体实例

	db, mock, err := sqlmock.New()if err != nil {t.Errorf("create sqlmock fail")}defer db.Close()mock.ExpectExec(`sql sentence`).WithArgs(sqlmock.AnyArg()).WillReturnResult(sqlmock.NewResult(1, 1))//ExpectExec里的sql sentence为期望执行的sql语句//WithArgs代表执行该语句所要带的参数//sqlmock.AnyArg()代表任意参数//WillReturnResult里面代表假定的返回//sqlmock.NewResult(1,1)代表自增主键为1,1条影响结果

gorm使用sqlmock测试时的示例

db, mock, err := sqlmock.New()
if nil != err {t.Fatalf("Init sqlmock failed, err %v", err)
}
defer db.Close()gormDB, err := gorm.Open(mysql.New(mysql.Config{SkipInitializeWithVersion: true,Conn: db,}), &gorm.Config{})
if err!=nil {t.Fatalf("Init DB with sqlmock failed, err %v", err)
} else {if db, err := database.KnodiDB.DB(); nil != err {db.SetMaxIdleConns(10)db.SetMaxOpenConns(10)db.Ping()}
}

增删改查 sqlmock示例

main.go

package mainimport ("database/sql"_ "github.com/go-sql-driver/mysql"
)type User struct {Id       int64Username stringPassword string
}func recordStats(db *sql.DB, userID, productID int64) (err error) {tx, err := db.Begin()if err != nil {return}defer func() {switch err {case nil:err = tx.Commit()default:tx.Rollback()}}()if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {return}if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {return}return
}func recordQuery(db *sql.DB, userID int64) (user *User, err error) {row := db.QueryRow("SELECT * FROM user where id =?", userID)user = new(User)err = row.Scan(&user.Id, &user.Username, &user.Password)return
}func recordDelete(db *sql.DB, userID int64) (err error) {_, err = db.Exec("DELETE FROM user where id=?", userID)if err != nil {return}return
}func main() {// @NOTE: the real connection is not required for testsdb, err := sql.Open("mysql", "root@/blog")if err != nil {panic(err)}defer db.Close()if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {panic(err)}
}

main_test.go

package mainimport ("fmt""regexp""testing""github.com/DATA-DOG/go-sqlmock"
)// a successful case
func TestShouldUpdateStats(t *testing.T) {db, mock, err := sqlmock.New()if err != nil {t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)}defer db.Close()mock.ExpectBegin()mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectCommit()// now we execute our methodif err = recordStats(db, 2, 3); err != nil {t.Errorf("error was not expected while updating stats: %s", err)}// we make sure that all expectations were metif err := mock.ExpectationsWereMet(); err != nil {t.Errorf("there were unfulfilled expectations: %s", err)}
}// a failing test case
func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {db, mock, err := sqlmock.New()if err != nil {t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)}defer db.Close()mock.ExpectBegin()mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnError(fmt.Errorf("some error"))mock.ExpectRollback()// now we execute our methodif err = recordStats(db, 2, 3); err == nil {t.Errorf("was expecting an error, but there was none")}// we make sure that all expectations were metif err := mock.ExpectationsWereMet(); err != nil {t.Errorf("there were unfulfilled expectations: %s", err)}
}func TestQuery(t *testing.T) {userInfo := []string{"id","username","password",}db, mock, err := sqlmock.New()if err != nil {t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)}mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM user")).WithArgs(1).WillReturnRows(sqlmock.NewRows(userInfo).AddRow(1, "zyj", "123"))if err = recordStats(db, 2, 3); err == nil {t.Errorf("was expecting an error, but there was none")}user, err := recordQuery(db, 1)if err != nil || user == nil {t.Errorf("this is something wrong")}t.Log(user)
}func TestDelete(t *testing.T) {db, mock, err := sqlmock.New()if err != nil {t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)}mock.ExpectExec("DELETE FROM user").WithArgs(1).WillReturnResult(sqlmock.NewResult(1, 1))err = recordDelete(db, 1)if err != nil {t.Errorf("this is something wrong")}
}

ginkgo和gomega

1.在引入ginkgo和gomega的时候前面加.这样每次调用时就可以直接使用包中的方法函数了。
2.ginkgo使用Describe()来描述这段代码的行为,使用Context()来描述表达该行为是在不同的环境下执行,一个it就是一个spec即一个测试用例
3.ginkgo使用BeforeEach()来为specs设置状态,并使用It()来指定单个spec,也是一个测试用例,且执行每一个It模块前都会执行一次Describe的BeforeEach和AfterEach,以确保每个Specs都处于原始状态
4.JustBeforeEach()模块在所有BeforeEach()模块执行之后,It模块执行之前运行,BeforeSuit函数在所有Specs运行前执行,AfterSuite函数在所有Specs运行后执行,不论测试是否失败
5.使用Gomega中的Expect()函数来设置期望

package mainimport ("database/sql""fmt""regexp""sync""github.com/DATA-DOG/go-sqlmock". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Record Test", func() {var (once     sync.Oncemock     sqlmock.Sqlmockdb       *sql.DBerr      erroruserInfo []string)BeforeEach(func() {once.Do(func() {db, mock, err = sqlmock.New()if err != nil {fmt.Println(err)}})userInfo = []string{"id","username","password",}})Context("test update and insert", func() {It("text update and insert success", func() {mock.ExpectBegin()mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectCommit()// now we execute our methoderr = recordStats(db, 2, 3)Expect(err).To(BeNil())// we make sure that all expectations were meterr = mock.ExpectationsWereMet()Expect(err).To(BeNil())})It("text update and insert failed", func() {mock.ExpectBegin()mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnError(fmt.Errorf("some error"))mock.ExpectRollback()// now we execute our methoderr = recordStats(db, 2, 3)Expect(err).To(BeNil())// we make sure that all expectations were meterr := mock.ExpectationsWereMet()Expect(err).To(BeNil())})Context("test query", func() {It("test query", func() {mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM user")).WithArgs(1).WillReturnRows(sqlmock.NewRows(userInfo).AddRow(1, "zyj", "123"))err = recordStats(db, 2, 3)Expect(err).To(BeNil())user, err := recordQuery(db, 1)Expect(err).To(BeNil())Expect(user.Id).To(Equal(int64(1)))})})Context("text delete", func() {It("test delete", func() {mock.ExpectExec("DELETE FROM user").WithArgs(1).WillReturnResult(sqlmock.NewResult(1, 1))err = recordDelete(db, 1)Expect(err).To(BeNil())})})})
})

RedisMock

redismock的安装:

go get github.com/go-redis/redismock/v9

简单示例:

main.go

package mainimport ("context""fmt""time""github.com/redis/go-redis/v9"
)func NewsInfoForCache(redisDB *redis.Client, newsID int) (info string, err error) {cacheKey := fmt.Sprintf("news_redis_cache_%d", newsID)ctx := context.TODO()info, err = redisDB.Get(ctx, cacheKey).Result()if err == redis.Nil {// info, err = call api()info = "test"err = redisDB.Set(ctx, cacheKey, info, 30*time.Minute).Err()}return
}

main_test.go

package mainimport ("errors""fmt""sync""time""github.com/go-redis/redismock/v9". "github.com/onsi/ginkgo". "github.com/onsi/gomega""github.com/redis/go-redis/v9"
)var _ = Describe("Record Test", func() {var (once        sync.Oncemock        redismock.ClientMockredisClient *redis.Client)BeforeEach(func() {once.Do(func() {redisClient, mock = redismock.NewClientMock()})})Context("test set", func() {id := 123key := fmt.Sprintf("new_redis_cache_%d", id)It("test set success", func() {mock.ExpectGet(key).RedisNil()mock.Regexp().ExpectSet(key, `[a-z]+`, 30*time.Second).SetErr(errors.New("FAIL"))_, err := NewsInfoForCache(redisClient, id)Expect(err).To(BeNil())})})})

Monkey

monkey是go语言非常常用的一个打桩工具,它在运行时通过汇编语言重写可执行文件,将目标函数或方法的实现跳转到桩实现。

monkey库很强大,但是使用时需注意以下事项:

1.monkey不支持内联函数,在测试的时候需要通过命令行参数-gcflags=-1关闭Go语言的内联优化
2.monkey不是线程安全的,所以不能把它放到并发的单元测试中

安装monkey库的命令:

go get bou.ke/monkey

简单的monkey打桩示例:

main.go

package mainimport ("fmt"
)type Student struct {
}func (S *Student) GetInfoByUID(id int64) (string, error) {return "", nil
}func MyFunc(uid int64) string {var varys Studentu, err := varys.GetInfoByUID(uid)if err != nil {return "welcome"}// 这里是一些逻辑代码...return fmt.Sprintf("hello %s\n", u)
}

main_test.go

package mainimport ("bou.ke/monkey". "github.com/onsi/ginkgo". "github.com/onsi/gomega"
)var _ = Describe("Record Test", func() {Context("test myfunc", func() {var varys Studentmonkey.Patch(varys.GetInfoByUID, func(num int64) (string, error) {return "zyj", nil})ret := MyFunc(123)Expect(ret).NotTo(Equal("welcome"))})})

相关文章:

golang入门笔记——测试

测试类型&#xff1a; 单元测试&#xff1a; 规则&#xff1a; 1.所有测试文件以_test.go结尾 2.func Testxxx&#xff08;*testing.T&#xff09; 3.初始化逻辑放到TestMain中 运行&#xff1a; go test [flags][packages]Go语言中的测试依赖go test命令。 go test命令是一…...

【CSAPP】整数运算

文章目录无符号加法练习1练习2补码加法练习1练习2练习3练习4补码的非练习无符号乘法补码乘法练习1练习2练习3乘以常数练习1练习2除以2的幂练习1练习2关于整数运算的最后思考练习无符号加法 考虑两个非负整数x和y&#xff0c;满足0≤x,y<2w0 \le x, y < 2^w0≤x,y<2w&…...

使用 xshell 远程连接(使用 xftp 远程传输)

xshell 和 xftp的使用都基于ssh协议&#xff0c;我们需要先在远程服务端或者虚拟机上安装ssh服务&#xff0c;然后才能远程连接。 目录 1、什么是ssh协议&#xff1f; 2、安装 openssh (1) 安装 openssh 服务器 (2) 关闭服务器防火墙&#xff08;或者开放端口22&#xff09…...

一个例子搞懂子网划分及子网掩码的计算

前置知识&#xff1a; 1、标准ip地址分为A、B、C、D、E五类&#xff0c;分类标准是ip地址的前几个比特位的值。 我们知道ip地址是32位比特-4字节组成&#xff0c;A类地址则是由首位为0&#xff0c;首字节为网络地址&#xff0c;其余3字节为主机地址组成&#xff0c;A类网络地址…...

SPI机制源码:JDK Dubbo Spring

JDK 17 Dubbo 3.1.6 JDK SPI JDK SPI在sql驱动类加载、以及slf4j日志实现加载方面有具体实现。 示例 public class Test {private static final Logger logger LoggerFactory.getLogger(Test.class);public static void main(String[] args) {ServiceLoader<JdkSpiServi…...

Spring Security+jwt+redis+自定义认证逻辑 权限控制

Spring Securityjwtredis自定义认证逻辑 权限控制 1.拦截访问基本思路 2.创建数据库表&#xff1a;角色表&#xff08;应该6个表&#xff0c;这里只用用户表代替角色表&#xff09;、权限表、路径表、角色-权限表、权限-路径表 /* SQLyog Professional v12.14 (64 bit) MySQL…...

打游戏什么蓝牙耳机好用?打游戏比较好的蓝牙耳机

游戏耳机提供身临其境的细致声音&#xff0c;同时也是与朋友在线聊天的绝佳通信设备&#xff0c;尤其对于游戏玩家来说&#xff0c;聆听和被聆听的最佳方式之一就是游戏耳机&#xff0c;那2023年到底有哪些值得购买的游戏耳机呢&#xff1f;现在就让我们一起来看看吧。 第一款…...

炔基点击交联试剂1704097-05-1,Alkyne-A-DSBSO crosslinker,发生相应点击反应

1、理论分析&#xff1a;中文名&#xff1a;炔基-A-DSBSO crosslinker&#xff0c;英文名&#xff1a;Alkyne-A-DSBSO crosslinkerCAS号&#xff1a;1704097-05-1化学式&#xff1a;C25H32N2O12S2分子量&#xff1a;616.652、产品详情&#xff1a;外观&#xff1a;白色固体&…...

刷题记录:牛客NC24309Overplanting (Silver)

传送门:牛客 题目描述: Farmer John has purchased a new machine that is capable of planting grass within any rectangular region of his farm that is "axially aligned" (i.e., with vertical and horizontal sides). Unfortunately, the machine malfunc…...

Spring Boot中使用Sa-Token实现轻量级登录与鉴权

1. Sa-Token 介绍 Sa-Token 是一个轻量级 Java 权限认证框架&#xff0c;主要解决&#xff1a;登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 功能结构图 2. 登录认证 对于一些登录之后才能访问的接口&#xff08;例如&…...

《分布式技术原理与算法解析》学习笔记Day20

CAP理论 什么是CAP理论&#xff1f; CAP理论用来指导分布式系统设计&#xff0c;以保证系统的可用性、数据一致性等。 C&#xff0c;Consistency&#xff0c;一致性&#xff0c;指所有节点在同一时刻的数据是相同的&#xff0c;即更新操作执行结束并响应用户完成后&#xff…...

【2023-2-23】FastDeploy 安装教程

【2023-2-22】FastDeploy 安装编译教程 该测试 FastDeploy CPU版本。 1. fastDeploy库编译 1.1 官方预编译库下载 预编译库下载安装 1.2 自定义CPU版本库编译 官方编译FastDeploy教程 CMakeGUI VS 2019 IDE编译FastDeploy 本人编译教程 CMAKE_CONFIGURATION_TYPES 属性设…...

rollup.js 一个简单实用的打包工具

最近在看vue3相关的知识的时候&#xff0c;发现了一个新的打包工具&#xff0c;至少于我而言是新鲜的。它就是rollup.js。一说到JS打包、合并、压缩、模块处理等都会想到webpack&#xff0c;这是王者&#xff0c;当然入门的难度偏高。而vue3中搭配的vite运行速度确实非常快&…...

数据结构与算法之最小爬楼梯费用动态规划

继续上一道题目&#xff0c;在上一道题目的基础之上&#xff0c;我们来解决这一道爬楼梯最小费用题。一.题目描述二.思路(动态规划五部曲)确定dp数组以及下标的含义使用动态规划&#xff0c;就要有一个数组来记录状态&#xff0c;本题只需要一个一维数组dp[i]就可以了。dp[i]的…...

阿里云ACA认证如何获取?

获取阿里云ACA&#xff08;Alibaba Cloud Certification Associate&#xff09;认证&#xff0c;需要按照以下步骤进行操作&#xff1a; 注册阿里云账号。如果您还没有阿里云账号&#xff0c;请先注册一个账号。登录阿里云官网。登录后&#xff0c;进入阿里云认证中心。选择AC…...

【Python入门第十六天】Python If ... Else

Python 条件和 If 语句 Python 支持来自数学的常用逻辑条件&#xff1a; 等于&#xff1a;a b不等于&#xff1a;a ! b小于&#xff1a;a < b小于等于&#xff1a;a < b大于&#xff1a;a > b大于等于&#xff1a;a > b 这些条件能够以多种方式使用&#xff0c…...

两数之和的解法

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案…...

领导催我优化SQL语句,我求助了ChatGPT。这是ChatGPT给出的建议,你们觉得靠谱吗

作为一个程序员&#xff0c;无论在面试还是工作中&#xff0c;优化SQL都是绕不过去的难题。 为啥&#xff1f;工作之后才会明白&#xff0c;随着公司的业务量增多&#xff0c;SQL的执行效率对程系统运行效率的影响逐渐增大&#xff0c;相对于改造代码&#xff0c;优化SQL语句是…...

ArcGIS手动分割矢量面要素从而划分为多个面部分的方式:Cut Polygons Tool

本文介绍在ArcGIS下属ArcMap软件中&#xff0c;通过“Cut Polygons Tool”工具&#xff0c;对一个面要素矢量图层加以手动分割&#xff0c;从而将其划分为指定形状的多个部分的方法。 对于一个面要素矢量文件&#xff0c;有时我们需要对其加以划分&#xff0c;通过手动勾勒新的…...

【LeetCode】剑指 Offer 13. 机器人的运动范围 p92 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/ 1. 题目介绍&#xff08;13. 机器人的运动范围&#xff09; 地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动&#xff0…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...