Go 1.19.4 序列化和反序列化-Day 16

news2024/12/24 22:10:07

1. 序列化和反序列化

1.1 序列化

1.1.1 什么是序列化

序列化它是一种将程序中的数据结构(map、slice、array等)或对象状态转换成一系列字节序列的过程,这些字节可以被存储或通过网络发送。

在GO中,序列化通常涉及到将结构体或其他数据类型转换成JSON、XML、二进制等格式。

1.1.2 为什么要序列化

内存中的map、slice、array以及各种对象,如何保存到一个文件中? 如果是自己定义的结构体的实例,如何保存到一个文件中?

这就需要设计一套协议,按照某种规则,把内存中数据保存到文件中,而文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件,这就是序列化。 

序列化的需求主要来自于以下几个方面:

  1. 数据持久化:我们需要将数据保存到硬盘或数据库中,以便在程序关闭后再次启动时能够恢复数据。
  2. 网络通信:在分布式系统中,服务之间需要通过网络进行通信,序列化是将数据转换成适合网络传输格式的关键步骤。
  3. 跨语言交互:不同的编程语言可能有不同的数据结构表示方式,序列化提供了一种通用的方法来确保数据在不同语言之间能够被正确理解和使用。

 1.1.3 何时进行序列化

  1. 数据存储:在将数据写入文件或数据库之前。
  2. 网络传输:在将数据发送到远程服务之前。
  3. 数据交换:在不同系统或服务之间交换数据时。

1.1.4 如何进行序列化

  1. 选择序列化格式:根据需求选择合适的序列化格式,如JSON、XML或二进制。
  2. 定义数据结构:在GO中定义要序列化的数据结构,通常是通过定义一个或多个结构体。
  3. 序列化数据:使用GO标准库中的序列化函数,如json.Marshalxml.Marshal,将数据结构转换成字节流。

 1.2 反序列化

反序列化是将序列化的数据(通常是字节流)转换回内存中的数据结构的过程。

1.3 总结

  • serialization 序列化:将内存中对象存储下来,把它变成一个个字节。转为二进制数据。
  • deserialization 反序列化:将文件的一个个字节恢复成内存中对象。从 二进制 数据中恢复序列化保存到文件就是持久化。

可以将数据序列化后持久化,或者网络传输;也可以将从文件中或者网络接收到的字节序列反序列化。

我们可以把数据和二进制序列之间的相互转换称为二进制序列化、反序列化,把数据和字符序列之间的相互转换称为字符序列化、反序列化。
 

字符序列化:JSON、XML等。
 

二进制序列化:Protocol Buffers、MessagePack等。

