Go复合类型之数组类型

news2024/12/24 20:58:24

Go复合类型之数组

文章目录

  • Go复合类型之数组
    • 一、数组(Array)介绍
      • 1.1 基本介绍
      • 1.2 数组的特点
    • 二、数组的声明与初始化
      • 2.1 数组声明
      • 2.2 常见的数据类型声明方法
      • 2.3 数组的初始化
        • 方式一:使用初始值列表初始化数组
        • 方法二:根据初始值个数自动推断数组长度
        • 方法三:通过指定索引值初始化数组
    • 三、数组的常用操作
      • 3.1 数组的遍历
        • 方法1:使用 `for` 循环遍历
        • 方法2:使用 `for range` 遍历
      • 3.2 获取数组长度
      • 3.3 访问数组元素
      • 3.4 修改数组元素
      • 3.5 数组的切片
      • 3.6 数组的比较
      • 3.7 数组作为函数参数
    • 四、数组类型在内存中的实际表示
    • 五、数组是值类型(数组拷贝和传参)
    • 六、多维数组
      • 6.1 二维数组
        • 6.2.1 二维数组的定义
        • 6.2.2 二维数组的遍历
      • 6.3 多维数组介绍
      • 6.4 多维数组声明与初始化
    • 七、Go 数组和以往认知的数组的区别

一、数组(Array)介绍

1.1 基本介绍

  • Go语言中数组是一个值类型(value type)。
  • 数组就是指一系列同一类型数据的集合
  • 数组是一个长度固定的、由同构类型元素组成的连续序列。
  • 数组类型包含两个重要属性:元素的类型和数组长度(元素的个数)
  • 数组长度在定义时确定,不可变更。
  • 数组类型表示为:[大小]T,比如[5]int表示拥有5个int元素的数组。
  • 如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。

1.2 数组的特点

  1. 长度固定:一旦声明和初始化,数组的长度就不能更改。
  2. 类型一致:所有数组元素必须是相同类型。
  3. 连续的内存分配:数组的所有元素在内存中是连续分配的,这有助于快速访问元素。
  4. 值类型:数组是值类型,它们在传递给函数时会被复制,而不是引用。

二、数组的声明与初始化

2.1 数组声明

定义方式如下:

var arr [N]T
// 或者使用短变量申明
arr := [N]T{}

这里我们声明了一个数组变量 arr,其中:

  • arr为数组变量名
  • N表示数组长度
  • T表示数组存储类型

**如果两个数组类型的元素类型 T 与数组长度 N 都是一样的,那么这两个数组类型是等价的,如果有一个属性不同,它们就是两个不同的数组类型。**下面这个示例很好地诠释了这一点:

func foo(arr [5]int) {}
func main() {
    var arr1 [5]int
    var arr2 [6]int
    var arr3 [5]string

    foo(arr1) // ok
    foo(arr2) // 错误:[6]int与函数foo参数的类型[5]int不是同一数组类型
    foo(arr3) // 错误:[5]string与函数foo参数的类型[5]int不是同一数组类型
}  

在这段代码里,arr2 与 arr3 两个变量的类型分别为[6]int 和 [5]string,前者的长度属性与[5]int 不一致,后者的元素类型属性与[5]int 不一致,因此这两个变量都不能作为调用函数 foo 时的实际参数。

2.2 常见的数据类型声明方法

var a [5]byte //长度为5的数组,每个元素为一个字节
var b [2*N] struct { x, y int5 } //复杂类型数组
var c [5]*int // 指针数组
var d [2][3]int //二维数组
var e [2][3][4]int //等同于[2]([3]([4]int))

2.3 数组的初始化

方式一:使用初始值列表初始化数组

这种方式在声明数组的同时,通过提供初始值列表来初始化数组元素。如果没有为数组的每个元素提供初始值,剩余的元素将会使用默认值。对于数值类型(如int),默认值为0;对于字符串类型(如string),默认值为空字符串。

	var testArray [3]int        //数组会初始化为int类型的零值
	var numArray = [3]int{1, 2} //使用指定的初始值完成初始化
	var strArray = [3]string{}
	fmt.Println(testArray) //[0 0 0]
	fmt.Println(numArray)  //[1 2 0]
	fmt.Println(strArray)  //[  ] 默认值空字符串
