【Golang星辰图】Go语言魔法使者:解锁消息队列魅力,轻松构建强大应用

极速通信:Go语言中不可错过的消息队列库全面解析

前言

随着现代应用程序的复杂性不断增加,消息队列成为了构建可靠、高效和可扩展系统的关键组件之一。在Go语言领域,开发人员可以利用各种消息队列库来简化消息传递过程,实现异步通信和解耦组件。

欢迎订阅专栏:Golang星辰图

文章目录

  • 极速通信:Go语言中不可错过的消息队列库全面解析
      • 前言
      • 1. Go-amqp: AMQP库
        • 1.1 功能介绍
        • 1.2 使用示例
        • 1.3 进阶用法示例
        • 1.4 效率优化
      • 2. Go-stomp: STOMP库
        • 2.1 功能介绍
        • 2.2 使用示例
      • 2.3 高级用法示例
      • 2.4 安全性考虑
      • 3. Go-nats: NATS库
        • 3.1 功能介绍
        • 3.2 使用示例
        • 3.3 进阶应用示例
        • 3.4 安全性与认证
      • 4. Go-kafka: Kafka库
        • 4.1 功能介绍
        • 4.2 使用示例
        • 4.3 高级应用示例
        • 4.4 容错处理
      • 5. Go-nsq: NSQ库
        • 5.1 功能介绍
        • 5.2 使用示例
        • 5.3 进阶应用示例
        • 5.4 稳定性与故障恢复
      • 6. Go-rabbitmq: RabbitMQ库
        • 6.1 功能介绍
        • 6.2 使用示例
        • 6.3 高级应用示例
        • 6.4 可靠性与持久化
      • 总结

1. Go-amqp: AMQP库

1.1 功能介绍

Go-amqp是一个用于处理AMQP(高级消息队列协议)的Go语言库。它提供了连接到AMQP代理、声明交换机和队列、发送和接收消息等功能,使得在Go应用程序中轻松实现与AMQP消息队列的通信。

1.2 使用示例
package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()ch, err := conn.Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()q, err := ch.QueueDeclare("hello",false,false,false,false,nil,)if err != nil {log.Fatalf("Failed to declare a queue: %v", err)}msgs, err := ch.Consume(q.Name,"",true,false,false,false,nil,)if err != nil {log.Fatalf("Failed to register a consumer: %v", err)}for msg := range msgs {log.Printf("Received message: %s", msg.Body)}
}
1.3 进阶用法示例

在实际应用中,除了基本的连接和发送消息外,处理消息队列中的错误和确认机制也是至关重要的。下面展示一个更完整的示例,包括错误处理和消息确认:

package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()ch, err := conn.Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()q, err := ch.QueueDeclare("hello",false,false,false,false,nil,)if err != nil {log.Fatalf("Failed to declare a queue: %v", err)}msgs, err := ch.Consume(q.Name,"",true,false,false,false,nil,)if err != nil {log.Fatalf("Failed to register a consumer: %v", err)}forever := make(chan bool)go func() {for msg := range msgs {log.Printf("Received message: %s", msg.Body)// Simulate error handlingif string(msg.Body) == "error" {log.Println("Error processing message")// Handle error scenario}// Acknowledge the messageerr := msg.Ack(false)if err != nil {log.Printf("Error acknowledging message: %v", err)}}}()log.Printf("Waiting for messages. To exit press CTRL+C")<-forever
}
1.4 效率优化

为了提高消息队列的性能和稳定性,可以采取一些优化措施,如使用连接池、设置心跳等。以下是一个简单的示例,展示如何使用连接池来管理RabbitMQ连接:

package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()pool := make(chan *amqp.Connection, 5)pool <- conn// 使用连接池中的连接进行操作ch, err := (<-pool).Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()// 在完成操作后将连接放回连接池pool <- conn
}

2. Go-stomp: STOMP库

2.1 功能介绍

Go-stomp是一个用于处理STOMP(简单文本协议消息传递)的Go语言库。它允许您与支持STOMP协议的消息代理进行通信,发送和接收消息,以及管理队列和订阅。