2. Json(文本序列化)

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于1999年发布的ES3 (ECMAScript是w3c组织制定的JavaScript规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

JSON是什么?字符串!

应该说,目前JSON得到几乎所有浏览器的支持。参看 http://json.org/。

2.1 JSON的数据类型

2.1.1 值

双引号引起来的字符串、数值、true和false、null、对象、数组,这些都是值。

2.1.2 字符串

由双引号包围起来的任意字符的组合,可以有转义字符。

2.1.3 数值

有正负,有整数、浮点数。

 

2.1.4 对象

无序的键值对的集合,格式: {"key1":value1, ... ,"keyn":valulen},key必须是一个字符串,需要双引号包围这个字符串。 value可以是任意合法的值。

2.1.5 数组

有序的值的集合 格式:[val1,...,valn]。

2.1.6 示例

{
	"person": [
	 {
	"name": "tom",
	  "age": 18
	 },
	 {
	"name": "jerry",
	"age": 16
	 }
	 ],
	"total": 2
}

特别注意:JSON是字符串,是文本。JavaScript引擎可以将这种字符串解析为某类型的数据。

2.2 json包

1. json.Marsha(序列化)

        语法:

                func json.Marshal(v any) ([]byte, error)

        参数:

              v any:  v 是一个空接口类型(interface{}),这意味着你可以传递任何类型的数据结构给它。

        返回值:

                []byte:字节切片([]byte),包含了 JSON 格式的数据。

                error:如果序列化过程中出现错误,这个错误会被返回。
 

2. json.Unmarshal(反序列化)

        语法:

                func json.Unmarshal(data []byte, v any) error

        参数:

                data []byte:这是一个包含JSON数据的字节切片。

                v any:这是一个空接口类型(interface{}),它可以接受任何类型的值。在Unmarshal函数中,这个参数通常是一个指向Go结构体的指针,或者是你想将JSON数据解码到的其他类型的变量。

        返回值:

                error:如果在解码过程中遇到任何错误,这个错误会被返回。如果没有错误发生,返回值将是nil

2.2.1 基本类型序列化

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var data = []any{
		// 100: 3个字符
		100,
		// 2.5: 3个字符
		2.5,
		// true: 4个字符
		true,
		// false: 5个字符
		false,
		// nil(null): 4个字符
		nil,
		// "accc":6个字符
		"accc",
	}

	// 对切片中的元素挨个进行序列化
	for i, v := range data {
		b, err := json.Marshal(v)
		if err != nil {
			continue
		}
		fmt.Printf("i=%d | v的类型=%T | v的值=%[2]v | b的类型=%[3]T | b的值=%[3]v | string(b)的类型=%[4]T | string(b)的值=%[4]v\n", i, v, b, string(b))
	}
	// 对整个切片序列化
	fmt.Println(json.Marshal(data))
	t, _ := json.Marshal(data)
	fmt.Println(string(t))
    fmt.Printf("%q", string(t)) // 注意,实际上序列化后的json数据,是有双引号的。
}
========调试结果========
i=0 | v的类型=int | v的值=100 | b的类型=[]uint8 | b的值=[49 48 48] | string(b)的类型=string | string(b)的值=100
i=1 | v的类型=float64 | v的值=2.5 | b的类型=[]uint8 | b的值=[50 46 53] | string(b)的类型=string | string(b)的值=2.5
i=2 | v的类型=bool | v的值=true | b的类型=[]uint8 | b的值=[116 114 117 101] | string(b)的类型=string | string(b)的值=true
i=3 | v的类型=bool | v的值=false | b的类型=[]uint8 | b的值=[102 97 108 115 101] | string(b)的类型=string | string(b)的值=false
i=4 | v的类型=<nil> | v的值=<nil> | b的类型=[]uint8 | b的值=[110 117 108 108] | string(b)的类型=string | string(b)的值=null
i=5 | v的类型=string | v的值=accc | b的类型=[]uint8 | b的值=[34 97 99 99 99 34] | string(b)的类型=string | string(b)的值="accc"
[91 49 48 48 44 50 46 53 44 116 114 117 101 44 102 97 108 115 101 44 110 117 108 108 44 34 97 99 99 99 34 93] <nil>
[100,2.5,true,false,null,"accc"]
"[100,2.5,true,false,null,\"accc\"]"

这里说下为什么上面b的值如100是[49 48 48]?

首先json本身的数据类型就是string,表达100的时候,直接就是1 0 0,但不能添加双引号,否则数据类型错误。上面看到的引号,只是在go中的界定符,json中实际不存在,看v的值就知道了。

也就是说100在json中是3个字符,对应的ASCII编码表就是:字符1=49(十进制)、字符0=48(十进制)。

在说下nil,它是一个特殊的数据类型,本意为空,转换为字符串后,就会变成null。

2.2.1.1 存储序列化数据

