在Go语言中的pubsub替代方案

huangapple go评论92阅读模式
英文:

pubsub alternative in golang

问题

我有一个已经用JavaScript和pubsub完成的简单任务,任务如下:

我有一个对象,假设为A,还有另外两个对象对某些元素(在这种情况下是字符串)感兴趣,假设Foo对元素mn感兴趣,Bar对元素nop感兴趣。这些兴趣可以相互交叉。

对象A有添加/删除元素的方法,当该对象包含Foo感兴趣的元素mn时,该对象存储在Foo中。以下是使用pubsub的JavaScript伪代码:

var A = {};

var Foo = {
    interests: ['m', 'n'],
    storedObj: {},
    tempObj: {}
};

// Bar与Foo类似,但兴趣不同,为['n', 'o', 'p']

// 在Foo和Bar的构造函数中的某个地方
// Foo和Bar订阅每个兴趣元素
// 对于每个兴趣,在添加时
subscribe('add'+interest, function(obj) {
    // 在tempObj中存储此对象并递增,直到满足所有兴趣
    tempObj[obj]++;

    // 如果此对象满足所有兴趣,则将其存储在对象数组中
    if(tempObj[obj] === len(interests)) {
        storedObj[obj] = true;
    }
});

// 对于每个兴趣,在删除时
subscribe('remove'+interest, function(obj) {
    // 从storedObj中删除
    delete storedObj[obj];

    // 将tempObj递减,以便在兴趣再次添加时可以使用
    tempObj[obj]--;
});

// 在A的原型中
prototype.add = function(interest) {
    publish('add'+interest, this);
    return this;
}
prototype.remove = function(interest) {
    publish('remove'+interest, this);
    return this;
}

// 实现
A.add('m')
 .add('n')
 .add('o')

// 然后A被存储在Foo中,但不在Bar中,因为A没有`p`,但它仍然存储在Bar.tempObj中,并且具有值2,等待添加`p`

A.remove('m')
 .add('p')

// 然后A从Foo中移除并存储在Bar中

我想将这个任务移植到Go语言中,但我不想使用pubsub,我想使用更符合Go语言习惯的方式。注意:我已经在Go语言中使用pubsub完成了这个任务。

你能告诉我如何在Go语言中实现吗?我考虑使用通道,但是找不到解决方案。

英文:

I have simple task that already done in javascript using pubsub, here is the task:

I have object let say A and another 2 object that have interest in some element(string in this case), let say Foo interest in element m, n and Bar interest in element n, o, p. The interest can intersect.

The A object have method adding/remove element and when that object contain m, n element which Foo interest in, then that object stored in Foo here's the pseudo code in javascript using pubsub

var A = {};

var Foo = {
    interests: ['m', 'n'],
    storedObj: {},
    tempObj: {}
};

// Bar same as Foo with different interest ['n', 'o', 'p']

// somewhere in Foo and Bar constructor
// Foo and Bar subscribe too each interests element
// for each interests when add
subscribe('add'+interest, function(obj) {
    // store this obj in tempObj and increment until satisfy all 
    // interest
    tempObj[obj]++;

    // if this obj satisfy all interest then store it in array of obj
    if(tempObj[obj] === len(interests)) {
        storedObj[obj] = true;
    }
});

// for each interests when remove
subscribe('remove'+interest, function(obj) {
    // remove from storedObj
    delete storedObj[obj];

    // decrement tempObj so it can be used for later if the interest 
    // is adding again
    tempObj[obj]--;
});

// inside A prototype
prototype.add = function(interest) {
    publish('add'+interest, this);
    return this;
}
prototype.remove = function(interest) {
    publish('remove'+interest, this);
    return this;
}

// implementation
A.add('m')
 .add('n')
 .add('o')

// then A is stored inside Foo but not in Bar because A doesn't have 
// `p`, but it still stored Bar.tempObj and have value 2 and waiting 
// for `p` to be add

A.remove('m')
 .add('p')

// then A is removed from Foo and stored in Bar

I want to porting this task into golang but i don't want using pubsub, i want more idiomatic to golang way. NOTE: i already done using pubsub in golang as well.

Can you show me how to do it in golang? i'm thingking using channel, but and can't find the solution.

答案1

得分: 1

只是给你一个想法,不一定是你真正的用例。

package main

import (
	"fmt"
	"time"
)

type Publisher struct {
	subscription map[string]chan string
}

func (p *Publisher) Subscribe(interest string) chan string {
	if p.subscription == nil {
		p.subscription = make(map[string]chan string)
	}
	p.subscription[interest] = make(chan string)
	return p.subscription[interest]
}

func (p *Publisher) Add(val string) {
	if p.subscription[val] != nil {
		fmt.Println("Adding " + val)
		p.subscription[val] <- "added " + val
	}
}
func (p *Publisher) Remove(val string) {
	if p.subscription[val] != nil {
		p.subscription[val] <- "removed " + val
	}
}

type Subscriber struct {
	subscriptions []chan string
	publisher     *Publisher
}

func (s *Subscriber) RegisterInterest(interest string) {
	s.subscriptions = append(s.subscriptions, s.publisher.Subscribe(interest))
}
func (s *Subscriber) run(channel chan string) {
	for {
		fmt.Println("Waiting for message")
		m := <-channel
		fmt.Println("Got message: " + m)
	}
}
func (s *Subscriber) Listen() {
	for _, elem := range s.subscriptions {
		go s.run(elem)
	}

}
func main() {
	pub := Publisher{}
	sub := &Subscriber{publisher: &pub}
	sub.RegisterInterest("m")
	sub.RegisterInterest("n")
	sub.Listen()
	pub.Add("m")
	pub.Add("n")
	pub.Remove("m")
	pub.Remove("n")
	time.Sleep(time.Second * 10)
}

希望对你有所帮助!

英文:

Just to give you an idea, not necessarily your real use case.

package main
import (
&quot;fmt&quot;
&quot;time&quot;
)
type Publisher struct {
subscription map[string]chan string
}
func (p *Publisher)Subscribe(interest string) chan string{
if p.subscription == nil {
p.subscription = make(map[string]chan string)
}
p.subscription[interest] = make(chan string)
return p.subscription[interest]
}
func (p *Publisher) Add(val string) {
if p.subscription[val] != nil {
fmt.Println(&quot;Adding &quot; + val)
p.subscription[val] &lt;- &quot;added &quot; + val
}
}
func (p *Publisher) Remove(val string) {
if p.subscription[val] != nil {
p.subscription[val] &lt;- &quot;removed &quot; + val
}
}
type Subscriber struct {
subscriptions [] chan string
publisher *Publisher
}
func (s *Subscriber) RegisterInterest(interest string){
s.subscriptions = append(s.subscriptions, s.publisher.Subscribe(interest))
}
func (s *Subscriber) run(channel chan string) {
for  {
fmt.Println(&quot;Waiting for message&quot;)
m := &lt;- channel
fmt.Println(&quot;Got message : &quot; + m)
}
}
func (s *Subscriber) Listen()  {
for _, elem := range s.subscriptions {
go s.run(elem)
}
}
func main() {
pub := Publisher{}
sub := &amp;Subscriber{publisher: &amp;pub}
sub.RegisterInterest(&quot;m&quot;)
sub.RegisterInterest(&quot;n&quot;)
sub.Listen()
pub.Add(&quot;m&quot;)
pub.Add(&quot;n&quot;)
pub.Remove(&quot;m&quot;)
pub.Remove(&quot;n&quot;)
time.Sleep(time.Second * 10)
}

huangapple
  • 本文由 发表于 2017年5月16日 19:27:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/44000215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定