2016-12-05 61 views
0

接收我试图排序的实施反应golang实现。我有一批观察员。他们只是一堆渠道。一切都封装在其他代码可以订阅和取消订阅的包中。当有订单被创建时,更改将被推送。但是我没有在方法中注册频道接收。值通过方法去发送到通道,不能在外面

package rxOrder 

import (
    "fmt" 
    "time" 

    "errors" 

    "gopkg.in/mgo.v2/bson" 
) 

// Order This is the sample data structure 
type Order struct { 
    id  bson.ObjectId 
    moldID bson.ObjectId 
    bomID  bson.ObjectId 
    deviceID bson.ObjectId 
    userIds []bson.ObjectId 
    name  string 
    orderType string // withOrder, noOrder, makeUp, test 
    startTime time.Time 
    deadline time.Time 
    volume int32 
} 

// OrderMutation This is the struct for sending 
// mutations to observers 
type OrderMutation struct { 
    order Order 
    action string 
} 

// RxOrder This is the node for reactive Order 
// management 
type RxOrder struct { 
    orders []Order 
    observers map[string]chan OrderMutation 
} 

// init This method initialize RxOrder, including 
// orders slice and subscriber map, user cannot 
// initialize a RxOrder object more than once 
func (rx *RxOrder) init() error { 
    if len(rx.orders) == 0 && len(rx.observers) == 0 { 
     rx.orders = make([]Order, 1) 
     rx.observers = make(map[string]chan OrderMutation) 
     return nil 
    } 

    return errors.New("Cannot reinitialize orders") 
} 

// subscribe, add observer to list 
func (rx *RxOrder) subscribe(key string, ch chan OrderMutation) error { 
    if _, ok := rx.observers[key]; ok { 
     return errors.New("Observer already existed") 
    } 

    rx.observers[key] = ch 

    return nil 
} 

// unsubscribe, delete observer from list 
func (rx *RxOrder) unsubscribe(key string) error { 
    if _, ok := rx.observers[key]; !ok { 
     return errors.New("Observer does not exist") 
    } 

    delete(rx.observers, key) 

    return nil 
} 

// createOrder The method for creating an order 
func (rx *RxOrder) createOrder(order Order) error { 

    if !order.id.Valid() { 
     return errors.New("Invalid order id") 
    } 

    if !order.bomID.Valid() { 
     return errors.New("Invalid bom id") 
    } 

    if !order.deviceID.Valid() { 
     return errors.New("Invalid device id") 
    } 

    if !order.moldID.Valid() { 
     return errors.New("Invalid mold id") 
    } 

    if len(order.userIds) < 1 { 
     return errors.New("Empty users list") 
    } 

    for index, userID := range order.userIds { 
     if !userID.Valid() { 
      return errors.New(fmt.Sprint("Invalid user id at index: ", index)) 
     } 
    } 

    if len(order.name) < 1 { 
     return errors.New("Empty order name") 
    } 

    if order.orderType != "withOrder" && order.orderType != "noOrder" && order.orderType != "makeUp" && order.orderType != "test" { 
     return errors.New("Wrong order type") 
    } 

    if order.startTime.After(order.deadline) { 
     return errors.New("Deadline cannot come before start time") 
    } 

    if order.volume < 1 { 
     return errors.New("Empty order is not accepted") 
    } 

    rx.orders = append(rx.orders, order) 

    for _, ch := range rx.observers { 
     ch <- OrderMutation{order, "create"} 
    } 

    return nil 
} 
func TestCreateOrder(t *testing.T) { 
    orderManagement := RxOrder{} 

    orderManagement.init() 

    orderManagement.subscribe("123", make(chan OrderMutation)) 
    orderManagement.subscribe("345", make(chan OrderMutation)) 
    orderManagement.subscribe("768", make(chan OrderMutation)) 

    order := Order{} 
    order.id = bson.NewObjectId() 
    order.bomID = bson.NewObjectId() 
    order.deviceID = bson.NewObjectId() 
    order.moldID = bson.NewObjectId() 
    order.name = "iPhone 8+" 
    order.orderType = "withOrder" 
    order.volume = 5 
    order.startTime = time.Now() 
    order.deadline = order.startTime.AddDate(0, 1, 1) 
    order.userIds = make([]bson.ObjectId, 1) 
    order.userIds = append(order.userIds, bson.NewObjectId()) 

    go func(t *testing.T) { 
     fmt.Println(<-orderManagement.observers["123"]) 
    }(t) 

    orderManagement.createOrder(order) 
    //orderManagement.observers["123"] <- OrderMutation{order, "w"} 

    t.Fail() 
} 

当我做测试,上面的代码打印什么,但如果我取消注释行:

orderManagement.observers["123"] <- OrderMutation{order, "w"} 

一切正常。看来我不能在一个方法内的频道上操作。我如何封装通道操作与封装?

+3

您绝对可以在方法内的通道上操作。你的测试失败,因为总是执行结尾处有一个t.Fail()。你需要有条件地失败。 –

+0

只有通过t.Fail()我可以让测试打印到控制台,通过方法发送的值不被接受的出方 – Nexus2020

+2

我认为你有一个竞争条件存在端接收到。在测试结束之前,不能保证goroutine会打印消息 –

回答

0

的情况取决于以下成果:

难道你createOrder返回一个错误?

如果createOrder有任何错误,那么它不会在频道上发送的任何信息,因此通过评论该行的主要测试功能,而无需等待退出。

你有没有输出,如果添加提到的线,你的主要测试功能将在渠道运作等到协同程序接收消息并打印输出。

如果您createOrder没有错误,你将面临的竞争条件,因为在通道发送除“123”的消息将永远阻止你的主要测试功能。

+0

没有我检查过,即使没有任何错误,也没有收到任何值。 – Nexus2020

+0

它总是打印 致命错误:所有goroutines睡着了 - 僵局! – Nexus2020

+0

'''去 错误:= orderManagement.createOrder(顺序) 如果ERR =零{ fmt.Println( “orderManagement错误:” ERR) }! ''' 添加此检查createOrder犯错,您还可以在这里打一些日志: '''去 为_,CH:=范围rx.observers { H < - OrderMutation {秩序 “打造”}} ''' – sydnash

0

当我这样做后,一切正常。

go func() { 
    for _, ch: = range rx.observers { 
    ch <-OrderMutation { 
     order, "create" 
    } 
    } 
}() 

// create a goroutine to send message 

    func() { 
     orderManagement.createOrder(order) 
    }() 

    select { 
    case val := <-orderManagement.observers["123"]: 
     fmt.Println(val) 
    } 

// then receive on the outside like this 

即使没有解决方法,一切正常。

+0

不过,我仍然愿意接受其他选择 – Nexus2020

相关问题