使用Go的encoding/asn1库处理复杂数据:技巧与最佳实践

使用Go的encoding/asn1库处理复杂数据:技巧与最佳实践

    • 引言
    • ASN.1 基础
      • ASN.1与Go语言的关系
      • ASN.1数据类型
    • encoding/asn1库概览
      • 主要功能和特性
      • 关键API
      • 应用场景
    • 基本使用方法
      • 序列化(编码)
      • 反序列化(解码)
      • 处理复杂数据结构
    • 处理时间和数值的处理
      • 时间类型的处理
      • 数值的处理
      • 自定义标签的应用
    • 安全性考虑
      • 验证输入数据
      • 使用安全的编码选项
      • 防范时间相关攻击
      • 注意大数处理
    • 高级应用场景
      • 加密算法参数的序列化和反序列化
      • 处理X.509证书
      • ASN.1和复杂数据结构
      • 常见问题及解决方案
    • 总结
      • 关键点回顾
      • 最佳实践

在这里插入图片描述

引言

在现代软件开发中,数据的序列化与反序列化是一项基础且关键的技术,它允许数据在不同的系统或组件间安全、高效地传输和存储。ASN.1(Abstract Syntax Notation One)是一种在众多领域,特别是在安全通信、电信和计算机网络中广泛应用的标准化表示法。它提供了一套丰富的数据描述语言,用以确保数据结构的一致性和兼容性。在Go语言的生态系统中,encoding/asn1库为开发者提供了一个强大的工具,以支持ASN.1数据格式的编码和解码。无论是处理证书、加密消息还是实现复杂的通信协议,encoding/asn1库都是实现这些功能不可或缺的组成部分。本文旨在深入探讨encoding/asn1库,通过实例和实践经验,帮助开发者掌握其在Go语言项目中的应用。

ASN.1 基础

ASN.1(抽象语法标记第一号)是一种标准的数据描述语言,用于定义在应用层之间交换的数据结构。它独立于编程语言,可以用于多种编程环境中,提供了一种灵活且强大的方式来描述数据结构和复杂数据类型。

ASN.1与Go语言的关系

虽然ASN.1本身是与编程语言无关的,但encoding/asn1库使得Go语言能够轻松地序列化和反序列化遵循ASN.1标准的数据。这一点对于开发需要处理如X.509证书、加密消息等遵循ASN.1标准的应用尤为重要。

ASN.1数据类型

ASN.1定义了一系列的数据类型,从基本类型如整数(INTEGER)、字符串(STRING)到复杂的结构体和序列。这些类型的多样性和灵活性使得ASN.1能够描述几乎任何类型的数据结构。以下是一些基本的ASN.1数据类型:

  • INTEGER:表示整数,大小不受限制。
  • BOOLEAN:表示布尔值,TRUE 或 FALSE。
  • STRING:有多种字符串类型,包括IA5String(ASCII字符集)、UTF8String等。
  • SEQUENCE:表示有序的元素集合,类似于其他语言中的数组或列表。
  • SET:表示无序的元素集合。
  • OID(对象标识符):用于唯一标识对象、数据类型等。

通过这些基本和构造数据类型,ASN.1能够精确地描述复杂的数据结构,为跨平台和跨语言的数据交换提供了坚实的基础。

encoding/asn1库概览

encoding/asn1库是Go语言标准库的一部分,提供了对ASN.1(抽象语法标记第一号)数据格式的支持。ASN.1用于在复杂的系统之间以一种标准化的方式交换数据,广泛应用于通信协议、加密算法的数据表示等领域。encoding/asn1库允许Go开发者序列化和反序列化遵循ASN.1标准的数据,是处理证书、加密消息等安全相关数据的重要工具。

主要功能和特性

序列化与反序列化encoding/asn1提供了将Go语言数据结构转换为ASN.1编码数据(序列化)以及将ASN.1编码数据转换回Go语言数据结构(反序列化)的功能。这是实现数据交换和存储的基础。