实际的存储,肯定是输出到文件或者数据库,这里只是演示一下把json数据写入到二维切片。

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var data = []any{100, 2.5, true, false, nil, "accc"}

	// 定义二维切片,存储json序列化数据
	var target = make([][]byte, 0, len(data))

	// 对切片中的元素进行序列化
	for _, v := range data {
		b, err := json.Marshal(v)
		if err != nil {
			continue
		}
		target = append(target, b)
		// fmt.Printf("i=%d | v的类型=%T | v的值=%[2]v | b的类型=%[3]T | b的值=%[3]v | string(b)的类型=%[4]T | string(b)的值=%[4]v\n", i, v, b, string(b))

	}
	fmt.Println(target)

}
=====================调试结果=====================
[[49 48 48] [50 46 53] [116 114 117 101] [102 97 108 115 101] [110 117 108 108] [34 97 99 99 99 34]]
2.2.1.2 反序列化
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var data = []any{100, 2.5, true, false, nil, "accc"}

	var target = make([][]byte, 0, len(data))

	for _, v := range data {
		b, err := json.Marshal(v)
		if err != nil {
			continue
		}
		target = append(target, b)
	}
	// fmt.Println(target)
	fmt.Println("==============反序列化==============")
	for i, v := range target {
		// json.Unmarshal需要的any类型,反序列化后的数据,也是存在a里面的
		var a any
		err := json.Unmarshal(v, &a)
		if err != nil {
			// 如果反序列化失败,则跳过本次循环,继续下一次循环
			continue
		}
		fmt.Printf("%d 反序列化后的值=%[3]v 反序列化后的类型=%[3]T 反序列化前的类型=%[2]T %[2]v \n", i, v, a)
	}
}
==============反序列化==============
0 反序列化后的值=100 反序列化后的类型=float64 反序列化前的类型=[]uint8 [49 48 48] 
1 反序列化后的值=2.5 反序列化后的类型=float64 反序列化前的类型=[]uint8 [50 46 53] 
2 反序列化后的值=true 反序列化后的类型=bool 反序列化前的类型=[]uint8 [116 114 117 101] 
3 反序列化后的值=false 反序列化后的类型=bool 反序列化前的类型=[]uint8 [102 97 108 115 101] 
4 反序列化后的值=<nil> 反序列化后的类型=<nil> 反序列化前的类型=[]uint8 [110 117 108 108] 
5 反序列化后的值=accc 反序列化后的类型=string 反序列化前的类型=[]uint8 [34 97 99 99 99 34]

为什么 1002.5 在反序列化后变成了 float64?

这是因为 JSON 标准中数字默认表示为双精度浮点数(float64)。即使它们看起来像是整数,Go 语言的 json 包在没有小数点的情况下也会将它们解码为 float64 类型。

2.2.1.3 数组序列化
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// var data = []any{100, 2.5, true, false, nil, "accc"}
	var data = []any{[...]int{97, 98, 99}}

	var target = make([][]byte, 0, len(data))

	for _, v := range data {
		b, err := json.Marshal(v)
		if err != nil {
			continue
		}
		target = append(target, b)
	}
	// fmt.Println(target)
	fmt.Println("==============反序列化==============")
	for i, v := range target {
		// json.Unmarshal需要的any类型,反序列化后的数据,也是存在a里面的
		var a any
		err := json.Unmarshal(v, &a)
		if err != nil {
			// 如果反序列化失败,则跳过本次循环,继续下一次循环
			continue
		}
		fmt.Printf("%d 反序列化前的值=%[2]v 反序列化后的值=%[3]v 反序列化后的类型=%[3]T 反序列化前的类型=%[2]T\n", i, v, a)
	}
}
==============反序列化==============
0 反序列化前的值=[91 57 55 44 57 56 44 57 57 93] 反序列化后的值=[97 98 99] 反序列化后的类型=[]interface {} 反序列化前的类型=[]uint8

json [91 57 55 44 57 56 44 57 57 93],实际对应的go中的字符串是:

实际就是json序列化后,如原来的99,字符序列化后就只占用2个字节了,\x39\x39,如果用整数表达,可以用一个字节,那就是0x39。

