通过go方法发送到通道的值,不能在外面接收

时间:2016-12-05 09:56:52

标签: go channel

我试图实现一个反应性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"}

一切正常。我似乎无法在一个方法中对通道进行操作。如何在包中封装频道操作?

2 个答案:

答案 0 :(得分:0)

情况取决于以下输出:

createOrder是否返回错误?

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

你没有输出,如果你添加上面提到的行,你的主测试函数将等待通道操作,直到你的协程收到消息并打印输出。

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

答案 1 :(得分:0)

在我这样做之后,一切正常。

0000001d

即使没有解决方法,一切也能正常运作。