支持多种数据类型:该库支持ASN.1定义的多种数据类型,包括基本类型(如INTEGER、BOOLEAN、STRING等)和复杂类型(如SEQUENCE、SET等)。这些数据类型的支持确保了与其他使用ASN.1的系统的兼容性。

自定义标签:Go开发者可以使用结构体字段后的标签指定ASN.1的编码细节,如类型、是否可选等。这提供了额外的灵活性,允许精确控制序列化和反序列化的行为。

关键API

  • Marshal函数:用于序列化Go数据结构为ASN.1编码的字节序列。它接受几乎任何Go数据类型,按照提供的类型信息转换为ASN.1格式。

  • Unmarshal函数:用于反序列化ASN.1编码的字节序列为Go数据结构。它能够处理由Marshal生成的数据,或者任何合法的ASN.1编码数据,将其转换回指定的Go类型。

  • 特定类型支持:库中还定义了一些特定的类型(如ObjectIdentifierBitString等),以便更方便地处理ASN.1中的一些常见结构。

应用场景

encoding/asn1库的应用场景非常广泛,特别是在需要数据加密和证书管理的领域。例如,它可以用于:

  • 处理X.509证书:在HTTPS通信、电子签名等领域中,证书的管理和验证是必不可少的。encoding/asn1库提供了解析和生成这些证书所需的功能。
  • 开发加密通信协议:许多安全通信协议(如SSL/TLS)在协议消息的格式化中使用ASN.1。通过encoding/asn1库,开发者可以实现这些协议的关键部分。
  • 实现复杂的数据交换协议:在需要严格的数据格式和兼容性的系统间通信中,encoding/asn1能够确保数据的准确性和一致性。

基本使用方法

encoding/asn1库的基本使用涉及到两个核心操作:序列化(编码)和反序列化(解码)。序列化是将Go语言的数据结构转换为ASN.1格式的字节序列,以便于存储或网络传输;反序列化则是将ASN.1格式的字节序列还原为Go语言的数据结构。以下是这两个操作的基本介绍及示例。

序列化(编码)

序列化是将Go语言中的数据结构转换成ASN.1编码的过程。这一过程通过asn1.Marshal函数实现,该函数接受Go中的数据结构作为输入,输出ASN.1编码的字节序列和可能的错误。

示例代码

package mainimport ("encoding/asn1""fmt""log"
)func main() {data := "Hello, ASN.1"encoded, err := asn1.Marshal(data)if err != nil {log.Fatalf("Error encoding data: %v", err)}fmt.Printf("Encoded data: %x\n", encoded)
}

在这个例子中,我们序列化了一个简单的字符串"Hello, ASN.1"asn1.Marshal返回的字节序列是这个字符串按照ASN.1规范编码的结果。

反序列化(解码)

反序列化是指将ASN.1编码的字节序列转换回Go语言中的数据结构的过程。这一过程通过asn1.Unmarshal函数完成,该函数接受ASN.1编码的字节序列和一个指向将要存放数据的Go变量的指针作为输入。

示例代码

package mainimport ("encoding/asn1""fmt""log"
)func main() {encoded := []byte{0x16, 0xd, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x41, 0x53, 0x4e, 0x2e, 0x31}var decoded string_, err := asn1.Unmarshal(encoded, &decoded)if err != nil {log.Fatalf("Error decoding data: %v", err)}fmt.Printf("Decoded data: %s\n", decoded)
}

在这个例子中,我们将之前序列化得到的字节序列反序列化回原始的字符串。注意,asn1.Unmarshal的第二个参数是一个指向目标变量的指针,这里是一个指向字符串的指针,用于存放解码后的数据。

处理复杂数据结构

encoding/asn1不仅支持基本数据类型的序列化和反序列化,还支持复杂的数据结构,如结构体。通过在结构体字段上使用ASN.1标签,开发者可以控制序列化和反序列化的细节,如指定字段的ASN.1类型、是否为可选字段等。

示例代码(处理结构体):