2.2.2 结构体序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	var data = Person{"Tom", 32}

	fmt.Println("=======序列化=======")
	// 序列化
	b, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}
	// 序列化后,原有的person类型就被json丢弃了,因为json本身没有person类型
	fmt.Printf("序列化前的数据类型=%T 序列化前的值=%[1]v\n序列化后的数据类型=%[2]T 序列化后的值=%[2]v\n", data, b)
	fmt.Println(string(b))

	fmt.Println("=======反序列化=======")
	var a Person
	err2 := json.Unmarshal(b, &a)
	// err2 := json.Unmarshal([]byte(`{"Name":"Tom","Age":32}`), &a)
	if err2 != nil {
		panic(err2)
	}
	fmt.Printf("反序列化前的类型=%T 反序列化前的值=%[1]v\n反序列化后的类型=%[2]T 反序列化后的值=%+[2]v\n", b, a)
}
=======序列化=======
序列化前的数据类型=main.Person 序列化前的值={Tom 32}
序列化后的数据类型=[]uint8 序列化后的值=[123 34 78 97 109 101 34 58 34 84 111 109 34 44 34 65 103 101 34 58 51 50 125]
{"Name":"Tom","Age":32}
=======反序列化=======
反序列化前的类型=[]uint8 反序列化前的值=[123 34 78 97 109 101 34 58 34 84 111 109 34 44 34 65 103 101 34 58 51 50 125]
反序列化后的类型=main.Person 反序列化后的值={Name:Tom Age:32}

2.2.3 切片序列化

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	var data = []Person{
		{Name: "AAA", Age: 20},
		{Name: "aaa", Age: 32},
	}

	fmt.Println("=======序列化=======")
	// 序列化
	b, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}
	// 序列化后,原有的person类型就被json丢弃了,因为json本身没有person类型
	fmt.Printf("序列化前的数据类型=%T 序列化前的值=%[1]v\n序列化后的数据类型=%[2]T 序列化后的值=%[2]v\n", data, b)
	fmt.Println(string(b))

	fmt.Println("=======反序列化=======")
	var a []Person
	err2 := json.Unmarshal(b, &a)

	if err2 != nil {
		panic(err2)
	}
	fmt.Printf("反序列化前的类型=%T 反序列化前的值=%[1]v\n反序列化后的类型=%[2]T 反序列化后的值=%+[2]v\n", b, a)
}
=======序列化=======
序列化前的数据类型=[]main.Person 序列化前的值=[{AAA 20} {aaa 32}]
序列化后的数据类型=[]uint8 序列化后的值=[91 123 34 78 97 109 101 34 58 34 65 65 65 34 44 34 65 103 101 34 58 50 48 125 44 123 34 78 97 109 101 34 58 34 97 97 97 34 44 34 65 103 101 34 58 51 50 125 93]
[{"Name":"AAA","Age":20},{"Name":"aaa","Age":32}]
=======反序列化=======
反序列化前的类型=[]uint8 反序列化前的值=[91 123 34 78 97 109 101 34 58 34 65 65 65 34 44 34 65 103 101 34 58 50 48 125 44 123 34 78 97 109 101 34 58 34 97 97 97 34 44 34 65 103 101 34 58 51 50 125 93]
反序列化后的类型=[]main.Person 反序列化后的值=[{Name:AAA Age:20} {Name:aaa Age:32}]

2.2.4 字段标签

结构体的字段可以增加标签tag,序列化、反序列化时使用。

(1)在字段类型后,可以跟反引号引起来的一个标签,用json为key,value用双引号引起来写,key与 value直接使用冒号,这个标签中不要加入多余空格,否则语法错误。

Name  string `json:"姓名"`:

        这里表示Name序列化后,就在json中显示为“姓名”。

        json表示json库使用,双引号内第一个参数用来指定字段转换使用的名称,多个参数使用逗号隔开。

Email string `json:"邮箱,omitempty"`:

        omitempty为序列化时忽略空值,也就是该字段 不序列化。
        空值为false、0、空数组、空切片、空map、空串、nil空指针、nil接口值。

        空数组、空切片、空串、空map,长度len为0,也就是容器没有元素。

(2)如果使用 - ,该字段将被忽略

Name string `json:"-"`,:

        序列化后没有该字段,反序列化也不会转换该字段。