2.2 使用示例
package mainimport ("context""fmt""log""github.com/go-stomp/stomp"
)func main() {conn, err := stomp.Dial("tcp", "localhost:61613")if err != nil {log.Fatalf("Failed to connect to STOMP server: %v", err)}defer conn.Disconnect()sub, err := conn.Subscribe("/queue/test", stomp.AckAuto)if err != nil {log.Fatalf("Failed to subscribe to queue: %v", err)}for {msg := <-sub.Cfmt.Println("Received message:", string(msg.Body))}
}

2.3 高级用法示例

在实际应用中,处理STOMP消息时可能需要更多的功能,如超时处理、异步发送和订阅多个目标等。下面是一个展示这些高级用法的示例代码:

package mainimport ("context""fmt""log""time""github.com/go-stomp/stomp"
)func main() {conn, err := stomp.Dial("tcp", "localhost:61613")if err != nil {log.Fatalf("Failed to connect to STOMP server: %v", err)}defer conn.Disconnect()sub1, err := conn.Subscribe("/queue/test1", stomp.AckAuto)if err != nil {log.Fatalf("Failed to subscribe to queue test1: %v", err)}sub2, err := conn.Subscribe("/queue/test2", stomp.AckAuto)if err != nil {log.Fatalf("Failed to subscribe to queue test2: %v", err)}ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()for {select {case msg1 := <-sub1.C:fmt.Println("Received message from test1:", string(msg1.Body))case msg2 := <-sub2.C:fmt.Println("Received message from test2:", string(msg2.Body))case <-ctx.Done():log.Println("Exiting due to timeout")return}}
}

2.4 安全性考虑

当与STOMP服务器通信时,确保数据传输的安全性至关重要。您可以通过添加TLS/SSL支持来加密通信,以下是一个简单示例:

package mainimport ("context""crypto/tls""fmt""log""github.com/go-stomp/stomp"
)func main() {tlsConfig := &tls.Config{InsecureSkipVerify: true, // 在生产环境中请勿使用此选项}conn, err := stomp.DialTLS("tcp", "localhost:61614", stomp.ConnOpt.TLS(tlsConfig))if err != nil {log.Fatalf("Failed to connect to STOMP server: %v", err)}defer conn.Disconnect()// Perform STOMP operations...
}

3. Go-nats: NATS库

3.1 功能介绍

Go-nats是一个用于连接和与NATS(快速且轻量级的消息系统)进行通信的Go语言库。它提供了简单的发布-订阅模型和请求-响应模式,适用于构建高性能和可伸缩的分布式系统。

3.2 使用示例
package mainimport ("fmt""log""github.com/nats-io/nats.go"
)func main() {nc, err := nats.Connect(nats.DefaultURL)if err != nil {log.Fatalf("Failed to connect to NATS server: %v", err)}defer nc.Close()// 发布消息err = nc.Publish("subject", []byte("Hello NATS"))if err != nil {log.Fatalf("Failed to publish message: %v", err)}// 订阅消息nc.Subscribe("subject", func(m *nats.Msg) {fmt.Printf("Received message: %s\n", string(m.Data))})select {}
}
3.3 进阶应用示例

在实际项目中,除了基本的发布和订阅外,还有许多高级功能可供利用,例如请求-响应模式、负载均衡等。以下是一个展示这些进阶应用的示例代码:

package mainimport ("fmt""log""github.com/nats-io/nats.go"
)func main() {nc, err := nats.Connect(nats.DefaultURL)if err != nil {log.Fatalf("Failed to connect to NATS server: %v", err)}defer nc.Close()// 请求-响应模式_, err = nc.Request("request.subject", []byte("Request message"), 1000)if err != nil {log.Fatalf("Failed to send request: %v", err)}// 负载均衡sub, err := nc.QueueSubscribe("queue.subject", "worker", func(m *nats.Msg) {fmt.Printf("%s received: %s\n", m.Subject, string(m.Data))})if err != nil {log.Fatalf("Failed to subscribe to queue: %v", err)}sub.AutoUnsubscribe(1) // 自动取消订阅第一条消息select {}
}
3.4 安全性与认证

确保与NATS服务器之间的通信是安全和经过身份验证的至关重要。以下是如何配置TLS和用户身份验证的示例代码:

package mainimport ("log""github.com/nats-io/nats.go"
)func main() {opts := []nats.Option{nats.Name("NATS Secure Connection"),nats.UserInfo("username", "password"),nats.Token("token"),nats.Secure(),nats.TLSFiles("ca.pem", "cert.pem", "key.pem"),}nc, err := nats.Connect("tls://nats-server:4222", opts...)if err != nil {log.Fatalf("Failed to connect to NATS server: %v", err)}defer nc.Close()// Perform NATS operations...
}

4. Go-kafka: Kafka库

4.1 功能介绍

Go-kafka是一个用于与Apache Kafka进行交互的Go语言库。Apache Kafka是一个分布式流处理平台,Go-kafka库使得在Go应用程序中能够方便地生产和消费Kafka消息。

4.2 使用示例
package mainimport ("log""github.com/Shopify/sarama"
)func main() {config := sarama.NewConfig()producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)if err != nil {log.Fatalf("Failed to create Kafka producer: %v", err)}defer producer.Close()msg := &sarama.ProducerMessage{Topic: "test-topic",Value: sarama.StringEncoder("Hello Kafka"),}_, _, err = producer.SendMessage(msg)if err != nil {log.Fatalf("Failed to produce message: %v", err)}
}
4.3 高级应用示例