方法二:根据初始值个数自动推断数组长度

在这种方式下,你可以在声明数组时省略长度,并使用...操作符,编译器会根据提供的初始值的个数自动推断数组的长度。这使得代码更加简洁,不需要显式指定数组的长度。

	arr := [...]int{1, 2, 3}                 // [1 2 3]
	fmt.Println(arr)                         // [1 2]
	fmt.Printf("type of numArray:%T\n", arr) // type of numArray:[3]int
方法三:通过指定索引值初始化数组

这种方式允许你在数组的指定索引位置提供初始值,其他位置会被初始化为默认值。在示例中,a[1]被初始化为1,a[3]被初始化为5,其他位置默认为0。

func main() {
	a := [...]int{1: 1, 3: 5}
	fmt.Println(a)                  // [0 1 0 5]
	fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}

三、数组的常用操作

3.1 数组的遍历

遍历数组有两种方法,使用for循环和使用for range语句

方法1:使用 for 循环遍历
var a = [...]string{"贾", "维", "斯"}
for i := 0; i < len(a); i++ {
    fmt.Println(a[i])
}

这是传统的for循环遍历数组的方式,它使用一个循环变量i来迭代数组的索引,然后使用a[i]来访问数组的元素。这种方式适用于需要访问数组索引或按照索引进行操作的情况。

方法2:使用 for range 遍历
  var a = [...]string{"贾", "维", "斯"}
	for index, value := range a {
		fmt.Println(index, value)
	}

for range语句更加简洁和直观。它会返回数组的索引和对应的值,这使得遍历数组变得非常方便。通常情况下,使用for range遍历数组更加推荐,特别是当你只需要访问数组的值而不需要索引时。

需要注意的是,for range遍历数组会创建一个值的拷贝,而不是原始数组的引用。如果你需要在循环内修改数组元素的值,并且希望这些修改在循环结束后对原始数组生效,那么你应该使用for循环,因为它允许你直接访问数组的元素。

3.2 获取数组长度

在Go语言中,数组长度在定义后就不可更改,在声明时长度可以为一个常量或者一个常量表达式(常量表达式是指在编译期即可计算结果的表达式)。数组的长度是该数组类型的一个内置常量,可以用Go语言的内置函数len()来获取。

arrLength := len(arr)

举个例子:

arr := [5]int{10, 20, 30, 40, 50}
length := len(arr) // 获取数组的长度,length的值为5

3.3 访问数组元素

  • 数组的下标值是从 0 开始的

  • 使用数组变量名加索引下标的方式就可以访问数组对应位置的元素。

var arr = [6]int{11, 12, 13, 14, 15, 16}
fmt.Println(arr[0], arr[5]) // 11 16
fmt.Println(arr[-1])        // 错误:下标值不能为负数
fmt.Println(arr[8])         // 错误:小标值超出了arr的长度范围

3.4 修改数组元素

  • 同样是通过数组变量名加索引下标的方式就可以修改数组对应位置的元素。
arr := [5]int{1, 2, 3, 4, 5}

arr[0] = 100 // 修改数组第一个元素
arr[1] = 200 // 修改数组第二个元素

fmt.Println(arr) // 输出:[100 200 3 4 5]

3.5 数组的切片

使用切片来从数组中创建一个动态长度的子集。切片是对数组的引用,因此它们与原始数组共享底层数据。

arr := [5]int{10, 20, 30, 40, 50}
slice := arr[1:4] // 创建一个包含arr的索引1到3的切片,slice的值为{20, 30, 40}

3.6 数组的比较

你可以使用==运算符来比较两个数组是否相等。两个数组相等的条件是它们的长度和元素都相同。

	arr1 := [3]int{1, 2, 3}
	arr2 := [3]int{1, 2, 3}
	isEqual := arr1 == arr2 
	fmt.Println(isEqual)  // isEqual为true

3.7 数组作为函数参数