Name string `json:"-,"`:

        序列化后该字段显示但名为 "-" ,反序列化也会转换该字段。


(3)多标签使用空格间隔

Name string `json:"name,omitempty" msgpack:"myname"`

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name  string `json:"姓名"`
	Age   int    `json:"年龄"`
	Email string `json:"邮箱,omitempty"` //omitempty 选项表示如果 Email 字段为空(即零值),则在 JSON 输出中省略该字段。
}

func main() {
	var data = []Person{
		{Name: "AAA", Age: 20},
		{Name: "aaa", Age: 32},
	}

	fmt.Println("=======序列化=======")
	// 序列化
	b, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}
	// 序列化后,原有的person类型就被json丢弃了,因为json本身没有person类型
	fmt.Printf("序列化前的数据类型=%T 序列化前的值=%[1]v\n序列化后的数据类型=%[2]T 序列化后的值=%[2]v\n", data, b)
	fmt.Println(string(b))

	fmt.Println("=======反序列化=======")
	var a []Person
	err2 := json.Unmarshal(b, &a)

	if err2 != nil {
		panic(err2)
	}
	fmt.Printf("反序列化前的类型=%T 反序列化前的值=%[1]v\n反序列化后的类型=%[2]T 反序列化后的值=%+[2]v\n", b, a)
}
=======序列化=======
序列化前的数据类型=[]main.Person 序列化前的值=[{AAA 20 } {aaa 32 }]
序列化后的数据类型=[]uint8 序列化后的值=[91 123 34 229 167 147 229 144 141 34 58 34 65 65 65 34 44 34 229 185 180 233 190 132 34 58 50 48 125 44 123 34 229 167 147 229 144 141 34 58 34 97 97 97 34 44 34 229 185 180 233 190 132 34 58 51 50 125 93]
[{"姓名":"AAA","年龄":20},{"姓名":"aaa","年龄":32}]
=======反序列化=======
反序列化前的类型=[]uint8 反序列化前的值=[91 123 34 229 167 147 229 144 141 34 58 34 65 65 65 34 44 34 229 185 180 233 190 132 34 58 50 48 125 44 123 34 229 167 147 229 144 141 34 58 34 97 97 97 34 44 34 229 185 180 233 190 132 34 58 51 50 125 93]
反序列化后的类型=[]main.Person 反序列化后的值=[{Name:AAA Age:20 Email:} {Name:aaa Age:32 Email:}]

3. MessagePack(二进制序列化)

MessagePack是一个基于二进制高效的对象序列化类库,可用于跨语言通信。 它可以像JSON那样,在 许多种语言之间交换结构对象。但是它比JSON更快速也更轻巧。 支持Python、Ruby、Java、C/C++、 Go等众多语言。宣称比Google Protocol Buffers还要快4倍。

安装

go get github.com/vmihailenco/msgpack/v5

基本使用方法和json包类似

package main

import (
	"fmt"

	"github.com/vmihailenco/msgpack/v5"
)

type Person struct {
	Name string `json:"name" msgpack:"myname"`
	Age  int    `json:"age" msgpack:"myage"`
}

func main() {
	// 序列化
	var data = []Person{
		{Name: "Tom", Age: 16},
		{Name: "Jerry", Age: 32},
	}
	b, err := msgpack.Marshal(data) // 方法都和json兼容
	if err != nil {
		panic(err)
	}
	fmt.Println(b, len(b), string(b)) // 二进制
	// 反序列化
	// 知道目标类型
	var j []Person
	err = msgpack.Unmarshal(b, &j)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%T: %+[1]v\n", j)
}

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

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

相关文章

JavaSE——三代日期类(Date、Calendar、LocalDate、LocalTime、LocalDateTime、Instant)

目录 一、util包.Date类——第一代日期类 二、SimpleDateFormat——日期时间格式化 1.日期时间转换成字符串 2.字符串转换成日期时间 三、Calendar日历类——第二代日期类 1.Calendar类中常用的静态方法 2.设置指定的字段(不常用) 3.calendar.setTime()使用案例——获取…