除了基本的生产和消费消息外,Kafka还支持分区、偏移量管理等高级功能。以下是一个展示如何使用Sarama库来实现从Kafka消费消息并手动提交偏移量的示例代码:

package mainimport ("log""os""os/signal""github.com/Shopify/sarama"
)func main() {config := sarama.NewConfig()consumer, err := sarama.NewConsumer([]string{"localhost:9092"}, config)if err != nil {log.Fatalf("Failed to create Kafka consumer: %v", err)}defer consumer.Close()partitionConsumer, err := consumer.ConsumePartition("test-topic", 0, sarama.OffsetOldest)if err != nil {log.Fatalf("Failed to consume partition: %v", err)}signals := make(chan os.Signal, 1)signal.Notify(signals, os.Interrupt)ConsumerLoop:for {select {case msg := <-partitionConsumer.Messages():log.Printf("Received message: %s\n", string(msg.Value))// 在此处处理消息consumer.MarkOffset(msg, "")case <-signals:break ConsumerLoop}}
}
4.4 容错处理

在与Kafka交互时,容错处理是至关重要的,可以通过设置重试机制和错误处理来提高系统的可靠性。以下是一个示例代码,展示如何配置重试机制和错误处理:

package mainimport ("log""github.com/Shopify/sarama"
)func main() {config := sarama.NewConfig()config.Producer.Retry.Max = 5config.Producer.RequiredAcks = sarama.WaitForAllproducer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)if err != nil {log.Fatalf("Failed to create Kafka producer: %v", err)}defer producer.Close()msg := &sarama.ProducerMessage{Topic: "test-topic",Value: sarama.StringEncoder("Hello Kafka"),}_, _, err = producer.SendMessage(msg)if err != nil {log.Fatalf("Failed to produce message: %v", err)}
}

5. Go-nsq: NSQ库

5.1 功能介绍

Go-nsq是一个用于与NSQ(实时分布式消息传递平台)集成的Go语言库。NSQ具有高可靠性和可伸缩性,Go-nsq库使得在Go应用程序中能够轻松地生产和消费NSQ消息。

5.2 使用示例
package mainimport ("log""os""os/signal""syscall""github.com/nsqio/go-nsq"
)func main() {cfg := nsq.NewConfig()producer, err := nsq.NewProducer("localhost:4150", cfg)if err != nil {log.Fatalf("Failed to create NSQ producer: %v", err)}defer producer.Stop()err = producer.Publish("test-topic", []byte("Hello NSQ"))if err != nil {log.Fatalf("Failed to publish message: %v", err)}signalChan := make(chan os.Signal, 1)signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)<-signalChan
}
5.3 进阶应用示例