数组是值类型,当它作为函数参数传递时,会复制整个数组。这意味着在函数内对数组的修改不会影响原始数组

func modify(arr [3]int) {
  arr[0] = 100 
}

func main() {
  a := [3]int{1, 2, 3}

  modify(a)

  fmt.Println(a) // 输出[1, 2, 3]
}
// 在modify函数中,我们把数组arr的第一个元素修改为了100。但是回到main函数后,打印数组a时,它的第一个元素仍然是1。

如果需要在函数内修改数组,需要传入数组指针:

func modify(arr *[3]int) {
	(*arr)[0] = 100
}

func main() {
	a := [3]int{1, 2, 3}

	modify(&a)

	fmt.Println(a) // 输出[100 2 3]
}

四、数组类型在内存中的实际表示

了解了数组类型的定义和操作后,我们再来看看数组类型在内存中的实际表示是怎样的,这是数组区别于其他类型,也是我们区分不同数组类型的根本依据。

**数组类型不仅是逻辑上的连续序列,而且在实际内存分配时也占据着一整块内存。**Go 编译器在为数组类型的变量实际分配内存时,会为 Go 数组分配一整块、可以容纳它所有元素的连续内存,如下图所示:

WechatIMG190

我们从这个数组类型的内存表示中可以看出来,这块内存全部空间都被用来表示数组元素,所以说这块内存的大小,就等于各个数组元素的大小之和。如果两个数组所分配的内存大小不同,那么它们肯定是不同的数组类型。Go 提供了预定义函数 len 可以用于获取一个数组类型变量的长度,通过 unsafe 包提供的 Sizeof 函数,我们可以获得一个数组变量的总大小,如下面代码:

var arr = [6]int{1, 2, 3, 4, 5, 6}
fmt.Println("数组长度:", len(arr))           // 6
fmt.Println("数组大小:", unsafe.Sizeof(arr)) // 48

数组大小就是所有元素的大小之和,这里数组元素的类型为 int。在 64 位平台上,int 类型的大小为 8,数组 arr 一共有 6 个元素,因此它的总大小为 6x8=48 个字节。

五、数组是值类型(数组拷贝和传参)

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。

func modifyArray(x [3]int) {
	x[0] = 100
}

func modifyArray2(x [3][2]int) {
	x[2][0] = 100
}
func main() {
	a := [3]int{10, 20, 30}
	modifyArray(a) //在modify中修改的是a的副本x
	fmt.Println(a) //[10 20 30]
	b := [3][2]int{
		{1, 1},
		{1, 1},
		{1, 1},
	}
	modifyArray2(b) //在modify中修改的是b的副本x
	fmt.Println(b)  //[[1 1] [1 1] [1 1]]
}

注意:

  1. 数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。
  2. [n]*T表示指针数组,*[n]T表示数组指针 。

六、多维数组

6.1 二维数组

  • 二维数组本质就是数组中又嵌套数组
6.2.1 二维数组的定义

组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type

variable_type 为 Go 语言的数据类型,arrayName 为数组名,二维数组可认为是一个表格,x 为行,y 为列,下图演示了一个二维数组 a 为三行四列:

img

举个栗子,二维数组定义并初始化

func main() {
	a := [3][2]string{
		{"北京", "上海"},
		{"广州", "深圳"},
		{"成都", "重庆"},
	}
	fmt.Println(a) //[[北京 上海] [广州 深圳] [成都 重庆]]
	fmt.Println(a[2][1]) //支持索引取值:重庆
}
6.2.2 二维数组的遍历
func main() {
	a := [3][2]string{
		{"北京", "上海"},
		{"广州", "深圳"},
		{"成都", "重庆"},
	}
	for _, v1 := range a {
		for _, v2 := range v1 {
			fmt.Printf("%s\t", v2)
		}
		fmt.Println()
	}
}

输出:

北京	上海	
广州	深圳	
成都	重庆	

注意: 多维数组只有第一层可以使用...来让编译器推导数组长度。例如:

//支持的写法
a := [...][2]string{
	{"北京", "上海"},
	{"广州", "深圳"},
	{"成都", "重庆"},
}
//不支持多维数组的内层使用...
b := [3][...]string{
	{"北京", "上海"},
	{"广州", "深圳"},
	{"成都", "重庆"},
}

6.3 多维数组介绍

多维数组是一种数组的扩展,它允许在一个数组中存储多个维度的数据。在许多编程语言中,通常可以创建二维数组、三维数组,甚至更高维度的数组。多维数组在处理具有多个维度的数据集时非常有用,比如矩阵、图像等。

多维数组的基本思想是使用多个索引来引用数组中的元素。例如,二维数组可以看作是一个表格,需要两个索引来定位某个元素,第一个索引表示行号,第二个索引表示列号。三维数组则需要三个索引,依此类推。以下是多维数组的一些基本概念:

  • 数组类型自身也可以作为数组元素的类型,这样就会产生多维数组
  • 多维数组在Go语言中不太常用,大多数情况下使用切片(slice)就可以实现多维数据结构。
  • 但是在某些需要明确数组大小的情况下,多维数组也会用到。

6.4 多维数组声明与初始化

Go 语言支持多维数组,以下为常用的多维数组声明方式:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

比如下面的变量 mArr 的类型就是一个多维数组[2][3][4]int

var mArr [2][3][4]int

多维数组也不难理解,我们以上面示例中的多维数组类型为例,我们从左向右逐维地去看,这样我们就可以将一个多维数组分层拆解成这样:WechatIMG191

我们从上向下看,首先我们将 mArr 这个数组看成是一个拥有两个元素,且元素类型都为[3] [4]int 的数组,就像图中最上层画的那样。这样,mArr 的两个元素分别为 mArr[0]mArr [1],它们的类型均为[3] [4]int,也就是说它们都是二维数组。

而以 mArr[0]为例,我们可以将其看成一个拥有 3 个元素且元素类型为[4]int 的数组,也就是图中中间层画的那样。这样 mArr[0]的三个元素分别为 mArr[0][0]mArr[0][1]以及 mArr[0][2],它们的类型均为[4]int,也就是说它们都是一维数组。

图中的最后一层就是 mArr[0]的三个元素,以及 mArr[1]的三个元素的各自展开形式。以此类推,你会发现,无论多维数组究竟有多少维,我们都可以将它从左到右逐一展开,最终化为我们熟悉的一维数组。

不过,虽然数组类型是 Go 语言中最基础的复合数据类型,但是在使用中它也会有一些问题。数组类型变量是一个整体,这就意味着一个数组变量表示的是整个数组。这点与 C 语言完全不同,在 C 语言中,数组变量可视为指向数组第一个元素的指针。这样一来,无论是参与迭代,还是作为实际参数传给一个函数 / 方法,Go 传递数组的方式都是纯粹的值拷贝,这会带来较大的内存拷贝开销

这时,你可能会想到我们可以使用指针的方式,来向函数传递数组。没错,这样做的确可以避免性能损耗。其实,Go 语言为我们提供了一种更为灵活、更为地道的方式 ,切片,来解决这个问题

七、Go 数组和以往认知的数组的区别

在Go语言中,数组和一般认知中的数组(如C、C++等语言中的数组)有一些重要区别和特点。下面是关于Go语言中数组的一些特点和区别:

  1. 固定长度的序列: 与一般认知中的数组类似,Go中的数组也是一种同一种数据类型的固定长度的序列。这意味着一旦数组被定义,其长度不能更改。
  2. 数组定义: 在Go中,数组的定义形式为var a [len]Type,其中len表示数组的长度,Type表示数组元素的类型。例如,var a [5]int定义了一个包含5个整数的数组。
  3. 长度是类型的一部分: 数组的长度是数组类型的一部分。因此,[5]int[10]int是不同的类型。这意味着不能将一个长度为5的数组赋值给一个长度为10的数组,它们是不兼容的。
  4. 下标访问: 类似于其他语言的数组,Go中的数组也可以通过下标进行访问,下标从0开始,最后一个元素的下标是len-1。可以使用for循环或range来遍历数组。
  5. 访问越界: 如果尝试访问数组中的索引超出合法范围,Go将会引发运行时错误,称为"越界访问",而不会继续执行程序。这是一种保护机制,以防止访问无效的内存。
  6. 数组是值类型: 在Go中,数组是值类型,这意味着当你将一个数组赋值给另一个数组时,实际上是将整个数组的副本复制给了目标数组,而不是引用。因此,在对副本进行更改时,不会影响原始数组。
  7. 支持比较操作: Go中的数组支持相等(==)和不等(!=)操作符,因为数组在定义后会被初始化,所以它们是可比较的。
  8. 指针数组和数组指针: Go支持指针数组和数组指针的概念。指针数组是一个包含指向某种类型的指针的数组,而数组指针是指向数组的指针。

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

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