总结拓展十二:SAP采购定价条件

第一节 采购定价条件 1.条件类型介绍 2.条件类型概念 条件类型&#xff08;Condition Technology&#xff09;是SAP中运用较多的配置技术&#xff0c;了解条件技术如何运作&#xff0c;有助于我们理解系统在不同情况下的行为和反应&#xff0c;条件技术广泛地应用于定价、文…

【论文_2000】REINFORCE 和 actor-critic 等策略梯度方法的局部收敛性证明

部分证明不太理解 SUTTON R S, MCALLESTER D A, SINGH S P, et al. Policy gradient methods for reinforcement learning with function approximation [C] // Advances in neural information processing systems, 2000: 1057-1063. 【PDF 链接】 文章目录 摘要引言1 策略梯…

Arthas jad(字节码文件反编译成源代码 )

文章目录 二、命令列表2.2 class/classloader相关命令2.2.1 jad&#xff08;字节码文件反编译成源代码 &#xff09;举例1&#xff1a;反编译指定的函数 &#xff1a;jad com.hero.lte.ems.sysmanager.cache.SMTaskCache executeTask举例2&#xff1a;反编绎时只显示源代码&…

PCIe扫盲(14)

系列文章目录 PCIe扫盲&#xff08;一&#xff09; PCIe扫盲&#xff08;二&#xff09; PCIe扫盲&#xff08;三&#xff09; PCIe扫盲&#xff08;四&#xff09; PCIe扫盲&#xff08;五&#xff09; PCIe扫盲&#xff08;六&#xff09; PCIe扫盲&#xff08;七&#xff09…

如何查看电脑的虚拟内存信息?

1、按下键盘的 win R 键 &#xff0c; 输入&#xff1a;cmd &#xff0c; 然后按下【回车】 2、在弹出的窗口输入&#xff1a;systeminfo &#xff0c; 然后按下【回车】&#xff0c;等待加载结果出来。 3、如下位置&#xff0c;显示的即是当前电脑的【虚拟内存】信息&…

Fusion Access

1.FA桌面云需要微软三剑客 2.AD&#xff0c;DNS&#xff0c;DHCP合并部署在一台虚机&#xff0c;内存配置8G 3.FA各个组件 3.1终端接入 3.2接入和访问控制层 3.3虚拟桌面管理层-桌面云规划及部署 3.4安装Linux基础架构虚拟机FA01 3.4.1安装Tools 3.4.2安装FusionAccess组件&am…

希捷电脑硬盘好恢复数据吗?探讨可能性、方法以及注意事项

在数字化时代&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。希捷电脑硬盘作为数据存储的重要设备&#xff0c;承载着大量的个人文件、工作资料以及珍贵回忆。然而&#xff0c;面对硬盘故障或误操作导致的数据丢失&#xff0c;许多用户不禁要问&#xff1a;希捷电脑…

找到你的工具!5款免费可视化报表工具对比分析

选择合适的可视化工具对于分析和展示数据至关重要&#xff0c;以下是五款免费的可视化工具&#xff0c;它们各具特色&#xff0c;能够适应各种需求。本文将介绍每款工具的优势与不足&#xff0c;帮助你找到最合适的解决方案。 1. 山海鲸可视化 介绍&#xff1a;山海鲸可视化是…

UniApp组件与微信小程序组件对照学习

UniApp只是一个第三方的开发工具&#xff0c;借鉴各种平台的能力&#xff0c;UniApp的组件也借鉴了微信小程序的组件&#xff0c;我们学习时&#xff0c;可以进行对照学习&#xff0c;我们在用UniApp开发微信小程序时&#xff0c;UniApp也只是将代码转成了微信小程序的代码&…

“电瓶车火灾”频发,如何防范自救

1.概述 近年来&#xff0c;随着电动自行车使用的普及化&#xff0c;由此引发的起火事故频繁发生。作为上海市烧伤急救中心&#xff0c;上海交通大学医学院附属瑞金医院的灼伤整形科收治的此类病人数量也在逐年上升。电动自行车&#xff0c;已经成为一种新型火灾事故的“肇事者…