在实际项目中,可能需要处理更复杂的场景,如消费者并发处理、消息重试等。以下是一个展示如何使用Go-nsq库编写具有消息重试和并发消费功能的NSQ消费者的示例代码:

package mainimport ("log""os""os/signal""syscall""github.com/nsqio/go-nsq"
)type ConsumerHandler struct{}func (h *ConsumerHandler) HandleMessage(msg *nsq.Message) error {log.Printf("Received message: %s", msg.Body)return nil
}func main() {cfg := nsq.NewConfig()consumer, err := nsq.NewConsumer("test-topic", "channel1", cfg)if err != nil {log.Fatalf("Failed to create NSQ consumer: %v", err)}consumer.AddHandler(&ConsumerHandler{})err = consumer.ConnectToNSQD("localhost:4150")if err != nil {log.Fatalf("Could not connect to NSQD: %v", err)}signalChan := make(chan os.Signal, 1)signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)<-signalChan
}
5.4 稳定性与故障恢复

确保在与NSQ集成时具备稳定性和故障恢复机制非常重要。下面是一个示例代码,展示如何配置NSQ生产者以支持故障恢复:

package mainimport ("log""time""github.com/nsqio/go-nsq"
)func main() {cfg := nsq.NewConfig()producer, err := nsq.NewProducer("localhost:4150", cfg)if err != nil {log.Fatalf("Failed to create NSQ producer: %v", err)}defer producer.Stop()err = producer.Publish("test-topic", []byte("Hello NSQ"))if err != nil {log.Printf("Publish failed: %v", err)// 在这里添加对失败情况的处理逻辑time.Sleep(time.Second) // 等待一段时间后重试err = producer.Publish("test-topic", []byte("Hello NSQ"))if err != nil {log.Fatalf("Failed to publish message after retry: %v", err)}}
}

6. Go-rabbitmq: RabbitMQ库

6.1 功能介绍

Go-rabbitmq是一个用于与RabbitMQ消息代理进行通信的Go语言库。RabbitMQ是一个功能丰富的消息代理,Go-rabbitmq库使得在Go应用程序中可以方便地与RabbitMQ进行集成,实现消息的发布和订阅。

6.2 使用示例
package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()ch, err := conn.Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()q, err := ch.QueueDeclare("hello",false,false,false,false,nil,)if err != nil {log.Fatalf("Failed to declare a queue: %v", err)}msgs, err := ch.Consume(q.Name,"",true,false,false,false,nil,)if err != nil {log.Fatalf("Failed to register a consumer: %v", err)}for msg := range msgs {log.Printf("Received message: %s", msg.Body)}
}
6.3 高级应用示例

除了基本的消息发布和订阅外,RabbitMQ还提供了更多功能,如交换机、确认模式等。以下是一个展示如何在Go应用程序中使用RabbitMQ库实现消息确认模式的示例代码:

package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()ch, err := conn.Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()err = ch.Confirm(false)if err != nil {log.Fatalf("Failed to set channel in confirm mode: %v", err)}q, err := ch.QueueDeclare("hello",false,false,false,false,nil,)if err != nil {log.Fatalf("Failed to declare a queue: %v", err)}msg := amqp.Publishing{Body: []byte("Hello RabbitMQ"),}err = ch.Publish("",q.Name,false,false,msg,)if err != nil {log.Fatalf("Failed to publish message: %v", err)}select {}
}
6.4 可靠性与持久化

确保消息传递的可靠性和持久化对于消息代理非常重要。下面是一个示例代码,展示如何配置RabbitMQ以支持消息持久化:

package mainimport ("log""github.com/streadway/amqp"
)func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")if err != nil {log.Fatalf("Failed to connect to RabbitMQ: %v", err)}defer conn.Close()ch, err := conn.Channel()if err != nil {log.Fatalf("Failed to open a channel: %v", err)}defer ch.Close()q, err := ch.QueueDeclare("hello",true,  // 设置队列为持久化false,false,false,nil,)if err != nil {log.Fatalf("Failed to declare a queue: %v", err)}
}