相关文章

温故知新:dfs模板-843. n-皇后问题

n−n−皇后问题是指将 nn 个皇后放在 nnnn 的国际象棋棋盘上&#xff0c;使得皇后不能相互攻击到&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 nn&#xff0c;请你输出所有的满足条件的棋子摆法。 输入格式 共一行&#xff0c;包含整数 n…

通过位运算,实现单字段标识多个状态位

可能经常有如下这种需求: 需要一张表,来记录学员课程的通过与否. 课程数量不确定,往往很多,且会有变动,随时可能新增一门课. 这种情况下,在设计表结构时,一门课对应一个字段,就有些不合适, 因为不知道课程的具体数量,也无法应对后期课程的增加. 考虑只用一个状态标志位,利用位运…

精确到区县级街道乡镇行政边界geojson格式矢量数据的获取拼接实现Echarts数据可视化大屏地理坐标信息地图的解决方案

在Echarts制作地理信息坐标地图时&#xff0c;最麻烦的就是街道乡镇级别的行政geojson的获取&#xff0c; 文件大小 788M 文件格式 .json格式&#xff0c;由于是大文件数据&#xff0c;无法直接使用记事本或者IDE编辑器打开&#xff0c;推荐Dadroit Viewer&#xff08;国外…

【代码实践】HAT代码Window平台下运行实践记录

HAT是CVPR2023上的自然图像超分辨率重建论文《activating More Pixels in Image Super-Resolution Transformer》所提出的模型。本文旨在记录在Window系统下运行该官方代码&#xff08;https://github.com/XPixelGroup/HAT&#xff09;的过程&#xff0c;中间会遇到一些问题&am…

linux系统中常见注册函数的使用方法

大家好&#xff0c;今天给大家分享一下&#xff0c;linux系统中常见的注册函数register_chrdev_region()、register_chrdev()、 alloc_chrdev_region()的使用方法​。 一、函数包含的头文件&#xff1a; 分配设备编号&#xff0c;注册设备与注销设备的函数均在fs.h中申明&…

OMV6 安装Extras 插件失败的解决方法

# Time: 2023/10/07 #Author: Xiaohong # 运行环境: OS: OMV6 # 功能: 安装Extras 插件失败的解决方法 问题描述&#xff1a;OMV6 安装插件omv-extras&#xff0c;只能按如下提示的命令行&#xff0c;但安装过程中&#xff0c;会提示raw.githubusercontent.com 无法访问插…

校招秋招,性格和职业有关系吗?

企业在招聘应届毕业生时不再局限于普通的面试或者笔试&#xff0c;在互联网时代&#xff0c;为了能够更好的匹配需要的优质人才&#xff0c;企业会通过各种测试来提高招聘的准确率以及成功率。也许以前很多人都听说过性格和职业是有一定关系的&#xff0c;但是如何确定自己的性…

win安装ESPHome教程

感谢 Little-Bear-Bear 博主的教程,ESPHome入门 windows环境安装 -01 1.安装python 从Python官方网站下载。 确保选中“将Python添加到PATH”&#xff0c;然后一直通过 安装。 安装后重新启动计算机 winR 。按回车键。cmd python --version输入 查看 是否安装成功 python…

