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

go语言中的切片详解

1.概念

在Go语言中,切片(Slice)是一种基于数组的更高级的数据结构,它提供了一种灵活、动态的方式来处理序列数据。切片在Go中非常常用,因为它们可以动态地增长和缩小,这使得它们比固定大小的数组更加灵活。

2.切片的内部实现

 切片是对数组的抽象表示,它包含三个要素:

1.  指向底层数组的指针
2.  切片的长度(元素数量)
3.  切片的容量(从开始到底层数组末尾的元素数量)

切片是一个有三个字段的数据结构,这些数据结构包含 Golang 需要操作底层数组的元数据: 

 这 3 个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量)。

3.切片创建和初始化

在 Golang 中可以通过多种方式创建和初始化切片。是否提前知道切片所需的容量通常会决定如何创建切片

通过 make() 函数创建切片
使用 Golang 内置的 make() 函数创建切片,此时需要传入一个参数来指定切片的长度:

slice := make([]int, length, capacity)

这里,length是切片的长度,capacity是切片的容量。如果未指定capacity,它将等于length。

// 创建一个整型切片
// 其长度和容量都是 5 个元素
slice := make([]int, 5)

分别指定长度和容量时,创建的切片,底层数组的长度是指定的容量,但是初始化后并不能
访问所有的数组元素。

注意,Golang 不允许创建容量小于长度的切片,当创建的切片容量小于长度时会在编译时刻报错:

// 创建一个整型切片
// 使其长度大于容量
myNum := make([]int, 5, 3)

分别指定长度和容量时,创建的切片,底层数组的长度是指定的容量,但是初始化后并不能
访问所有的数组元素。

注意,Golang 不允许创建容量小于长度的切片,当创建的切片容量小于长度时会在编译时刻报错 

4.通过字面量创建切片

另一种常用的创建切片的方法是使用切片字面量,这种方法和创建数组类似,只是不需要指定[]运算符里的值。初始的长度和容量会基于初始化时提供的元素的个数确定:

// 创建字符串切片
// 其长度和容量都是 3 个元素
myStr := []string{"Jack", "Mark", "Nick"}
// 创建一个整型切片
// 其长度和容量都是 4 个元素
myNum := []int{10, 20, 30, 40}

当使用切片字面量创建切片时,还可以设置初始长度和容量。要做的就是在初始化时给出所需的长度和容量作为索引。下面的语法展示了如何使用索引方式创建长度和容量都是100个元素的切片:

// 创建字符串切片
// 使用空字符串初始化第 100 个元素
myStr := []string{99: ""}

区分数组的声明和切片的声明方式
当使用字面量来声明切片时,其语法与使用字面量声明数组非常相似。二者的区别是:如果在 [] 运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。看下面的例子:

// 创建有 3 个元素的整型数组
myArray := [3]int{10, 20, 30}
// 创建长度和容量都是 3 的整型切片
mySlice := []int{10, 20, 30}

切片的复制:

当你有一个切片或者数组的时候,当希望将其元素作为单独的参数传递给一个函数时候,可以使用...操作符

func sum(x, y, z int) int {return x + y + z
}numbers := []int{1, 2, 3}
result := sum(numbers...) // 将 numbers 切片中的元素作为参数传递给 sum 函数
fmt.Println(result) // 输出: 6

在这个例子中,numbers...将切片numbers中的元素1,2,3展开为sum函数的参数 

5.nil 和空切片

有时,程序可能需要声明一个值为 nil 的切片(也称nil切片)。只要在声明时不做任何初始化,就会创建一个 nil 切片

// 创建 nil 整型切片
var myNum []int

在 Golang 中,nil 切片是很常见的创建切片的方法。nil 切片可以用于很多标准库和内置函数。在需要描述一个不存在的切片时,nil 切片会很好用。比如,函数要求返回一个切片但是发生异常的时候。下图描述了 nil 切片的状态:

空切片和 nil 切片稍有不同,下面的代码分别通过 make() 函数和字面量的方式创建空切片: 