package mainimport ("encoding/asn1""fmt""log"
)type Person struct {Name stringAge  int `asn1:"optional"`
}func main() {person := Person{Name: "John Doe", Age: 30}encoded, err := asn1.Marshal(person)if err != nil {log.Fatalf("Error encoding person: %v", err)}fmt.Printf("Encoded person: %x\n", encoded)var decodedPerson Person_, err = asn1.Unmarshal(encoded, &decodedPerson)if err != nil {log.Fatalf("Error decoding person: %v", err)}fmt.Printf("Decoded person: %+v\n", decodedPerson)
}

在这个例子中,我们定义了一个Person结构体,并通过asn1.Marshalasn1.Unmarshal函数分别进行序列化和反序列化操作。通过这种方式,encoding/asn1库能够灵活地处理各种复杂的数据结构,满足不同应用场景的需求。

处理时间和数值的处理

在使用encoding/asn1库进行数据序列化和反序列化时,特定的数据类型,如时间和大数(BigIntegers),需要特别注意。这些类型在ASN.1中有特定的表示方法,encoding/asn1库为它们提供了相应的支持。

时间类型的处理

ASN.1定义了多种时间类型,比如UTCTimeGeneralizedTime,用于不同的精度和范围。在Go中,time.Time类型可以被序列化为这两种ASN.1时间格式。序列化时,encoding/asn1会根据时间值的范围和精度自动选择最合适的ASN.1时间类型。

示例代码

package mainimport ("encoding/asn1""fmt""log""time"
)func main() {currentTime := time.Now()encodedTime, err := asn1.Marshal(currentTime)if err != nil {log.Fatalf("Error encoding time: %v", err)}fmt.Printf("Encoded time: %x\n", encodedTime)var decodedTime time.Time_, err = asn1.Unmarshal(encodedTime, &decodedTime)if err != nil {log.Fatalf("Error decoding time: %v", err)}fmt.Printf("Decoded time: %v\n", decodedTime)
}

这段代码展示了如何将time.Time类型的当前时间序列化为ASN.1编码,然后再反序列化回Go的时间类型。

数值的处理

对于大数(如公钥加密中的大整数),Go的math/big包提供了*big.Int类型。encoding/asn1可以直接序列化和反序列化*big.Int类型,确保数值的正确编码和解码。

示例代码

package mainimport ("encoding/asn1""fmt""log""math/big"
)func main() {bigInt := big.NewInt(123456789)encodedBigInt, err := asn1.Marshal(bigInt)if err != nil {log.Fatalf("Error encoding big.Int: %v", err)}fmt.Printf("Encoded big.Int: %x\n", encodedBigInt)var decodedBigInt *big.Int_, err = asn1.Unmarshal(encodedBigInt, &decodedBigInt)if err != nil {log.Fatalf("Error decoding big.Int: %v", err)}fmt.Printf("Decoded big.Int: %s\n", decodedBigInt.String())
}

在这个示例中,我们创建了一个*big.Int类型的大数,通过asn1.Marshalasn1.Unmarshal进行序列化和反序列化。这样,即使是非常大的数值也可以被正确处理。

自定义标签的应用

在某些情况下,你可能需要对序列化和反序列化过程进行更细致的控制,比如指定ASN.1的具体类型或者标记某些字段为可选。encoding/asn1通过在Go结构体字段后使用标签来支持这种需求,允许开发者自定义序列化和反序列化的行为。

示例代码(自定义标签):

type CustomData struct {Field1 int    `asn1:"explicit,tag:0"`Field2 string `asn1:"ia5,optional"`
}

在这个结构体定义中,Field1被标记为显式标签0,Field2被指定为IA5String类型且为可选字段。这种灵活性使得encoding/asn1能够满足各种复杂ASN.1数据结构的处理需求。

安全性考虑

在使用encoding/asn1库处理数据序列化和反序列化时,安全性是一个重要的考虑因素。不当的数据处理可能导致安全漏洞,如数据篡改、信息泄露等。因此,了解和应用安全最佳实践是至关重要的。

验证输入数据

在反序列化来自不可信源的数据时,务必验证输入数据的合法性和完整性。恶意构造的数据可能导致解析错误,甚至触发安全漏洞,比如缓冲区溢出或逻辑错误。

