Skip to content

Commit e9d8247

Browse files
authored
Merge pull request #3 from hayageek/new_apis
New APIs are added to Array,Slice,Map,Stack & Queue
2 parents ff96c4b + 11b997b commit e9d8247

13 files changed

+813
-169
lines changed

README.md

+34-11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ A thread-safe array with a fixed size.
2424
- `NewArray(size int) *Array[T]` - Creates a new thread-safe array with the given size.
2525
- `(*Array[T]) Get(index int) (T, bool)` - Retrieves the value at the given index.
2626
- `(*Array[T]) Set(index int, value T) bool` - Sets the value at the given index.
27+
- `(*Array[T]) Append(value T)` - Appends a value to the array.
28+
- `(*Array[T]) Remove(index int) bool` - Removes the element at the given index.
29+
- `(*Array[T]) Contains(value T) bool` - Checks if the array contains the specified value.
30+
- `(*Array[T]) Clear()` - Clears all elements from the array.
31+
- `(*Array[T]) Insert(index int, value T) bool` - Inserts a value at the specified index.
32+
- `(*Array[T]) Copy() *Array[T]` - Returns a copy of the array.
2733
- `(*Array[T]) Length() int` - Returns the length of the array.
2834

2935
#### Example
@@ -63,6 +69,12 @@ A dynamically-sized, thread-safe slice.
6369
- `(*Slice[T]) Append(value T)` - Appends a value to the slice.
6470
- `(*Slice[T]) Get(index int) (T, bool)` - Retrieves the value at the given index.
6571
- `(*Slice[T]) Set(index int, value T) bool` - Sets the value at the given index.
72+
- `(*Slice[T]) Remove(index int) bool` - Removes the element at the given index.
73+
- `(*Slice[T]) Contains(value T) bool` - Checks if the slice contains the specified value.
74+
- `(*Slice[T]) Clear()` - Clears all elements from the slice.
75+
- `(*Slice[T]) Insert(index int, value T) bool` - Inserts a value at the specified index.
76+
- `(*Slice[T]) Copy() *Slice[T]` - Returns a copy of the slice.
77+
- `(*Slice[T]) Values() []T` - Returns a slice of all values present in the slice.
6678
- `(*Slice[T]) Length() int` - Returns the length of the slice.
6779