// 使用 make 创建空的整型切片
myNum := make([]int, 0)
// 使用切片字面量创建空的整型切片
myNum := []int{}

区别:
1.  内存分配:
•  nil 切片:没有指向任何底层数组,没有任何内存分配。
•  空切片:指向一个长度为0的底层数组,但这个数组可能已经分配了内存(尽管长度为0)。


2.  函数返回值:
•  使用 nil 可以表示“没有值”,这在错误处理和可选值中很有用。
•  空切片通常用于表示一个有效的切片,但当前没有元素。

 

package main
import "fmt"func main() {//创建一个空切片emptySlice :=make([]int,0)fmt.Println(emptySlice)//创建一个nil切片var nilSlice []intfmt.Println(nilSlice)//检查切片是否为空if len(emptySlice) == 0 {fmt.Println("emptySlice is empty")}if nilSlice == nil {fmt.Println("nilSlice is nil")}//尝试访问空切片的元素if len(emptySlice) > 0 {fmt.Println(emptySlice[0])}else {fmt.Println("emptySlice is empty")}}

•  emptySlice是一个空切片,它有长度0,但是它指向一个内存地址。
•  nilSlice是一个nil指针,它没有指向任何内存地址,因此不能用来访问任何元素。


尝试访问nil切片的元素会导致程序崩溃(panic),因为nil没有指向有效的内存。而空切片虽然长度为0,但是它是指向一个有效的内存地址的,所以可以安全地对其进行操作,比如扩展或赋值。

6.为切片中的元素赋值

对切片里某个索引指向的元素赋值和对数组里某个索引指向的元素赋值的方法完全一样。使
用 [] 操作符就可以改变某个元素的值,下面是使用切片字面量来声明切片:

// 创建一个整型切片
// 其容量和长度都是 5 个元素
myNum := []int{10, 20, 30, 40, 50}
// 改变索引为 1 的元素的值
myNum [1] = 25

切片之所以被称为切片,是因为创建一个新的切片,也就是把底层数组切出一部分。通过切片创建新切片的语法如下:

slice[i:j]
slice[i:j:k]

其中 i 表示从 slice 的第几个元素开始切,j 控制切片的长度(j-i),k 控制切片的容量(k-i),如果没有给定 k,则表示切到底层数组的最尾部。下面是几种常见的简写形式:

slice[i:]  // 从 i 切到最尾部
slice[:j]  // 从最开头切到 j(不包含 j)
slice[:]   // 从头切到尾,等价于复制整个 slice

让我们通过下面的例子来理解通过切片创建新的切片的本质:

// 创建一个整型切片
// 其长度和容量都是 5 个元素
myNum := []int{10, 20, 30, 40, 50}
// 创建一个新切片
// 其长度为 2 个元素,容量为 4 个元素
newNum := slice[1:3]

执行上面的代码后,我们有了两个切片,它们共享同一段底层数组,但通过不同的切片会看到底层数组的不同部分:

 

下面是详细的用法: 

package mainimport "fmt"func main() {// 创建一个原始切片original := []int{1, 2, 3, 4, 5}// 通过切片操作符创建新的切片a := original[:3] // 包含从索引0到索引2的元素b := original[2:] // 包含从索引2到末尾的元素c := original[:] // 创建一个新的切片,它是原始切片的一个副本// 修改原始切片original[0] = 10// 打印结果fmt.Println("Original slice:", original)  // 输出: [10 2 3 4 5]fmt.Println("Slice a:", a)               // 输出: [1 2 3]fmt.Println("Slice b:", b)               // 输出: [3 4 5]fmt.Println("Slice c:", c)               // 输出: [1 2 3 4 5]// 修改新的切片aa[0] = 100// 打印结果fmt.Println("Original slice after modifying a:", original)  // 输出: [10 2 3 4 5]fmt.Println("Slice a after modification:", a)               // 输出: [100 2 3]
}

共享底层数组的切片
需要注意的是:现在两个切片 myNum 和 newNum 共享同一个底层数组。如果一个切片修改了该底层数组的共享
部分,另一个切片也能感知到(请参考前图):

在Go语言中,切片是引用类型,这意味着它们指向底层数组的连续区域。当你通过切片操作创建一个新的切片时,新切片和原始切片可能共享同一个底层数组。如果新切片的容量足够,对新切片的修改可能会反映到原始切片上,因为它们可能指向相同的底层数组元素。

如果你需要一个与原始切片完全独立的副本,可以使用copy函数来创建一个新的底层数组。这样,对新数组的修改就不会影响原始数组。
下面是一个详细的示例,展示了如何使用copy函数创建一个完全独立的切片副本,并解释了为什么这样做可以避免对原始切片的意外修改。

package mainimport "fmt"func main() {original := []int{1,2,3,4,5}//使用切片操作符创建一个新的切片,它与原始切片共享同一个底层数组sharedSlice := original[:]independentSlice :=make([]int, len(original))copy(independentSlice, original)// 打印原始切片和两个新切片的内容fmt.Println("Original slice:", original)       // 输出: [1 2 3 4 5]fmt.Println("Shared slice:", sharedSlice)      // 输出: [1 2 3 4 5]fmt.Println("Independent slice:", independentSlice) // 输出: [1 2 3 4 5]//修改原始切片original[0] = 10fmt.Println("Modified original slice:", original) // 输出: [10 2 3 4 5]fmt.Println("Shared slice after modification:", sharedSlice) // 输出: [10 2 3 4 5]//修改独立切片independentSlice[0] = 20fmt.Println("Independent slice after modification:", independentSlice) // 输出: [20 2 3 4 5]//修改独立切片之后,原始切片不受影响fmt.Println("Original slice after independent modification:", original) // 输出: [10 2 3 4 5]fmt.Println("Shared slice after independent modification:", sharedSlice) // 输出: [10 2 3 4 5]}

代码运行结果: 

 7.切片扩容

Go 语言中的切片(slice)是一种动态数组,它允许你动态地增长和缩小。当你向切片添加元素,而切片的容量(capacity)不足以容纳更多元素时,Go 语言会自动进行扩容。扩容的具体机制如下:

  • 1.  初始容量:当你创建一个新的切片时,它会有一个初始的容量。如果你通过 make 函数创建切片,你可以指定切片的长度(length)和容量(capacity)。
  • 2.  扩容机制:当你向切片添加元素,超出当前容量时,Go 语言会进行扩容。扩容通常遵循以下规则:
  •   扩容后的容量通常是原容量的两倍,但具体增长因子可能因实现而异。
  •   如果切片的容量已经很大,扩容可能不会简单地翻倍,而是增加一个固定的数量。
  • 3.  扩容过程:扩容时,Go 语言会分配一个新的数组,并将原切片中的元素复制到新数组中。然后,新元素会被添加到新数组中。最后,切片的底层数组指针会被更新为指向新数组。
  • 4.  性能考虑:频繁的扩容可能会导致性能问题,因为每次扩容都需要分配新的内存并复制元素。为了避免这种情况,你可以通过预先分配足够的容量来减少扩容的次数。
  • 5.  手动扩容:虽然 Go 语言会自动管理切片的扩容,但你也可以手动扩容切片。例如,你可以使用 append 函数来添加元素,或者使用 copy 函数和新的切片来手动复制元素。

下面是一个简单的 Go 语言切片扩容的:

package mainimport "fmt"func main() {s := make([]int, 0, 1) // 创建一个长度为0,容量为1的切片for i := 0; i < 5; i++ {s = append(s, i)    // 向切片添加元素fmt.Printf("len=%d cap=%d slice=%v\n", len(s), cap(s), s)}
}

运行结果:

len=1 cap=1 slice=[0]
len=2 cap=2 slice=[0 1]
len=3 cap=4 slice=[0 1 2]
len=4 cap=4 slice=[0 1 2 3]
len=5 cap=8 slice=[0 1 2 3 4]

函数 append() 会智能地处理底层数组的容量增长。在切片的容量小于 1000 个元素时,总是会成倍地增加容量。一旦元素个数超过 1000,容量的增长因子会设为 1.25,也就是会每次增加 25%的容量(随着语言的演化,这种增长算法可能会有所改变)。

8.遍历切片

8.1使用for循环和索引

package mainimport "fmt"func main() {slice := []int{10, 20, 30, 40, 50}for i := 0; i < len(slice); i++ {fmt.Println("Element at index", i, "is", slice[i])}
}

8.2 使用for循环和range

使用range关键字可以同时获取索引和值,这是遍历切片的常用方法

package mainimport "fmt"func main() {slice :=[]int{10,20,30,40,50}for index,value := range slice{fmt.Printf("Index is %d and value is %d\n",index,value)}
}

8.3 使用 for 循环和 range(只获取值)

如果你不需要索引,只关心值,可以使用以下方式简化代码。

用以下方式简化代码。
package mainimport "fmt"func main() {slice := []int{10, 20, 30, 40, 50}for _, value := range slice {fmt.Println("Value is", value)}
}

8.4 使用 for 循环和 range(只获取索引)

如果你只需要索引,可以使用下划线 _ 忽略值。

package mainimport "fmt"func main() {slice := []int{10, 20, 30, 40, 50}for index, _ := range slice {fmt.Println("Index is", index)}
}

8.5 使用 for 循环和 range(遍历字符串切片)

对于字符串切片,range 会返回每个字符串中的每个字符(作为 rune 类型)。

package mainimport "fmt"func main() {slice := []string{"hello", "world"}for _, word := range slice {for _, char := range word {fmt.Printf("%c ", char)}fmt.Println()}
}

9.切片操作

9.1 使用copy函数

copy 函数是标准库 copy 包中提供的一个函数,用于将一个切片的内容复制到另一个切片中。它接受两个切片作为参数:源切片和目标切片,并返回复制的元素数量。

package mainimport "fmt"func main() {src :=[]int{1,2,3,4,5}dst :=make([]int,5)//从src复制到dstcopied :=copy(dst,src)fmt.Println("Copied element",copied)fmt.Println("Destination",dst)
}

9.2 使用 append 函数

  •   第一个参数是目标切片,用于接收新添加的元素。
  •  后续参数是要添加到切片中的元素。
  •   使用 append 进行切片复制
  • 在 append([]int(nil), original...) 中:
  •   []int(nil) 创建了一个类型为 []int 的空切片。这个切片的长度和容量都是0。
  •  original... 是 Go 语言的变参语法,它将 original 切片中的所有元素作为独立的参数传递给 append 函数。
package mainimport "fmt"func main() {original := []int{1, 2, 3, 4, 5}copy := append([]int(nil), original...)fmt.Println("Original slice:", original)fmt.Println("Copy slice:", copy)
}

在这个例子中,copy 切片是通过 append 函数创建的,它包含了 original 切片的所有元素。这种方法不仅代码简洁,而且性能也很好,因为它避免了不必要的内存分配和复制操作。
总结来说,append([]int(nil), original...) 是一种利用 append 函数的灵活性和智能内存管理来高效复制切片的方法。

9.3手动复制

你也可以通过遍历源切片并手动将每个元素赋值到新的切片中来实现复制。

package mainimport ("fmt"
)func main() {src := []int{1, 2, 3, 4, 5}dst := make([]int, len(src)) // 创建一个相同长度的新切片for i := range src {dst[i] = src[i]}fmt.Println("Source slice:", src)fmt.Println("Destination slice:", dst)
}

这种方法虽然直接,但效率较低,特别是对于大型切片。

注意事项

•  当使用 copy 函数时,确保目标切片有足够的容量来接收所有元素,否则它只会复制目标切片的容量允许的部分。
•  使用 append 函数时,虽然方便,但可能会因为扩容操作而增加额外的性能开销。
•  手动复制虽然控制更精细,但代码更复杂,且容易出错。
在实际应用中,选择哪种方法取决于具体的需求和性能考虑。对于大多数情况,copy 函数提供了一个简单而高效的方式来复制切片。

相关文章:

go语言中的切片详解

1.概念 在Go语言中&#xff0c;切片&#xff08;Slice&#xff09;是一种基于数组的更高级的数据结构&#xff0c;它提供了一种灵活、动态的方式来处理序列数据。切片在Go中非常常用&#xff0c;因为它们可以动态地增长和缩小&#xff0c;这使得它们比固定大小的数组更加灵活。…...

ElK 8 收集 Nginx 日志

1. 说明 elk 版本&#xff1a;8.15.0 2. 启个 nginx 有 nginx 可以直接使用。我这里是在之前环境下 docker-compose.yml 中启动了个 nginx&#xff1a; nginx:restart: alwaysimage: nginx:1.26.1ports:- "80:80"- "443:443"volumes:#- ./nginx/html:/…...

Xv6驱动(四):CLINT

阅读材料 Xv6代码&#xff1a;memlayout.h、start.c、kernelvec.S教材5.4节 CLINT内存映射 实际上&#xff0c;CLINT还包括若干个MSIP寄存器&#xff0c;用来触发软件中断&#xff0c;但是在Xv6中不考虑软件中断&#xff0c;因此这些寄存器也不用考虑 // core local interr…...

【LInux】HTTPS是如何实现安全传输的

1. 客户端发起HTTPS连接请求 当浏览器请求一个HTTPS网址时&#xff0c;客户端&#xff08;例如浏览器&#xff09;会向服务器发起一个HTTPS请求。 2. 服务器返回数字证书 服务器收到请求后&#xff0c;会向客户端发送包含公钥的数字证书。数字证书由**权威认证机构&#xff…...

英飞凌PSoC4000T的GPIO中断示例工程

关于PSoC4000T的初步介绍见:英飞凌MCU第五代高性能CAPSENSE技术PSoC4000T_psoc 4000t-CSDN博客 下面这个工程,在modustoolbox中可编译、下载到开发板、debug调试。 编译时会用到mtb_shared这个库: 已经pdl这个periperal driver library库:...

物联网(IoT)中基于深度学习的入侵检测系统的综合综述

这篇论文是一篇全面的综述&#xff0c;标题为“A comprehensive survey on deep learning-based intrusion detection systems in Internet of Things (IoT)”&#xff0c;作者是Qasem Abu Al-Haija和Ayat Droos。论文主要探讨了在物联网(IoT)环境中基于深度学习的入侵检测系统…...

《成都体育学院学报》

投稿指南 成都体育学院学报属于体育类型期刊&#xff0c;由成都体育学院主办&#xff0c;国内统一刊号&#xff1a;51-1097/G8&#xff0c;国际标准刊号&#xff1a;1001-9154&#xff0c;双月&#xff0c;面向国内外公开发行。 一、来稿必须是作者独立取得的原创性学术研究成…...

Flask-JWT-Extended登录验证, 不用自定义

"""安装:pip install Flask-JWT-Extended创建对象 初始化与app绑定jwt JWTManager(app) # 初始化JWTManager设置 Cookie 的选项:除了设置 cookie 的名称和值之外&#xff0c;你还可以指定其他的选项&#xff0c;例如&#xff1a;过期时间 (max_age)&#xff1…...

rpm 与 yum

11 rpm -qa | grep openssh rpm与 yum CentOS仅删除软件包本身而不删除依赖 https://blog.csdn.net/kangshuaibi/article/details/125472204...

几种修改docker默认存储位置的方法

需求 docker容器存放目录磁盘空间满了&#xff0c;需要转移数据&#xff0c;修改Docker默认存储位置 解决方法 方法&#xff11;&#xff1a;迁移到新目录 停止docker服务。 1systemctl stop docker; //每个liunx版本的命令不一样。创建新的docker目录&#xff0c;执行命令df…...

istio中如何使用serviceentry引入外部服务

假设需要引入一个外部服务&#xff0c;外部服务ip为10.10.102.90&#xff0c;端口为32033. 引入到istio中后&#xff0c;我想通过域名gindemo.test.ch:9090来访问这个服务。 serviceentry yaml内容如下&#xff1a; apiVersion: networking.istio.io/v1beta1 kind: ServiceEn…...

模仿抖音用户ID加密ID的算法MB4E,提高自己平台ID安全性

先看抖音的格式 对ID加密的格式 MB4EENgLILJPeQKhJht-rjcc6y0ECMk_RGTceg6JBAA 需求是 同一个ID 比如 413884936367560 每次获取得到的加密ID都是不同的&#xff0c;最终解密的ID都是413884936367560 注意这是一个加密后可解密原文的方式&#xff0c;不是单向加密 那么如下进行…...

solidwork镜像实体

效果如下&#xff1a; 可以看到这两条线是对称的。 第一步&#xff0c;点击这条要镜像的边&#xff0c;接着点击镜像实体。 然后选择镜像轴&#xff0c;即可...

第6天:趋势轮动策略开发(年化18.8%,大小盘轮动加择时)

原创内容第655篇&#xff0c;专注量化投资、个人成长与财富自由。 轮动策略是一种投资策略&#xff0c;它涉及在不同的资产类别、行业或市场之间进行切换&#xff0c;以捕捉市场机会并优化投资组合的表现。 这种策略的核心在于识别并利用不同资产或市场的相对强弱&#xff0c…...

米客方德SD NAND 掉电测试

SD NAND 异常上下电测试的作用 SD NAND 异常上下电测试是一项关键的测试步骤&#xff0c;对确保SD NAND在不同电源条件下的稳定性和可靠性至关重要。 通过模拟正常和异常电源情况&#xff0c;测试可以验证设备的电源管理功能、检测潜在错误和异常行为&#xff0c;并评估设备在…...

深入探索Android开发之Kotlin核心技术学习大全

Android作为全球最流行的移动操作系统之一&#xff0c;其开发技能的需求日益增长。本文将为您介绍一套专为Android开发者设计的Kotlin核心技术学习资料&#xff0c;包括详细的学习大纲、PDF文档、源代码以及配套视频教程&#xff0c;帮助您从Kotlin基础到高级特性&#xff0c;再…...

langchain报错记录(js)

文章目录 [ERR_PACKAGE_PATH_NOT_EXPORTED]报错&#xff1a;报错语句&#xff1a;思路&#xff1a;解决方法&#xff1a; [ERR_PACKAGE_PATH_NOT_EXPORTED] 报错&#xff1a; Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath ‘./dist/prompts/’ is not defined by…...

VSCode调试Unity准备工作

一.Unity设置VSCode为默认编辑器 Unity编辑器中Edit-Preferences-External Tools中选择VSCode 二.VSCode安装Unity插件 三.Unity的Visual Studio Editor升至最新 Window->Package Manager->Visual Studio Editor 四.下载配置.Net 8.0 安装之前VSCode会提示你下载.Net …...

缓存穿透 问题(缓存空对象)

文章目录 1、缓存穿透2、缓存空对象3、AlbumInfoApiController --》getAlbumInfo()4、AlbumInfoServiceImpl --》getAlbumInfo()5、RedisConstant6、请求缓存不存在的数据 1、缓存穿透 2、缓存空对象 3、AlbumInfoApiController --》getAlbumInfo() GetMapping("getAlbumI…...

Vue3:mitt实现组件通信

目录 一.性质 1.轻量级 2.单例 3.异步 4.事件绑定与解绑 二.作用 1.组件间通信 2.解耦 3.状态管理 4.事件的集中处理 三.使用 1.安装mitt 2.引入mitt&#xff1b;调用mitt&#xff1b;暴露mitt 3.组件1 4.组件2 四.代码 1.组件1 2.组件2 五.效果 一.性质 1…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...