diff --git a/g/container/gchan/gchan.go b/g/container/gchan/gchan.go index 9e762162f..eeba2e153 100644 --- a/g/container/gchan/gchan.go +++ b/g/container/gchan/gchan.go @@ -10,55 +10,61 @@ package gchan import ( - "errors" - "github.com/gogf/gf/g/container/gtype" + "errors" + + "github.com/gogf/gf/g/container/gtype" ) // Graceful channel. type Chan struct { - channel chan interface{} - closed *gtype.Bool + channel chan interface{} + closed *gtype.Bool } // New creates a graceful channel with given . func New(limit int) *Chan { - return &Chan { - channel : make(chan interface{}, limit), - closed : gtype.NewBool(), - } + return &Chan{ + channel: make(chan interface{}, limit), + closed: gtype.NewBool(), + } } // Push pushes to channel. // It is safe to be called repeatedly. func (c *Chan) Push(value interface{}) error { - if c.closed.Val() { - return errors.New("channel is closed") - } - c.channel <- value - return nil + if c.closed.Val() { + return errors.New("channel is closed") + } + c.channel <- value + return nil } // Pop pops value from channel. // If there's no value in channel, it would block to wait. // If the channel is closed, it will return a nil value immediately. func (c *Chan) Pop() interface{} { - return <- c.channel + return <-c.channel } // Close closes the channel. // It is safe to be called repeatedly. func (c *Chan) Close() { - if !c.closed.Set(true) { - close(c.channel) - } + if !c.closed.Set(true) { + close(c.channel) + } } // See Len. func (c *Chan) Size() int { - return c.Len() + return c.Len() } // Len returns the length of the channel. func (c *Chan) Len() int { return len(c.channel) -} \ No newline at end of file +} + +// Cap returns the capacity of the channel. +func (c *Chan) Cap() int { + return cap(c.channel) +} diff --git a/g/container/gchan/gchan_z_unit_test.go b/g/container/gchan/gchan_z_unit_test.go new file mode 100644 index 000000000..057113627 --- /dev/null +++ b/g/container/gchan/gchan_z_unit_test.go @@ -0,0 +1,47 @@ +package gchan_test + +import ( + "errors" + "testing" + + "github.com/gogf/gf/g/container/gchan" + "github.com/gogf/gf/g/test/gtest" +) + +func Test_Gchan(t *testing.T) { + gtest.Case(t, func() { + ch := gchan.New(10) + + gtest.Assert(ch.Cap(), 10) + gtest.Assert(ch.Push(1), nil) + gtest.Assert(ch.Len(), 1) + gtest.Assert(ch.Size(), 1) + ch.Pop() + gtest.Assert(ch.Len(), 0) + gtest.Assert(ch.Size(), 0) + ch.Close() + gtest.Assert(ch.Push(1), errors.New("channel is closed")) + + ch = gchan.New(0) + ch1 := gchan.New(0) + go func() { + var i = 0 + for { + v := ch.Pop() + if v == nil { + ch1.Push(i) + break + } + gtest.Assert(v, i) + i++ + } + }() + + for index := 0; index < 10; index++ { + ch.Push(index) + } + ch.Close() + gtest.Assert(ch1.Pop(), 10) + ch1.Close() + }) +}