基于虚拟同步发电机控制的双机并联Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于LADRC自抗扰控制的VSG三相逆变器预同步并网控制策略(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

8.2 JUC - 4.Semaphore

目录 一、是什么&#xff1f;二、简单使用三、semaphore应用四、Semaphore原理 一、是什么&#xff1f; Semaphore&#xff1a;信号量&#xff0c;用来限制能同时访问共享资源的线程上限 二、简单使用 public class TestSemaphore {public static void main(String[] args) …

freeRTOS的数据类型定义(portmacro.h文件里)

freeRTOS的数据类型定义&#xff08;portmacro.h文件里&#xff09; 解读&#xff1a; https://www.bilibili.com/video/BV1n8411y7DF/?buvidXY4F2994565924F2FFA7142AEEB2220A602A4&is_story_h5false&mid%2B8iBjJuKH0VIWaMd8h0wSQ%3D%3D&p1&plat_id114&s…

铭控传感亮相2023国际物联网展,聚焦“多场景物联感知方案”应用

金秋九月&#xff0c;聚焦IoT基石技术&#xff0c;荟萃最全物联感知企业&#xff0c;齐聚IOTE 2023第20届国际物联网展深圳站。铭控传感携智慧楼宇&#xff0c;数字工厂&#xff0c;智慧消防&#xff0c;智慧泵房等多场景物联感知方案及多品类无线传感器闪亮登场&#xff0c;现…

windows内核编程(2021年出版)笔记

1. Windows内部概览 1.1 进程 进程包含以下内容&#xff1a; 可执行程序&#xff0c;代码和数据私有的虚拟地址空间&#xff0c;分配内存时从这里分配主令牌&#xff0c;保存进程默认安全上下文&#xff0c;进程中的线程执行代码时会用到它私有句柄表&#xff0c;保存进程运…

C语言之共用体、枚举类型、typedef

共用体 共用体的所有成员共享同一个内存地址 插入一个知识点&#xff1a;字符串不可以直接赋值&#xff0c;要不就在定义的时候赋值&#xff0c;要不就只能使用scanf函数赋值或者<string>中的strcpy赋值 证明 如果要同时访问联合体中多个成员的值...... 则会出现以下情…

自动化项目实战->测试博客系统

1.熟悉项目-->哪些场景容易出现问题 2.针对核心流程设计测试用例(手工测试用例) 3.将手工测试用例转换为自动化测试用例 4.部署到服务器 一、针对核心流程设计测试用例 二、将手工测试用例转换为自动化测试用例 2.1设计自动化测试用例的代码结构 初始化动作:BeforeAll--…

[NISACTF 2022]popchains - 反序列化+伪协议

[NISACTF 2022]popchains 一、解题流程二、小小疑惑 一、解题流程 1、链条&#xff1a;Road_is_Long&#xff08;construct->wakeup【page$r】-> toString【string$m】&#xff09;-> Make_a_Change&#xff08;construct->get【effort$t】&#xff09;-> Try_W…

数据压缩与管理:掌握Linux VDO和LVM的力量

1.逻辑卷(LVM&#xff0c;Logical Volume Management) 动态的为服务器磁盘添加空间&#xff0c;而不会影响原磁盘的数据&#xff0c;也不需要对原始磁盘重新分区。 1.1 LVM介绍 以下是LVM的示意图&#xff1a; 我们拿到一块硬盘后首先对齐进行划分分区&#xff0c;也就得到…

Web:前端常用的几种Http请求GET和POST样例

1、简述 在Web开发过程中&#xff0c;少不了发起Http请求服务端的接口数据&#xff0c;在不同的框架中使用了不同的Http请求方式&#xff0c;常用的请求有fetch、 ajax、 axios、XMLHttpRequest、request&#xff0c;以下样例仅供参考。 2、Fetch Fetch API 是一种 JavaScr…

Redis的五种常用数据类型

1.字符串 String的数据结构是简单的Key-Value模型&#xff0c;Value可以是字符串&#xff0c;也可以是数字。 String是Redis最基本的类型&#xff0c;是二进制安全的&#xff0c;意味着Redis的string可以包含任何数据&#xff0c;比如jpg图片。 一个redis中字符串value最大是…