总结

通过本文的介绍和示例代码,读者将了解如何在Go语言项目中集成各种消息队列功能。从连接到消息代理、声明队列和交换机,到发送和接收消息,每个库都提供了方便且高效的方法来处理消息传递任务。选择合适的消息队列库取决于项目需求和性能要求,但无论选择哪个库,都可以极大地简化消息通信并提高系统的可靠性和可伸缩性。

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

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

相关文章

LeetCode_Java_递归系列(题目+思路+代码)

206.反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]以此类推&#xff0c;直到反转结束返回头结点 class Solution {public ListNode rever…

是德科技N9020A信号分析仪

181/2461/8938产品概述&#xff1a; N9020A MXA信号分析仪通过增加针对新一代技术的信号分析和频谱分析能力&#xff0c;具备了中档分析仪的更高性能。它突破了以往分析仪的极限&#xff0c;支持业界更快的信号和频谱分析,实现了速度与性能的更佳优化。 速度 测试速度超过其它…

动态规划专题之不同路径

LC 62 不同的路径 dp数组以及下标的含义 dp[i][j]:从起点到第i行第j列的方案数为dp[i][j] 递推公式 这么想&#xff0c;当前状态可以由哪些状态得到&#xff1f;由于它只能向下或向右走&#xff0c;所以就只能向下走到第i行第j列或向右走到第i行第j列 所以dp[i][j]dp[i-1][…

linux之shell脚本基础

1.构建基础脚本 1.1 创建shell脚本 1.1.1 第一行需要指定使用的shell # 用作注释行.shell并不会处理脚本中的注释行,但是第一行的注释,会告诉shell使用哪个shell来运行脚本. #!/bin/bash 1.1.2 让shell找到你的脚本 直接运行脚本会提示-bash: a.sh: command not found.因…

jupyter notebook或jupyterlab运行于/切换指定的conda虚拟环境或显示所有环境方法

Jupyter 在一个名为 kernel 的单独进程中运行用户的代码。kernel 可以是不同的 Python 安装在不同的 conda 环境或虚拟环境&#xff0c;甚至可以是不同语言&#xff08;例如 Julia 或 R&#xff09;的解释器。 如何使用 conda 环境和 Jupyter 有三种方法&#xff1a; 1. 在 c…

ES同步失败维护步骤(适用于修改了部分主键值导致同步失败)

维护步骤&#xff1a; 登录到ES服务器&#xff1a;192.168.111.141。停止 Canal 和 Canal-Adapter 服务&#xff1a;cd /home/xiangtan/canal/bin ./stop.shcd /home/xiangtan/canal-adapter/bin ./stop.sh确定修改了主键值的表&#xff0c;例如 tbl_sparking&#xff0c;使用…

一套键盘鼠标控制两台电脑 Mouse Without Borders

有两台电脑&#xff0c;一台笔记本一台台式机&#xff0c;拥有各自拥有鼠标和键盘&#xff0c;但总是需要切换&#xff0c;感觉太麻烦&#xff0c;想找个简单的方式&#xff0c;不需要额外操作就能同时操作这两台电脑。无意间发现了一个微软软件Mouse Without Borders&#xff…

算法体系-13 第十三 二叉树的基本算法+二叉树的递归套路

一 完全二叉树的判断 1.1 描述 完全二叉树&#xff1a;他每一层都是满的&#xff0c;即使不满也是最后一层不满&#xff0c;最后一层不满也是从左到右变满的&#xff1b;话句话说就是 完全二叉树从根结点到倒数第二层满足完美二叉树&#xff0c;最后一层可以不完全填充&#x…

MySQL数据库 - 索引

一. 索引的相关知识 1. 索引的概念 是一个排序的列表&#xff0c;存储着索引值和这个值所对应的物理地址&#xff08;类似于C语言的链表通过指针指向数据记录的内存地址&#xff09;使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索引表找到该行数据对应…

How to install PyAlink on Ubuntu 22.04

