golang 结构体使用chan

本文展示了一个使用Golang编写的并发程序示例,通过生产者消费者模式演示了通道(channel)的使用。代码中定义了一个test1结构体,并创建了一个容量为10的通道。生产者函数连续发送10个不同状态的test1实例到通道,而消费者函数从通道接收并打印这些实例。主函数中启动了生产者和消费者协程,并等待一段时间确保所有数据被处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

附上test代码,以便后续查看使用
package main

import (
“fmt”
“time”
)

type test1 struct {
a string
b int
c int
d int
}

func produce(p chan<- test1) {
aaa := test1{
a: “aaaaaa”,
b: 1,
c: 1,
}
for i := 0; i < 10; i++ {
aaa.b = i
aaa.c = i
aaa.d = i
p <- aaa
fmt.Println(“send:”, i)
time.Sleep(1 * time.Second)
}
}
func consumer(c <-chan test1) {
for i := 0; i < 10; i++ {
v := <-c
fmt.Println(“receive:”, v)
}
}
func main() {
ch := make(chan test1, 10)
go produce(ch)
go consumer(ch)
time.Sleep(20 * time.Second)
}

### Golang 实现任务队列 在 Go 语言中,可以通过多种方式实现任务队列。以下是几种常见的方法及其对应的示例代码。 #### 方法一:基于切片的简单队列 通过定义一个结构体使用切片作为底层存储机制,可以轻松实现一个基本的任务队列。此方法适合小型项目或学习目的。 ```go package main import "fmt" type Queue struct { items []interface{} } func (q *Queue) Enqueue(item interface{}) { q.items = append(q.items, item) } func (q *Queue) Dequeue() interface{} { if len(q.items) == 0 { return nil } item := q.items[0] q.items = q.items[1:] return item } func (q *Queue) Length() int { return len(q.items) } func main() { queue := &Queue{} fmt.Println(queue.Length()) // 输出: 0 queue.Enqueue("Task 1") queue.Enqueue("Task 2") fmt.Println(queue.Dequeue()) // 输出: Task 1 fmt.Println(queue.Length()) // 输出: 1 } ``` 这种方法适用于简单的场景[^1]。 --- #### 方法二:基于通道(Channel)的任务队列 Go 的并发特性使其非常适合用于构建高效的任务队列。利用 `channel` 和多个 Goroutines 可以创建一个高效的生产者-消费者模式。 ```go package main import ( "fmt" "time" ) func worker(id int, jobs <-chan string, results chan<- string) { for job := range jobs { fmt.Printf("Worker %d processing task '%s'\n", id, job) time.Sleep(time.Second) // Simulate work being done results <- fmt.Sprintf("Result of %s by Worker %d", job, id) } } func main() { const numJobs = 5 jobs := make(chan string, numJobs) results := make(chan string, numJobs) // Start workers for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // Send tasks to the queue for j := 1; j <= numJobs; j++ { jobs <- fmt.Sprintf("Job-%d", j) } close(jobs) // Collect all results for a := 1; a <= numJobs; a++ { result := <-results fmt.Println(result) } } ``` 上述代码展示了如何使用通道和 Goroutines 来分发任务,并让多个工作线程处理它们。这种方式能够有效避免单个消费者的任务积压问题[^2]。 --- #### 方法三:集成 RabbitMQ 或其他消息中间件 对于更复杂的分布式系统,建议使用专业的消息队列服务(如 RabbitMQ)。为了确保任务公平分配给所有可用消费者,可以在客户端启用 QoS 设置: ```go package main import ( "log" "github.com/streadway/amqp" ) func failOnError(err error, msg string) { if err != nil { log.Fatalf("%s: %s", msg, err) } } func main() { conn, err := amqp.Dial("amqp://guest:guest@localhost/") failOnError(err, "Failed to connect to RabbitMQ") defer conn.Close() ch, err := conn.Channel() failOnError(err, "Failed to open a channel") defer ch.Close() err = ch.Qos( 1, // prefetch count 0, // prefetch size false, // global ) failOnError(err, "Failed to set qos") msgs, err := ch.Consume( "task_queue", // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") forever := make(chan bool) go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) d.Ack(false) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") <-forever } ``` 这段代码设置了每名消费者最多只能同时处理一条未完成的任务,从而防止某些消费者过载而另一些闲置的情况发生[^3]。 --- #### 方法四:环形队列的应用扩展 如果需要进一步优化性能或者支持特定功能(例如流量控制),则可采用环形队列的设计思路。这种方案特别适合于高吞吐量的数据流管理。 ```go package main import "sync/atomic" const capacity = 8 type CircularQueue struct { data [capacity]interface{} head uint64 tail uint64 size uint64 capcity uint64 } func NewCircularQueue(capacity uint64) *CircularQueue { return &CircularQueue{capcity: capacity} } func (cq *CircularQueue) Push(value interface{}) bool { if cq.size >= cq.capcity { return false } index := atomic.AddUint64(&cq.tail, 1)%cq.capcity cq.data[index] = value atomic.AddUint64(&cq.size, 1) return true } func (cq *CircularQueue) Pop() interface{} { if cq.IsEmpty() { return nil } index := atomic.AddUint64(&cq.head, 1)%cq.capcity value := cq.data[index] atomic.AddUint64(&cq.size, ^uint64(0)) // Decrement size using two's complement. return value } func (cq *CircularQueue) IsEmpty() bool { return atomic.LoadUint64(&cq.size) == 0 } ``` 该实现解决了传统队列可能遇到的“假溢出”问题,提高了资源利用率[^5]。 --- #### 总结 以上介绍了四种不同的任务队列实现方式,分别针对不同需求提供了灵活的选择。无论是基础版还是高级版本,都可以根据实际应用场景调整参数配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值