【Docker】02-数据卷

1. 数据卷 数据卷(volume) 是一个虚拟目录&#xff0c;是容器内目录与宿主机目录之间映射的桥梁。 2. 常见命令 docker volume createdocker volume lsdocker volume rmdocker volume inspect 查看某个数据卷的详情docker volume prune 清除数据卷 **数据卷挂载&#xff1a…

【笔记】数据结构|链表算法总结|快慢指针场景和解决方案|链表归并算法和插入算法|2012 42

受堆积现象直接影响的是&#xff1a;平均查找长度 产生堆积现象&#xff0c;即产生了冲突&#xff0c;它对存储效率、散列函数和装填因子均不会有影响&#xff0c;而平均查找长度会因为堆积现象而增大。 2012 42 参考灰灰考研 假定采用带头结点的单链表保存单词&#xff0c;当…

MySQL_表_进阶(1/2)

我们的进阶篇中&#xff0c;还是借四张表&#xff0c;来学习接下来最后关于表的需求&#xff0c;以此完成对表的基本学习。 照例给出四张表&#xff1a; 学院表&#xff1a;(testdb.dept) 课程表&#xff1a;(testdb.course) 选课表:&#xff08;testdb.sc&#xff09; 学生表…

JS面试真题 part7

JS面试真题 part7 31、web常见的攻击方式有哪些&#xff1f;如何防御32、说说JavaScript中内存泄漏的几种情况33、JavaScript如何实现继承34、说说JavaScript数字精度丢失的问题&#xff0c;如何解决35、举例说明你对尾递归的理解&#xff0c;有哪些应用场景 31、web常见的攻击…

使用kaggle命令下载数据集和模型

点击用户头像&#xff0c;点击Settings&#xff1a; 找到API&#xff0c;点击create new token&#xff0c;将自动下载kaggle.json&#xff1a; 在用户目录下创建.kaggle文件夹&#xff0c;并将下载的kaggle.json文件移动到该文件夹&#xff1a; cd ~ mv Downloads/kaggle.j…

Universal Link配置不再困扰,Xinstall来帮忙

在移动互联网时代&#xff0c;App的推广和运营至关重要。而Universal Link作为一种能够实现网页与App间无缝跳转的技术&#xff0c;对于提升用户体验、引流至App具有显著效果。今天&#xff0c;我们就来科普一下Universal Link的配置方法&#xff0c;并介绍如何通过Xinstall这款…

2024-2025华为ICT大赛报名|赛前辅导|学习资料

华为ICT大赛是华为公司打造的面向全球高校的年度ICT赛事&#xff0c;大赛以“联接、荣耀、未来”为主题&#xff0c;协同政府、高等教育机构、培训机构和行业企业&#xff0c;促进高校ICT人才培养、成长和就业&#xff0c;助力ICT人才生态繁荣。2021年3月&#xff0c;大赛成功入…

Linux Centos7达梦8数据库安装说明(附安装包,超详细图文!)收藏这一篇就够了!

VMWare17&Linux Centos7&达梦数据库8.4 使用说明 1.导语 1.1说明文档编写思路 小伙伴们,在自己电脑上搞起来啊&#xff0c;随便安装Linux环境&#xff0c;也不用担心搞错配置搞坏环境&#xff0c;大不了重装Linux系统。hahahhhhhhhhhh 由于本地没有合适的Linux环境进行…

AIGAME平台的由来与未来展望 —— 蒙特加密基金推动区块链与AI融合创新

摘要&#xff1a; AIGAME平台凭借蒙特加密产业基金的战略投资&#xff0c;成为区块链与AI融合创新的先驱。该平台集成了链游、DeFi、加密聊天和跨境支付等多项功能&#xff0c;打造出一个多元化的Web3生态系统。未来&#xff0c;AIGAME将在技术创新和全球布局中持续引领潮流。 …