Go 实现线程安全栈

问题

使用切片实现栈,要求线程安全。

思路

栈主要特征就是数据先进后出,操作主要有push/pop/top/isempty,使用切片保存数据,为了线程安全,增加读写锁。

实现

直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// SafeStack 线程安全栈
type SafeStack struct {
data []interface{}
sync.RWMutex
}

func (s *SafeStack) initSilce() {
if s.data == nil {
s.data = make([]interface{}, 0)
}
}

// Push Push
func (s *SafeStack) Push(v interface{}) {
s.Lock()
defer s.Unlock()
s.initSilce()
s.data = append(s.data, v)
}

// Pop Pop
func (s *SafeStack) Pop() (interface{}, error) {
s.Lock()
defer s.Unlock()
s.initSilce()
lenght := len(s.data)
if lenght == 0 {
return nil, errors.New("empty")
}
result := s.data[lenght-1]
s.data = s.data[:lenght-1]
return result, nil
}

// Top Top
func (s *SafeStack) Top() (interface{}, error) {
s.RLock()
defer s.RUnlock()
if s.data == nil || len(s.data) == 0 {
return nil, errors.New("empty")
}
return s.data[len(s.data)-1], nil
}

// IsEmpty IsEmpty
func (s *SafeStack) IsEmpty() bool {
s.RLock()
defer s.RUnlock()
return s.data == nil || len(s.data) == 0
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func main() {
s := &SafeStack{}

fmt.Println(s.IsEmpty())
_, err1 := s.Top()
if err1 != nil {
fmt.Println(err1)
}
_, err2 := s.Pop()
if err2 != nil {
fmt.Println(err2)
}
for i := 0; i < 10; i++ {
s.Push(i)
}
fmt.Println(s.IsEmpty())
v3, err3 := s.Top()
if err3 != nil {
fmt.Println(err3)
}
fmt.Println(v3)
v4, err4 := s.Pop()
if err4 != nil {
fmt.Println(err4)
}
fmt.Println(v4)
for {
v5, err5 := s.Pop()
if err5 != nil {
fmt.Println(err5)
break
}
fmt.Println(v5)
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
true
empty
empty
false
9
9
8
7
6
5
4
3
2
1
0
empty