最佳实践

  • 在反序列化之前,尽可能对输入数据进行格式和范围的检查。
  • 使用asn1.Unmarshal时,确保目标结构体与期望的数据格式严格对应。

使用安全的编码选项

encoding/asn1库提供了多种编码选项,某些选项可能更适合安全敏感的应用场景。例如,确保使用正确的字符串类型、避免不必要的可选字段,这些都有助于减少潜在的安全风险。

最佳实践

  • 明确指定ASN.1标签中字段的类型和属性,避免使用默认的编解码行为。
  • 对于安全敏感的数据,考虑使用更安全的编码选项,如显式标签等。

防范时间相关攻击

在处理时间数据时,确保使用encoding/asn1库以安全的方式序列化和反序列化时间值。不正确的时间处理可能导致逻辑错误,甚至被利用进行攻击。

最佳实践

  • 在序列化和反序列化时间值时,确认使用的时间类型(UTCTimeGeneralizedTime)与数据的预期使用场景相匹配。
  • 验证反序列化后的时间值是否在合理的范围内,避免因时间解析错误导致的安全问题。

注意大数处理

在处理大数(如加密算法中使用的大整数)时,正确的序列化和反序列化尤为重要。不当处理可能导致数值错误,影响加密算法的安全性。

最佳实践

  • 确保在序列化和反序列化大数时使用*big.Int类型,以避免精度丢失。
  • 检查反序列化后的大数是否符合预期的数值范围和逻辑条件。

高级应用场景

encoding/asn1库在Go语言中不仅适用于基本数据类型的序列化与反序列化,还能够处理更复杂和高级的应用场景,特别是在加密和证书管理等领域。这些场景往往要求对数据的处理既要精确又要安全,以下是一些高级应用场景的例子及如何使用encoding/asn1库来实现它们。

加密算法参数的序列化和反序列化

在加密应用中,经常需要序列化和反序列化算法参数,如公钥和私钥的参数。encoding/asn1库能够帮助开发者以标准化的方式处理这些数据,确保加密算法的正确实现和应用。

示例代码(序列化RSA公钥):

package mainimport ("crypto/rand""crypto/rsa""crypto/x509""encoding/asn1""log"
)func main() {// 生成RSA密钥对privateKey, err := rsa.GenerateKey(rand.Reader, 2048)if err != nil {log.Fatalf("Failed to generate private key: %v", err)}publicKey := &privateKey.PublicKey// 将公钥序列化为ASN.1 DER编码asn1Bytes, err := x509.MarshalPKIXPublicKey(publicKey)if err != nil {log.Fatalf("Failed to marshal public key: %v", err)}// 使用encoding/asn1序列化var encoded asn1.RawValue_, err = asn1.Unmarshal(asn1Bytes, &encoded)if err != nil {log.Fatalf("Failed to unmarshal ASN.1 encoded public key: %v", err)}// 此处可以使用encoded进行进一步处理
}

在这个例子中,我们生成了一个RSA密钥对,然后将公钥序列化为ASN.1 DER编码。之后,使用encoding/asn1进行反序列化,得到asn1.RawValue类型的数据,这可以用于进一步的处理或传输。

处理X.509证书

X.509证书广泛用于HTTPS通信、电子签名等安全领域。这些证书使用ASN.1格式编码,因此encoding/asn1库自然成为处理这类数据的有力工具。

示例代码(解析X.509证书):

package mainimport ("crypto/x509""encoding/asn1""encoding/pem""io/ioutil""log"
)func main() {// 读取证书文件certPEM, err := ioutil.ReadFile("certificate.pem")if err != nil {log.Fatalf("Failed to read certificate file: %v", err)}// PEM解码block, _ := pem.Decode(certPEM)if block == nil {log.Fatalf("Failed to decode PEM block containing the certificate")}// 解析X.509证书cert, err := x509.ParseCertificate(block.Bytes)if err != nil {log.Fatalf("Failed to parse certificate: %v", err)}// 使用cert进行进一步处理,例如验证签名等
}

