From 9c37f53cdcc4790b9afd1ae81c4f7478e8e625a1 Mon Sep 17 00:00:00 2001 From: Kirin <11296899+KirinRyuuri@users.noreply.github.com> Date: Mon, 6 Mar 2023 14:42:50 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Pair=20=E5=92=8C=20Tri?= =?UTF-8?q?ple=20=E4=B8=A4=E7=A7=8D=20Tuple=20=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tuple/pair/example_test.go | 35 ++++ tuple/pair/pair.go | 30 ++++ tuple/triple/example_test.go | 38 +++++ tuple/triple/triple.go | 34 ++++ tuple/tuple.go | 6 + tuple/tuple_test.go | 323 +++++++++++++++++++++++++++++++++++ 6 files changed, 466 insertions(+) create mode 100644 tuple/pair/example_test.go create mode 100644 tuple/pair/pair.go create mode 100644 tuple/triple/example_test.go create mode 100644 tuple/triple/triple.go create mode 100644 tuple/tuple.go create mode 100644 tuple/tuple_test.go diff --git a/tuple/pair/example_test.go b/tuple/pair/example_test.go new file mode 100644 index 00000000..d818d1b1 --- /dev/null +++ b/tuple/pair/example_test.go @@ -0,0 +1,35 @@ +package ekit_test + +import ( + "fmt" + . "github.com/gotomicro/ekit/tuple/pair" +) + +func ExamplePair_Copy() { + pair := Pair{ + First: 1, + Second: "two"} // <1,"two"> + pair = pair.Copy( + Pair{Second: "one"}) + fmt.Println(pair.ToString()) + + // Output: <1,one> +} + +func ExamplePair_ToList() { + pair := Pair{ + First: 1, + Second: "one"} + fmt.Println(pair.ToList()) + + //Output: [1 one] +} + +func ExamplePair_ToString() { + pair := Pair{ + First: 1, + Second: "one"} + fmt.Println(pair.ToString()) + + //Output: <1,one> +} diff --git a/tuple/pair/pair.go b/tuple/pair/pair.go new file mode 100644 index 00000000..abb6beb9 --- /dev/null +++ b/tuple/pair/pair.go @@ -0,0 +1,30 @@ +package ekit + +import "fmt" + +type Pair struct { + First any + Second any +} + +// ToString 将 Pair 转为字符串,格式类似于 +func (p Pair) ToString() string { + return fmt.Sprint("<", p.First, ",", p.Second, ">") +} + +// ToList 将 Pair 转为数组 +func (p Pair) ToList() []any { + return []any{p.First, p.Second} +} + +// Copy 传入一个 Pair 来修改对应位置的值 +func (p Pair) Copy(toPair Pair) (newPair Pair) { + newPair = Pair{First: p.First, Second: p.Second} + if toPair.First != nil { + newPair.First = toPair.First + } + if toPair.Second != nil { + newPair.Second = toPair.Second + } + return +} diff --git a/tuple/triple/example_test.go b/tuple/triple/example_test.go new file mode 100644 index 00000000..74b29e65 --- /dev/null +++ b/tuple/triple/example_test.go @@ -0,0 +1,38 @@ +package ekit_test + +import ( + "fmt" + . "github.com/gotomicro/ekit/tuple/triple" +) + +func ExampleTriple_Copy() { + triple := Triple{ + First: 1, + Second: "one", + Third: "second"} // <1,"one","second"> + + triple = triple.Copy( + Triple{Third: "first"}) + + fmt.Println(triple.ToString()) + + // Output: <1,one,first> +} + +func ExampleTriple_ToList() { + triple := Triple{ + First: 1, + Second: "one"} + fmt.Println(triple.ToList()) + + //Output: [1 one] +} + +func ExampleTriple_ToString() { + triple := Triple{ + First: 1, + Second: "one"} + fmt.Println(triple.ToString()) + + //Output: <1,one> +} diff --git a/tuple/triple/triple.go b/tuple/triple/triple.go new file mode 100644 index 00000000..5e5fc15a --- /dev/null +++ b/tuple/triple/triple.go @@ -0,0 +1,34 @@ +package ekit + +import "fmt" + +type Triple struct { + First any + Second any + Third any +} + +// ToString 将 Triple 转为字符串,格式类似于 +func (t Triple) ToString() string { + return fmt.Sprint("<", t.First, ",", t.Second, ",", t.Third, ">") +} + +// ToList 将 Triple 转为数组 +func (t Triple) ToList() []any { + return []any{t.First, t.Second, t.Third} +} + +// Copy 传入一个 Triple 来修改对应位置的值 +func (t Triple) Copy(toTriple Triple) (newTriple Triple) { + newTriple = Triple{First: t.First, Second: t.Second} + if toTriple.First != nil { + newTriple.First = toTriple.First + } + if toTriple.Second != nil { + newTriple.Second = toTriple.Second + } + if toTriple.Third != nil { + newTriple.Third = toTriple.Third + } + return +} diff --git a/tuple/tuple.go b/tuple/tuple.go new file mode 100644 index 00000000..3388bbed --- /dev/null +++ b/tuple/tuple.go @@ -0,0 +1,6 @@ +package tuple + +type Tuple interface { + ToString() string + ToList() []any +} diff --git a/tuple/tuple_test.go b/tuple/tuple_test.go new file mode 100644 index 00000000..6374f96e --- /dev/null +++ b/tuple/tuple_test.go @@ -0,0 +1,323 @@ +package tuple + +import ( + . "github.com/gotomicro/ekit/tuple/pair" + . "github.com/gotomicro/ekit/tuple/triple" + "github.com/stretchr/testify/assert" + "testing" +) + +// Test_Example 期望的使用方法 +func Test_Example(t *testing.T) { + pair := Pair{First: 1, Second: "one"} + _ = pair.First // 1 + _ = pair.Second // one + _ = pair.ToString() // <1,one> + _ = pair.ToList() // [1,"one"] + pair = pair.Copy(Pair{First: "two"}) // <"two","one"> + pair = pair.Copy(Pair{Second: 2}) // <"two",2> + pair = pair.Copy(Pair{ + First: 2, + Second: "two", + }) // <2,"two"> + + triple := Triple{ + First: 3, + Second: "Three", + Third: true, + } + _ = triple.First // 3 + _ = triple.Second // three + _ = triple.Third // true + _ = triple.ToString() // <3,"three",true> + _ = triple.ToList() // [3,"three", true] + triple = triple.Copy(Triple{First: "four"}) // <"four","three",true> + triple = triple.Copy(Triple{Second: 4}) // <"four",4,true> + triple = triple.Copy(Triple{Third: false}) //<"four",4,false> + triple = triple.Copy(Triple{ + First: 4, + Second: "four", + Third: nil, + }) // <4,"four",false> +} + +// Test_getValue 获取元素 +func Test_getValue(t *testing.T) { + testCases := []struct { + name string + // 用于区分是 Pair(2) 还是 Triple(3) + class int + inputValue Tuple + wantValue1 any + wantValue2 any + wantValue3 any + wantErr error + }{ + { + name: "Pair:nil", + class: 2, + inputValue: Pair{}, + wantValue1: nil, + wantValue2: nil, + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:nil", + class: 3, + inputValue: Triple{}, + wantValue1: nil, + wantValue2: nil, + wantValue3: nil, + wantErr: nil, + }, + { + name: "Pair:bool + int", + class: 2, + inputValue: Pair{ + First: true, + Second: 1, + }, + wantValue1: true, + wantValue2: int(1), + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:bool + int + uint", + class: 3, + inputValue: Triple{ + First: false, + Second: int(0), + Third: uint(2), + }, + wantValue1: false, + wantValue2: int(0), + wantValue3: uint(2), + wantErr: nil, + }, + { + name: "Pair:rune + byte", + class: 2, + inputValue: Pair{ + First: rune('a'), + Second: byte('b'), + }, + wantValue1: rune('a'), + wantValue2: byte('b'), + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:rune + byte + string", + class: 3, + inputValue: Triple{ + First: rune('c'), + Second: byte('d'), + Third: string("efg"), + }, + wantValue1: rune('c'), + wantValue2: byte('d'), + wantValue3: string("efg"), + wantErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + switch tc.class { + case 2: + assert.Equal(t, tc.wantValue1, tc.inputValue.(Pair).First) + assert.Equal(t, tc.wantValue2, tc.inputValue.(Pair).Second) + case 3: + assert.Equal(t, tc.wantValue1, tc.inputValue.(Triple).First) + assert.Equal(t, tc.wantValue2, tc.inputValue.(Triple).Second) + assert.Equal(t, tc.wantValue3, tc.inputValue.(Triple).Third) + default: + } + }) + } +} + +// Test_changeValue 改变内部值,只能从 非nil 变成 nil,不能从 nil 变成 非nil +func Test_changeValue(t *testing.T) { + runes := []rune{'a', 'b', 'c'} + bytes := []byte{'d', 'e', 'f'} + testCases := []struct { + name string + // 用于区分是 Pair(2) 还是 Triple(3) + class int + inputValue Tuple + changeValue Tuple + wantValue1 any + wantValue2 any + wantValue3 any + wantErr error + }{ + { + name: "Pair:nil -> all filed", + class: 2, + inputValue: Pair{}, + changeValue: Pair{ + First: 0, + Second: "zero", + }, + wantValue1: 0, + wantValue2: "zero", + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:nil -> all filed", + class: 3, + inputValue: Triple{}, + changeValue: Triple{ + First: 3, + Second: "three", + Third: true, + }, + wantValue1: 3, + wantValue2: "three", + wantValue3: true, + wantErr: nil, + }, + { + name: "Pair:bool + int -> the same type", + class: 2, + inputValue: Pair{ + First: true, + Second: 1, + }, + changeValue: Pair{First: false}, + wantValue1: false, + wantValue2: int(1), + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:bool + int + uint -> the same type", + class: 3, + inputValue: Triple{ + First: false, + Second: int(0), + Third: uint(2), + }, + changeValue: Triple{ + Third: uint(20)}, + wantValue1: false, + wantValue2: int(0), + wantValue3: uint(20), + wantErr: nil, + }, + { + name: "Pair:rune + byte -> different type", + class: 2, + inputValue: Pair{ + First: rune('a'), + Second: byte('b'), + }, + changeValue: Pair{ + First: float32(3.14), + Second: complex64(314), + }, + wantValue1: float32(3.14), + wantValue2: complex64(314), + wantValue3: nil, + wantErr: nil, + }, + { + name: "Triple:rune + byte + string -> different type", + class: 3, + inputValue: Triple{ + First: rune('c'), + Second: byte('d'), + Third: string("efg"), + }, + changeValue: Triple{ + First: uintptr(0x9876543210), + Second: runes, + Third: bytes, + }, + wantValue1: uintptr(0x9876543210), + wantValue2: runes, + wantValue3: bytes, + wantErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + switch tc.class { + case 2: + output := tc.inputValue.(Pair).Copy(tc.changeValue.(Pair)) + assert.Equal(t, tc.wantValue1, output.First) + assert.Equal(t, tc.wantValue2, output.Second) + case 3: + output := tc.inputValue.(Triple).Copy(tc.changeValue.(Triple)) + assert.Equal(t, tc.wantValue1, output.First) + assert.Equal(t, tc.wantValue2, output.Second) + assert.Equal(t, tc.wantValue3, output.Third) + default: + } + }) + } +} + +// Test_TransInChan 尝试通过一组 chan 来传输 +func Test_TransInChan(t *testing.T) { + ch := make(chan Tuple, 1) + testCases := []struct { + name string + input Tuple + want Tuple + wantErr error + }{ + { + name: "pair + nil", + input: Pair{}, + want: Pair{}, + wantErr: nil, + }, + { + name: "triple + nil", + input: Triple{}, + want: Triple{}, + wantErr: nil, + }, + { + name: "pair", + input: Pair{ + First: 0, + Second: "zero", + }, + want: Pair{ + First: 0, + Second: "zero", + }, + wantErr: nil, + }, + { + name: "triple", + input: Triple{ + First: 1, + Second: "one", + Third: "first", + }, + want: Triple{ + First: 1, + Second: "one", + Third: "first", + }, + wantErr: nil, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + go func() { + ch <- tc.input + }() + v := <-ch + assert.Equal(t, tc.want, v) + }) + } +} From 15146a80e9850bd388a3f8f6a459401803395610 Mon Sep 17 00:00:00 2001 From: Kirin <11296899+KirinRyuuri@users.noreply.github.com> Date: Mon, 6 Mar 2023 15:12:53 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=20-=20=E5=A2=9E=E5=8A=A0=20Copyright=20=20?= =?UTF-8?q?-=20=E4=BF=AE=E6=94=B9=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .CHANGELOG.md | 1 + tuple/pair/example_test.go | 14 ++++++++++++++ tuple/pair/pair.go | 14 ++++++++++++++ tuple/triple/example_test.go | 14 ++++++++++++++ tuple/triple/triple.go | 14 ++++++++++++++ tuple/tuple.go | 14 ++++++++++++++ tuple/tuple_test.go | 14 ++++++++++++++ 7 files changed, 85 insertions(+) diff --git a/.CHANGELOG.md b/.CHANGELOG.md index 997a926a..664ec5ef 100644 --- a/.CHANGELOG.md +++ b/.CHANGELOG.md @@ -3,6 +3,7 @@ - [reflectx: IsNil 方法](https://github.com/gotomicro/ekit/pull/150) - [setx: Set接口设计和基于map的实现](https://github.com/gotomicro/ekit/pull/148) - [setx: TreeSet基于TreeMap实现](https://github.com/gotomicro/ekit/issues/147) +- [tuple: 增加 Pair 和 Triple 两种](https://github.com/ecodeclub/ekit/issues/161) # v0.0.6 - [queue: 基于semaphore的并发阻塞队列实现](https://github.com/gotomicro/ekit/pull/129) diff --git a/tuple/pair/example_test.go b/tuple/pair/example_test.go index d818d1b1..e7c33061 100644 --- a/tuple/pair/example_test.go +++ b/tuple/pair/example_test.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ekit_test import ( diff --git a/tuple/pair/pair.go b/tuple/pair/pair.go index abb6beb9..55ef6fb3 100644 --- a/tuple/pair/pair.go +++ b/tuple/pair/pair.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ekit import "fmt" diff --git a/tuple/triple/example_test.go b/tuple/triple/example_test.go index 74b29e65..18b1c8c6 100644 --- a/tuple/triple/example_test.go +++ b/tuple/triple/example_test.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ekit_test import ( diff --git a/tuple/triple/triple.go b/tuple/triple/triple.go index 5e5fc15a..00301783 100644 --- a/tuple/triple/triple.go +++ b/tuple/triple/triple.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ekit import "fmt" diff --git a/tuple/tuple.go b/tuple/tuple.go index 3388bbed..bbef7bc0 100644 --- a/tuple/tuple.go +++ b/tuple/tuple.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package tuple type Tuple interface { diff --git a/tuple/tuple_test.go b/tuple/tuple_test.go index 6374f96e..e30514f3 100644 --- a/tuple/tuple_test.go +++ b/tuple/tuple_test.go @@ -1,3 +1,17 @@ +// Copyright 2021 ecodeclub +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package tuple import ( From fa2a8e1da1c6c339f5fd68e4a7b592c85a2270f4 Mon Sep 17 00:00:00 2001 From: Kirin <11296899+KirinRyuuri@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:58:27 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=8C=85=E5=90=8D=20ekit?= =?UTF-8?q?=20->=20pair|triple?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tuple/pair/example_test.go | 2 +- tuple/pair/pair.go | 2 +- tuple/triple/example_test.go | 2 +- tuple/triple/triple.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tuple/pair/example_test.go b/tuple/pair/example_test.go index e7c33061..61afd4cd 100644 --- a/tuple/pair/example_test.go +++ b/tuple/pair/example_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ekit_test +package pair_test import ( "fmt" diff --git a/tuple/pair/pair.go b/tuple/pair/pair.go index 55ef6fb3..4c46fc13 100644 --- a/tuple/pair/pair.go +++ b/tuple/pair/pair.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ekit +package pair import "fmt" diff --git a/tuple/triple/example_test.go b/tuple/triple/example_test.go index 18b1c8c6..a4ed54fb 100644 --- a/tuple/triple/example_test.go +++ b/tuple/triple/example_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ekit_test +package triple_test import ( "fmt" diff --git a/tuple/triple/triple.go b/tuple/triple/triple.go index 00301783..0c8a0a2e 100644 --- a/tuple/triple/triple.go +++ b/tuple/triple/triple.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ekit +package triple import "fmt"