How to install PyAlink on Ubuntu 22.04 环境准备准备conda python环境创建项目虚拟环境激活虚拟环境 安装脚本细节 环境准备 准备conda python环境 关于如何安装conda环境&#xff0c;可以参阅我此前整理的如下文章&#xff1a; How to install Miniconda on ubuntu 22.04…

一句话讲清脏读 、丢失修改、不可重复读、幻读

脏读 : 一个事务读取到了另一个事务回滚之前的数据. 丢失修改 : 两个事务同时访问一个数据时,一个事务在修改的时候不能获取到另一个事务先前已经修改过的内容. 不可重复读:一个事务A内在第二次查询的时候,查到了另一个事务B在A事务第一次查询之后修改的数据. 幻读&#xff…

【Godot 3.5控件】用TextureProgress制作血条

说明 本文写自2022年11月13日-14日&#xff0c;内容基于Godot3.5。后续可能会进行向4.2版本的转化。 概述 之前基于ProgressBar创建过血条组件。它主要是基于修改StyleBoxFlat&#xff0c;好处是它几乎可以算是矢量的&#xff0c;体积小&#xff0c;所有东西都是样式信息&am…

基于Arduino IDE 野火ESP8266模块WIiFi开发

一、函数介绍 头文件 #include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h>ESP8266WiFi.h库主要用于连接单个WiFi网络。如果需要连接到多个WiFi网络&#xff0c;例如在需要切换不同网络或者备用网络时&#xff0c;可以使用ESP8266WiFiMulti.h头文件&#xff…

mysql的基本知识点-排序和分组

分组&#xff08;GROUP BY&#xff09; GROUP BY 语句用于结合聚合函数&#xff0c;根据一个或多个列对结果集进行分组。例如&#xff0c;假设你有一个包含销售数据的表&#xff0c;并且你想按产品类别计算总销售额。你可以使用 GROUP BY 和 SUM() 函数来实现这一点。 SELECT…

策略模式业务实战

一、策略模式实现任务分发 1.新建策略接口 package com.ehe.elder.strategy;public interface ElderJobOrderStrategy {void notifyMethod(String outTradeNo); }2.新建策略实现类 Slf4j Component public class ElderJobOrderGranter implements ElderJobOrderStrategy {pu…

【Leetcode】top 100 多维动态规划

62 不同路径 一个机器人位于一个 m x n 网格的左上角&#xff0c;机器人每次只能向下或者向右移动一步&#xff0c;机器人试图达到网格的右下角&#xff0c;问总共有多少条不同的路径&#xff1f; 分析&#xff1a;dp[i][j] 代表走到 (i, j) 的路径总和数 递推规律&#xff1a…

java.lang.String final

关于String不可变的问题&#xff1a;从毕业面试到现在&#xff0c;一个群里讨论的东西&#xff0c;反正码农面试啥都有&#xff0c;这也是我不咋喜欢面试代码&#xff0c;因为对于我而言&#xff0c;我并不喜欢这些面试。知道或不知道基本没啥含氧量&#xff0c;就是看看源代码…

构造函数调用规则

默认情况下&#xff0c;c编译器至少给一个类添加3个函数 1&#xff0e;默认构造函数(无参&#xff0c;函数体为空) 2&#xff0e;默认析构函数(无参&#xff0c;函数体为空) 3&#xff0e;默认拷贝构造函数&#xff0c;对属性进行值拷贝(“”号赋值) 构造函数调用规则如下&…

大数据,或称巨量资料

大数据&#xff0c;或称巨量资料&#xff0c;指的是在传统数据处理应用软件不足以处理的大或复杂的数据集。大数据也可以定义为来自各种来源的大量非结构化或结构化数据。从学术角度而言&#xff0c;大数据的出现促成广泛主题的新颖研究&#xff0c;这也导致各种大数据统计方法…

【ZooKeeper】2、安装

本文基于 Apache ZooKeeper Release 3.7.0 版本书写 作于 2022年3月6日 14:22:11 转载请声明 下载zookeeper安装包 wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz解压 tar -zxvf apache-zookeeper-3.7.0-b…