在这个示例中,我们从PEM编码的文件中读取并解析了一个X.509证书。虽然直接使用了crypto/x509库进行证书的解析,但encoding/asn1crypto/x509库的实现中扮演了核心角色,尤其是在ASN.1格式的解码和编码过程中。

ASN.1和复杂数据结构

在某些场景下,开发者可能需要处理复杂的ASN.1数据结构,如嵌套的序列或带有特定标签的数据。encoding/asn1库提供了灵活的方式来处理这些复杂结构,确保数据的准确序列化和反序列化。

示例代码(自

定义复杂结构):

package mainimport ("encoding/asn1""log"
)type ComplexStruct struct {Field1 stringField2 []intField3 asn1.BitString
}func main() {// 创建复杂结构实例complexData := ComplexStruct{Field1: "Example",Field2: []int{1, 2, 3},Field3: asn1.BitString{Bytes: []byte{0x00, 0x00, 0xFF}, BitLength: 24},}// 序列化serialized, err := asn1.Marshal(complexData)if err != nil {log.Fatalf("Failed to serialize complex data: %v", err)}// 此处可以对serialized进行进一步处理
}

这个例子演示了如何定义和序列化一个包含基本类型、切片和asn1.BitString的复杂结构。通过对这些高级应用场景的探讨,我们可以看到encoding/asn1库在Go语言中的强大能力和灵活性,它不仅能够处理简单的数据类型,也能够应对复杂的序列化和反序列化需求。

定义结构体序列化):

package mainimport ("encoding/asn1""fmt""log"
)type ComplexType struct {ID        intTimestamp asn1.RawValueData      []byte `asn1:"tag:4,explicit,optional"`
}func main() {// 初始化一个复杂类型实例complexInstance := ComplexType{ID:   12345,Data: []byte("Example Data"),}// 将当前时间作为RawValue序列化asn1Timestamp, err := asn1.Marshal(asn1.RawValue{Tag: asn1.TagUTCTime, Bytes: []byte("20060102150405Z")})if err != nil {log.Fatalf("Failed to marshal timestamp: %v", err)}complexInstance.Timestamp = asn1.RawValue{FullBytes: asn1Timestamp}// 序列化整个结构体encoded, err := asn1.Marshal(complexInstance)if err != nil {log.Fatalf("Failed to marshal complex instance: %v", err)}fmt.Printf("Encoded ASN.1 Data: %x\n", encoded)// 反序列化var decodedInstance ComplexType_, err = asn1.Unmarshal(encoded, &decodedInstance)if err != nil {log.Fatalf("Failed to unmarshal ASN.1 data: %v", err)}fmt.Printf("Decoded Complex Type: %+v\n", decodedInstance)
}

在这个示例中,我们定义了一个包含复杂ASN.1标签和类型的结构体ComplexType。该结构体中的Timestamp字段使用了asn1.RawValue来处理特定的时间格式,而Data字段则通过ASN.1标签实现了自定义的编码。通过序列化和反序列化该结构体,我们展示了如何在Go中使用encoding/asn1库处理复杂的ASN.1数据结构。

常见问题及解决方案

在使用encoding/asn1进行序列化和反序列化时,开发者可能会遇到一些常见的问题,如编码不匹配、解析错误等。以下是一些解决这些问题的建议:

  • 确保ASN.1标签正确:当定义结构体用于ASN.1编解码时,正确的标签非常关键。确保使用的标签与数据格式匹配,特别是在处理可选字段或使用显式/隐式标签时。
  • 处理未知或可选字段:对于可能缺失的字段,可以使用asn1.RawValue或指针类型来表示可选性,这样在字段不存在时可以避免解析错误。
  • 调试编解码问题:当遇到序列化或反序列化的问题时,首先检查结构体定义中的ASN.1标签是否正确。使用小型的测试案例逐步调试,可以更容易地定位问题所在。

总结

通过本文的深入探讨,我们已经全面了解了Go语言标准库中的encoding/asn1库及其在实际开发中的应用。从基本的数据类型序列化与反序列化,到复杂数据结构的处理,再到高级应用场景如加密算法参数的序列化和X.509证书的处理,encoding/asn1库展现了其强大的功能和灵活性。

