Testing 如何测试Golang通道/围棋程序

Testing 如何测试Golang通道/围棋程序,testing,concurrency,go,testify,Testing,Concurrency,Go,Testify,我有一个类型,它包含一个字节的数据,并使用一个通道将新数据发布到那里。其他代码可以使用read函数读取最后写入的数据字节 编辑:有关实际的可运行代码,请特别参阅文件acia6551.go和acia6551_test.go。测试结果可在此处查看: 我有以下资料: // Emulates a serial interface chip of some kind. type Unit struct { // Channel used for others to use, bytes written

我有一个类型,它包含一个字节的数据,并使用一个通道将新数据发布到那里。其他代码可以使用read函数读取最后写入的数据字节

编辑:有关实际的可运行代码,请特别参阅文件acia6551.go和acia6551_test.go。测试结果可在此处查看:

我有以下资料:

// 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路由开始写入数据之前。但在阅读之前,张贴的信息总是打印出来的

因此,还有两个问题:

这是以9600波特处理传入字节流的最佳方法- 如果这是正确的方法,我如何正确地测试它或我的代码有什么问题?
从这里发布的文章来看,在访问存储的数据时,似乎没有任何东西可以保证操作的顺序。您可以在goroutine之间共享的任何数据周围使用互斥锁

这里更好的选择是使用长度为1的缓冲通道来写入、存储和读取字节

使用-race来测试程序总是一个好主意,使用race检测器


因为这看起来非常像流,所以您可能需要一些缓冲,并查看一些io.Reader和io.Writer接口常用的示例

请修改你的代码。您缺少一个右括号,并且rxChar未在Read方法中声明。rxData应该是rxChar吗?@JimB修复了我的代码。如果你发布了一些可以运行的东西,这会有所帮助。没有办法知道rxData和rxChar之间发生了什么。这个goroutine中有这么多代码。它大约相当于go func{for unit.rxData=range unit.Rx{fmt.PrintfPosted 0x%02X\n,data}但如果你关闭channelI+1@Dustin,这将正确终止。同样在你的github提交中。我建议在你的实现中根本不要使用通道。只需创建一个实现io的类。所有这些串行接口都是可读的。没错,这就是我在问题中试图描述的。但我如何实现这一点?使用通道或互斥体看看编辑是否有帮助。作为旁白-我更喜欢本视频中描述的通道扇形:而不是依赖其他同步机制,如互斥体。如果你来自另一种语言,它们更容易解释。当然,我来自C语言,这对我来说也是一样的-但视频中描述的技术e在围棋生态系统中更有意义。只是把它作为一种选择留在这里。事实证明,让Acia6551或单元实现io.Reader和io.Writer对我来说要好得多。感谢你指出这一点并告诉我-race,它实际上非常有用。除了JimB所写的之外,还有一个更好的主意,就是在围棋期间使用无缓冲通道ng开发。如果未缓冲通道未出现死锁,那么在以后添加缓冲时也不会出现死锁。添加缓冲仅仅是一个优化步骤。此策略是一个很好的方法,可以清楚地考虑设计中的并发性,尤其是消除经常导致死锁的循环依赖性。