2016-12-05 20 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

相關問題