关键点回顾

  • 广泛的数据类型支持encoding/asn1支持多种ASN.1数据类型,包括基本类型和复杂类型,满足不同场景的需求。
  • 序列化与反序列化:库提供了简洁的API用于数据的序列化与反序列化,使得数据交换和存储变得简单高效。
  • 安全性考虑:在使用过程中,开发者需要注意验证输入数据,使用安全的编码选项,以及遵循安全最佳实践,确保应用的安全性。
  • 高级应用支持encoding/asn1能够处理复杂的应用场景,如加密算法参数和证书管理,为开发安全相关应用提供了有力的支持。

最佳实践

  • 细致地定义数据结构:正确使用ASN.1标签,明确字段的类型和属性,以确保数据的正确编解码。
  • 安全地处理输入数据:特别是在反序列化来自外部的数据时,始终进行验证,以避免潜在的安全威胁。
  • 利用encoding/asn1库进行调试:在遇到序列化或反序列化问题时,逐步检查和调试,确保数据结构定义的正确性。

encoding/asn1库是Go语言处理ASN.1数据的强大工具,但掌握它需要时间和实践。我们鼓励读者通过实际项目应用这些知识,深入探索库的更多功能和使用技巧。随着对encoding/asn1理解的加深,你将能更加高效地开发出安全、可靠的应用。

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

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

相关文章

npm、cnpm、pnpm使用详细

简介: npm:npm(Node Package Manager)是Node.js的包管理工具,用于安装、更新、卸载Node.js的模块和包。它提供了一个命令行界面,使得开发者可以轻松地管理项目依赖。npm 是 nodejs 中的一部分,…

Pytorch学习 day01(Jupyter安装、常用函数、三种编辑器的对比)

Jupyter 安装过程中遇到的问题: Anaconda的base环境会自动安装Jupyter,但是如果我们要在其他环境中安装Jupyter,就需要注意,该环境的python版本不能高于3.11,且用以下代码安装: conda install nb_conda_…

什么是跨站脚本攻击(XSS)

厦门微思网络​​​​​​https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle OCP\CKA\K8S\ CISP\CISSP\PMP\ ​ 跨站脚本攻击(Cross-site Scripting,通常称为XSS)&#xf…

SpringCloud-RabbitMQ消息模型

本文深入介绍了RabbitMQ消息模型,涵盖了基本消息队列、工作消息队列、广播、路由和主题等五种常见消息模型。每种模型都具有独特的特点和适用场景,为开发者提供了灵活而强大的消息传递工具。通过这些模型,RabbitMQ实现了解耦、异步通信以及高…

深度学习系列61:在CPU上运行大模型

1. 快速版 1.1 llamafile https://github.com/Mozilla-Ocho/llamafile 直接下载就可以用,链接为:https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4.llamafile?downloadtrue 启动:./llava-v1.5-7b-q4.lla…

提升效率的电脑定时工具,AutoOff软件推荐

今天最软库给大家带来一款非常实用的电脑定时关机软件在我们日常办公的时候有的时候需要上传一些资料由于我们下班了,我们想让他上传完成之后我们才离开这时候呢,就可以用到这款定时工具了。 我们可以设置中设置在几小时或者几分钟之后让电脑进行关机我们…

基于springboot+vue的新闻资讯系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

【HarmonyOS】DevEco Studio3.1x安装教程

目录 下载安装开发工具配置 下载 开发工具点击跳转→https://hmxt.org/deveco-studio 点击‘立即下载’ 安装 将安装包解压 双击安装,点击“Next” 选择安装目录,点击Next 勾选创建桌面快捷方式和环境的添加,点击Next 点击Instal…

Python实现ROC工具判断信号:股票技术分析的工具系列(7)

Python实现ROC工具判断信号:股票技术分析的工具系列(7) 介绍算法公式 代码rolling函数介绍完整代码data代码ROC.py 介绍 ROC(变动率指标)是一种技术分析指标,用于衡量价格变动的速度和幅度,计算…

LCR 127. 跳跃训练