6880
#### Example
@@ -113,6 +125,9 @@ A thread-safe map for storing key-value pairs.
113125
- `(*Map[K, V]) Get(key K) (V, bool)` - Retrieves the value associated with the key.
114126
- `(*Map[K, V]) Set(key K, value V)` - Sets the value for the given key.
115127
- `(*Map[K, V]) Delete(key K)` - Deletes the value associated with the key.
128+
- `(*Map[K, V]) Contains(key K) bool` - Checks if the map contains the specified key.
129+
- `(*Map[K, V]) Clear()` - Clears all key-value pairs from the map.
130+
- `(*Map[K, V]) Copy() *Map[K, V]` - Returns a copy of the map.
116131
- `(*Map[K, V]) Length() int` - Returns the number of key-value pairs in the map.
117132
- `(*Map[K, V]) Keys() []K` - Returns a slice of all keys present in the map.
118133
- `(*Map[K, V]) Values() []V` - Returns a slice of all values present in the map.
@@ -171,14 +186,18 @@ func main() {
171186

172187
A thread-safe stack for safely adding and removing items.
173188

174-
### Methods
189+
#### APIs
175190

176-
- `NewStack() *Stack`: Creates a new thread-safe stack.
177-
- `Push(value interface{})`: Adds an element to the stack.
178-
- `Pop() (interface{}, bool)`: Removes and returns an element from the stack. Returns `false` if the stack is empty.
179-
- `Len() int`: Returns the number of elements in the stack.
191+
- `NewStack() *Stack` - Creates a new thread-safe stack.
192+
- `(*Stack) Push(value interface{})` - Adds an element to the stack.
193+
- `(*Stack) Pop() (interface{}, bool)` - Removes and returns an element from the stack. Returns `false` if the stack is empty.
194+
- `(*Stack) Peek() (interface{}, bool)` - Returns the element at the top of the stack without removing it.
195+
- `(*Stack) IsEmpty() bool` - Checks if the stack is empty.
196+
- `(*Stack) Clear()` - Clears all elements from the stack.
197+
- `(*Stack) Values() []interface{}` - Returns a slice of all elements in the stack.
198+
- `(*Stack) Len() int` - Returns the number of elements in the stack.
180199

181-
### Example
200+
#### Example
182201

183202
```go
184203
package main
@@ -213,12 +232,16 @@ func main() {
213232

214233
A thread-safe queue for safely adding and removing items.
215234

216-
#### Methods
235+
#### APIs
217236

218-
- `NewQueue() *Queue`: Creates a new thread-safe queue.
219-
- `Enqueue(value interface{})`: Adds an element to the queue.
220-
- `Dequeue() (interface{}, bool)`: Removes and returns an element from the queue. Returns `false` if the queue is empty.
221-
- `Len() int`: Returns the number of elements in the queue.
237+
- `NewQueue() *Queue` - Creates a new thread-safe queue.
238+
- `(*Queue) Enqueue(value interface{})` - Adds an element to the queue.
239+
- `(*Queue) Dequeue() (interface{}, bool)` - Removes and returns an element from the queue. Returns `false` if the queue is empty.
240+
- `(*Queue) Peek() (interface{}, bool)` - Returns the element at the front of the queue without removing it.
241+
- `(*Queue) IsEmpty() bool` - Checks if the queue is empty.
242+
- `(*Queue) Clear()` - Clears all elements from the queue.
243+
- `(*Queue) Values() []interface{}` - Returns a slice of all elements in the queue.
244+
- `(*Queue) Len() int` - Returns the number of elements in the queue.
222245

223246
#### Queue Example
224247

array.go

+86-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package threadsafe
22

33
import (
4+
"reflect"
45
"sync"
56
)
67

@@ -13,15 +14,17 @@ type Array[T any] struct {
1314

1415
// NewArray creates a new thread-safe array with a given size.
1516
// Example:
16-
// arr := threadsafe.NewArray
17+
//
18+
// arr := threadsafe.NewArray
1719
func NewArray[T any](size int) *Array[T] {
1820
return &Array[T]{data: make([]T, size)}
1921
}
2022

2123
// Get retrieves the value at the given index.
2224
// It returns the value and a boolean indicating whether the index was valid.
2325
// Example:
24-
// value, ok := arr.Get(2)
26+
//
27+
// value, ok := arr.Get(2)
2528
func (a *Array[T]) Get(index int) (T, bool) {
2629
a.mu.RLock()
2730
defer a.mu.RUnlock()
@@ -35,7 +38,8 @@ func (a *Array[T]) Get(index int) (T, bool) {
3538
// Set sets the value at the given index.
3639
// It returns a boolean indicating whether the operation was successful.
3740
// Example:
38-
// ok := arr.Set(2, 100)
41+
//
42+
// ok := arr.Set(2, 100)
3943
func (a *Array[T]) Set(index int, value T) bool {
4044
a.mu.Lock()
4145
defer a.mu.Unlock()
@@ -48,9 +52,87 @@ func (a *Array[T]) Set(index int, value T) bool {
4852

4953
// Length returns the length of the array.
5054
// Example:
51-
// length := arr.Length()
55+
//
56+
// length := arr.Length()
5257
func (a *Array[T]) Length() int {
5358
a.mu.RLock()
5459
defer a.mu.RUnlock()
5560
return len(a.data)
5661
}
62+
63+
// Append appends a value to the array.
64+
// Example:
65+
//
66+
// arr.Append(10)
67+
func (a *Array[T]) Append(value T) {
68+
a.mu.Lock()
69+
defer a.mu.Unlock()
70+
a.data = append(a.data, value)
71+
}
72+
73+
// Remove removes the element at the given index.
74+
// It returns a boolean indicating whether the operation was successful.
75+
// Example:
76+
//
77+
// ok := arr.Remove(2)
78+
func (a *Array[T]) Remove(index int) bool {
79+
a.mu.Lock()
80+
defer a.mu.Unlock()
81+
if index < 0 || index >= len(a.data) {
82+
return false
83+
}
84+
a.data = append(a.data[:index], a.data[index+1:]...)
85+
return true
86+
}
87+
88+
// Contains checks if the array contains the specified value.
89+
// Example:
90+
//
91+
// contains := arr.Contains(10)
92+
func (a *Array[T]) Contains(value T) bool {
93+
a.mu.RLock()
94+
defer a.mu.RUnlock()
95+
for _, v := range a.data {
96+
if reflect.DeepEqual(v, value) {
97+
return true
98+
}
99+
}
100+
return false
101+
}
102+
103+
// Clear removes all elements from the array.
104+
// Example:
105+
//
106+
// arr.Clear()
107+
func (a *Array[T]) Clear() {
108+
a.mu.Lock()
109+
defer a.mu.Unlock()
110+
a.data = []T{}
111+
}
112+
113+
// Insert inserts a value at the specified index.
114+
// It returns a boolean indicating whether the operation was successful.
115+
// Example:
116+
//
117+
// ok := arr.Insert(2, 10)
118+
func (a *Array[T]) Insert(index int, value T) bool {
119+
a.mu.Lock()
120+
defer a.mu.Unlock()
121+
if index < 0 || index > len(a.data) {
122+
return false
123+
}
124+
a.data = append(a.data[:index], append([]T{value}, a.data[index:]...)...)
125+
return true
126+
}
127+
128+
// Copy returns a new thread-safe array that is a copy of the current array.
129+
// Example:
130+
//
131+
// copyArray := arr.Copy()
132+
func (a *Array[T]) Copy() *Array[T] {
133+
a.mu.RLock()
134+
defer a.mu.RUnlock()
135+
dataCopy := make([]T, len(a.data))
136+
copy(dataCopy, a.data)
137+
return &Array[T]{data: dataCopy}
138+
}

array_test.go

+100-23
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,112 @@ package threadsafe
22

33
import (
44
"testing"
5+
6+
"github.com/stretchr/testify/assert"
57
)
68

7-
func TestArray(t *testing.T) {
8-
// Create a new thread-safe array with size 5
9+
func TestNewArray(t *testing.T) {
910
arr := NewArray[int](5)
11+
assert.Equal(t, 5, arr.Length())
12+
}
1013

11-
// Test setting values
12-
for i := 0; i < arr.Length(); i++ {
13-
if !arr.Set(i, i*10) {
14-
t.Errorf("Failed to set value at index %d", i)
15-
}
16-
}
14+
func TestArrayGetSet(t *testing.T) {
15+
arr := NewArray[int](3)
16+
ok := arr.Set(2, 42)
17+
assert.True(t, ok)
18+
value, ok := arr.Get(2)
19+
assert.True(t, ok)
20+
assert.Equal(t, 42, value)
21+
}
1722

18-
// Test getting values
19-
for i := 0; i < arr.Length(); i++ {
20-
value, ok := arr.Get(i)
21-
if !ok || value != i*10 {
22-
t.Errorf("Expected %d, got %d at index %d", i*10, value, i)
23-
}
24-
}
23+
func TestArrayGetInvalidIndex(t *testing.T) {
24+
arr := NewArray[int](1)
25+
value, ok := arr.Get(10)
26+
assert.False(t, ok)
27+
assert.Equal(t, 0, value)
28+
}
2529

26-
// Test getting value out of range
27-
_, ok := arr.Get(10)
28-
if ok {
29-
t.Error("Expected false for out-of-range index, got true")
30-
}
30+
func TestArraySetInvalidIndex(t *testing.T) {
31+
arr := NewArray[int](1)
32+
ok := arr.Set(10, 42)
33+
assert.False(t, ok)
34+
}
3135

32-
// Test setting value out of range
33-
if arr.Set(10, 100) {
34-
t.Error("Expected false for out-of-range index, got true")
36+
func TestArrayAppend(t *testing.T) {
37+
arr := NewArray[int](0)
38+
arr.Append(42)
39+
assert.Equal(t, 1, arr.Length())
40+
value, ok := arr.Get(0)
41+
assert.True(t, ok)
42+
assert.Equal(t, 42, value)
43+
}
44+
45+
func TestArrayRemove(t *testing.T) {
46+
arr := NewArray[int](3)
47+
arr.Set(0, 1)
48+
arr.Set(1, 2)
49+
arr.Set(2, 3)
50+
ok := arr.Remove(1)
51+
assert.True(t, ok)
52+
assert.Equal(t, 2, arr.Length())
53+
value, ok := arr.Get(1)
54+
assert.True(t, ok)
55+
assert.Equal(t, 3, value)
56+
}
57+
58+
func TestArrayRemoveInvalidIndex(t *testing.T) {
59+
arr := NewArray[int](1)
60+
ok := arr.Remove(10)
61+
assert.False(t, ok)
62+
}
63+
64+
func TestArrayContains(t *testing.T) {
65+
arr := NewArray[int](3)
66+
arr.Set(0, 1)
67+
arr.Set(1, 2)
68+
arr.Set(2, 3)
69+
assert.True(t, arr.Contains(2))
70+
assert.False(t, arr.Contains(42))
71+
}
72+
73+
func TestArrayClear(t *testing.T) {
74+
arr := NewArray[int](3)
75+
arr.Set(0, 1)
76+
arr.Set(1, 2)
77+
arr.Set(2, 3)
78+
arr.Clear()
79+
assert.Equal(t, 0, arr.Length())
80+
}
81+
82+
func TestArrayInsert(t *testing.T) {
83+
arr := NewArray[int](3)
84+
arr.Set(0, 1)
85+
arr.Set(1, 2)
86+
arr.Set(2, 3)
87+
ok := arr.Insert(1, 42)
88+
assert.True(t, ok)
89+
assert.Equal(t, 4, arr.Length())
90+
value, ok := arr.Get(1)
91+
assert.True(t, ok)
92+
assert.Equal(t, 42, value)
93+
}
94+
95+
func TestArrayInsertInvalidIndex(t *testing.T) {
96+
arr := NewArray[int](1)
97+
ok := arr.Insert(10, 42)
98+
assert.False(t, ok)
99+
}
100+
101+
func TestArrayCopy(t *testing.T) {
102+
arr := NewArray[int](3)
103+
arr.Set(0, 1)
104+
arr.Set(1, 2)
105+
arr.Set(2, 3)
106+
copyArr := arr.Copy()
107+
assert.Equal(t, arr.Length(), copyArr.Length())
108+
for i := 0; i < arr.Length(); i++ {
109+
origValue, _ := arr.Get(i)
110+
copyValue, _ := copyArr.Get(i)
111+
assert.Equal(t, origValue, copyValue)
35112
}
36113
}

go.mod

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@ module github.com/hayageek/threadsafe
22

33
go 1.18
44

5-
require github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
5+
require github.com/stretchr/testify v1.9.0
6+
7+
require (
8+
github.com/davecgh/go-spew v1.1.1 // indirect
9+
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
10+
github.com/pmezard/go-difflib v1.0.0 // indirect
11+
gopkg.in/yaml.v3 v3.0.1 // indirect
12+
)

go.sum

+9
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
24
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
11+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)