Как проверить Golang каналы / go-рутины
У меня есть тип, который содержит байт данных и использует канал для размещения новых данных там. Другой код может прочитать последний записанный байт данных, используя Read
функция.
Редактировать: действительный, работающий код, см. https://github.com/ariejan/i6502/pull/3 особенно файлы acia6551.go и acia6551_test.go. Результаты тестов можно посмотреть здесь: https://travis-ci.org/ariejan/i6502/jobs/32862705
У меня есть следующее:
// Emulates a serial interface chip of some kind.
type Unit struct {
// Channel used for others to use, bytes written here will be placed in rxChar
Rx chan byte
// Internal store of the last byte written.
rxChar byte // Internal storage
}
// Used internally to read data store in rxChar
func (u *Unit) Read() byte {
return u.rxChar
}
// Create new Unit and go-routing to listen for Rx bytes
func NewUnit(rx chan byte) *Unit {
unit := &Unit{Rx: rx}
go func() {
for {
select {
case data := <-unit.Rx:
unit.rxData = data
fmt.Printf("Posted 0x%02X\n", data)
}
}
}()
return unit
}
Мой тест выглядит так:
func TestUnitRx(t *testing.T) {
rx := make(chan byte)
u := NewUnit(rx)
// Post a byte to the Rx channel
// This prints "Posted 0x42", as you'd expect
rx <- 0x42
// Using testing
// Should read last byte, 0x42 but fails.
fmt.Println("Reading value...")
assert.Equal(t, 0x42, u.Read())
}
Сначала я подумал, что "Значение чтения" произошло до того, как go-routing приступил к записи данных. Но сообщение "Отправлено" всегда печатается перед "Чтением".
Итак, остаются два вопроса:
- Это лучший способ обработки входящего потока байтов (9600 бод;-))
- Если это правильный путь, как я могу его правильно протестировать или что не так с моим кодом?
1 ответ
Судя по опубликованным здесь частям, похоже, что у вас нет ничего, что гарантировало бы порядок операций при доступе к хранимым данным. Вы можете использовать мьютекс вокруг любых данных, совместно используемых программами.
Лучшим вариантом здесь является использование буферизованных каналов длиной 1 для записи, хранения и чтения байтов.
Это всегда хорошая идея, чтобы проверить вашу программу с -race
использовать детектор гонки.
Так как это выглядит очень "потоковым", вы вполне можете захотеть некоторой буферизации и посмотреть на некоторые примеры того, как io.Reader
а также io.Writer
интерфейсы часто используются.