解题思路&#xff1a; 动态规划&#xff0c;类似于斐波那契数列&#xff0c;但需要根据题意调整初始值dp[0]和dp[1]&#xff0c;递推公式由最后一跳跳一次或两次得到。 class Solution {public int trainWays(int num) {if(num<1) return 1;int[] dpnew int[num1];//当平台…

抖音视频评论批量采集软件|视频下载工具

《轻松搞定&#xff01;视频评论批量采集软件&#xff0c;助您高效工作》 在短视频这个充满活力和创意的平台上&#xff0c;了解用户评论是了解市场和观众心声的重要途径之一。为了帮助您快速获取大量视频评论数据&#xff0c;我们推出了一款操作便捷、功能强大的软件&#xff…

JVM运行时数据区——堆

文章目录 1、堆的核心概述1.1、JVM实例与堆内存的对应关系1.2、堆与栈的关系1.3、JVM堆空间划分 2、设置堆内存大小与内存溢出2.1、设置堆内存大小2.2、内存溢出案例 3、新生代与老年代4、图解对象分配过程5、Minor GC、Major GC、Full GC5.1、GC的分类5.2、分代式GC策略的触发…

Linux 之一:Linux 简介、客户端、安装

Linux简介 Linux 内核最初只是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的。 Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹于…

Springboot实现缓存预热

很多时候我们代码中使用缓存时都是先判断缓存中没有数据我们再读取数据库而有则直接使用缓存数据&#xff0c;而在系统冷启动(当系统重启或新启动时&#xff0c;缓存是空的&#xff0c;这被称为冷启动)时&#xff0c;我们毫无意外都是直接获取数据库的内容&#xff0c;这时候缓…

计算机网络-网络安全(二)

1.应用层安全协议&#xff1a; S-HTTP或SHTTP&#xff08;Sec HTTP&#xff09;&#xff0c;安全超文本传输协议&#xff0c;是HTTP扩展&#xff0c;使用TCP的80端口。HTTPS&#xff1a;HTTPSSL&#xff0c;使用TCP的443端口。和TLS&#xff08;传输层安全标准&#xff09;是双…

[Redis]——Spring整合Redis(SpringDataRedis)

⭐准备工作&#xff1a; 确保Redis服务已启动idea开发环境 ⭐Redis整合步骤&#xff1a; 1.pom文件引入依赖 2.yml文件配置连接信息 3.修改Redis序列化方式 4.注入RedisTemplate 使用 小知识&#xff1a; Spring整合的Redis可以将Object对象自动序列化成字符串&#xff0…

RabbitMQ分享

RabbitMQ遵循AMQP协议&#xff0c;自身采用Erlang RabbitMQ工作模式 生产者发消息&#xff0c;启动多个消费者实例来消费消息&#xff0c;每个消费者仅消费部分信息&#xff0c;可达到负载均衡的效果。 RabbitMQ三种常用交换机类型&#xff1a; 交换机主要起调度分发作用。 …

【Oracle Database】如何远程连接服务器、创建用户、从本地dmp导入表

C:\Users\test>imp test/123456ip/orcl:1521 fileE:\db.dmp tablestable1,table2Import: Release 11.2.0.3.0 - Production on 星期一 3月 4 12:59:09 2024Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.IMP-00058: 遇到 ORACLE 错误 1263…

电机应用-正点原子直流有刷电机例程笔记

目录 基础驱动实验&#xff1a;调速和换向 初始化工作 电机基础驱动API 电压、电流、温度检测实验 初始化工作 采集工作 编码器测速实验 编码器接口计数原理 初始化工作 编码器测速工作 速度环控制实现 PID相关函数 PID运算 电流环控制实现 PID相关函数 PID运算…

Shell管道和过滤器

一、Shell管道 Shell 还有一种功能&#xff0c;就是可以将两个或者多个命令&#xff08;程序或者进程&#xff09;连接到一起&#xff0c;把一个命令的输出作为下一个命令的输入&#xff0c;以这种方式连接的两个或者多个命令就形成了管道&#xff08;pipe&#xff09;。 重定…