Skip to content

Commit 36e5c29

Browse files
committed
feat: bring rust type to go
0 parents  commit 36e5c29

File tree

9 files changed

+898
-0
lines changed

9 files changed

+898
-0
lines changed

.github/workflows/matrix-test.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Matrix Test
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- master
9+
- dev
10+
11+
concurrency:
12+
group: ${{ github.sha }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-latest
18+
name: Golang ${{ matrix.go }}
19+
strategy:
20+
matrix:
21+
go:
22+
- "1.25"
23+
- "1.18"
24+
25+
steps:
26+
- uses: actions/checkout@v5
27+
- name: Set up Golang
28+
uses: actions/setup-go@v5
29+
with:
30+
go-version: ${{ matrix.go }}
31+
- name: Test option
32+
run: cd option && go test -v
33+
- name: Test result
34+
run: cd result && go test -v

.gitignore

Whitespace-only changes.

LICENSE

Lines changed: 373 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# type
2+
3+
Bring the Rust [Result Option] type to Golang
4+
5+
## Installation
6+
7+
`go get github.com/initdc/type`
8+
9+
## Usage
10+
11+
```go
12+
import (
13+
. "github.com/initdc/type/option"
14+
. "github.com/initdc/type/result"
15+
)
16+
17+
// Option
18+
s := Some(1)
19+
20+
var s Option[int]
21+
s.None()
22+
23+
n := None[int]()
24+
25+
// Result
26+
var r Result[int, string]
27+
r.Ok(1)
28+
29+
var e Result[int, string]
30+
e.Err("error")
31+
32+
33+
r := Ok[int, string](1)
34+
e := Err[int, string]("error")
35+
```
36+
37+
## Contributing
38+
39+
Bug reports and pull requests are welcome on GitHub at https://github.com/initdc/type.

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/initdc/type
2+
3+
go 1.18

option/option.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package option
2+
3+
type Option[T any] struct {
4+
value T `json:"value"`
5+
some bool `json:"some"`
6+
assigned bool `json:"assigned"`
7+
}
8+
9+
func Some[T any](v T) Option[T] {
10+
return Option[T]{
11+
value: v,
12+
some: true,
13+
assigned: true,
14+
}
15+
}
16+
17+
func None[T any]() Option[T] {
18+
return Option[T]{
19+
some: false,
20+
assigned: true,
21+
}
22+
}
23+
24+
func (o *Option[T]) Some(v T) {
25+
if o.assigned {
26+
panic("Option already assigned")
27+
}
28+
o.value = v
29+
o.some = true
30+
o.assigned = true
31+
}
32+
33+
func (o *Option[T]) None() {
34+
if o.assigned {
35+
panic("Option already assigned")
36+
}
37+
o.some = false
38+
o.assigned = true
39+
}
40+
41+
func (o *Option[T]) IsSome() bool {
42+
return o.some
43+
}
44+
45+
func (o *Option[T]) IsSomeAnd(f func(T) bool) bool {
46+
if !o.some {
47+
return false
48+
}
49+
return f(o.value)
50+
}
51+
52+
func (o *Option[T]) IsNone() bool {
53+
return !o.some
54+
}
55+
56+
func (o *Option[T]) IsNoneOr(f func(T) bool) bool {
57+
if !o.some {
58+
return true
59+
}
60+
return f(o.value)
61+
}
62+
63+
func (o *Option[T]) Expect(msg string) T {
64+
if o.some {
65+
return o.value
66+
}
67+
panic(msg)
68+
}
69+
70+
func (o *Option[T]) Unwrap() T {
71+
if o.some {
72+
return o.value
73+
}
74+
panic("called Option.Unwrap() on a None value")
75+
}
76+
77+
func (o *Option[T]) UnwrapOr(def T) T {
78+
if o.some {
79+
return o.value
80+
}
81+
return def
82+
}
83+
84+
func (o *Option[T]) UnwrapOrElse(f func() T) T {
85+
if o.some {
86+
return o.value
87+
}
88+
return f()
89+
}
90+
91+
func (o *Option[T]) UnwrapOrDefault() T {
92+
if o.some {
93+
return o.value
94+
}
95+
var zero T
96+
return zero
97+
}

option/option_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package option
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestIsSome(t *testing.T) {
8+
s := Some(1)
9+
if s.IsSome() == false {
10+
t.Error("TestIsSome case 1 failed")
11+
}
12+
13+
n := None[int]()
14+
if n.IsSome() == true {
15+
t.Error("TestIsSome case 2 failed")
16+
}
17+
}
18+
19+
func TestIsNone(t *testing.T) {
20+
var s Option[int]
21+
s.Some(1)
22+
if s.IsNone() == true {
23+
t.Error("TestIsNone case 1 failed")
24+
}
25+
26+
var n Option[int]
27+
n.None()
28+
if n.IsNone() == false {
29+
t.Error("TestIsNone case 2 failed")
30+
}
31+
}
32+
33+
func TestIsSomeAnd(t *testing.T) {
34+
s := Some(1)
35+
if s.IsSomeAnd(func(int) bool { return true }) == false {
36+
t.Error("TestIsSomeAnd case 1 failed")
37+
}
38+
39+
n := None[int]()
40+
if n.IsSomeAnd(func(int) bool { return true }) == true {
41+
t.Error("TestIsSomeAnd case 2 failed")
42+
}
43+
}
44+
45+
func TestIsNoneOr(t *testing.T) {
46+
s := Some(1)
47+
if s.IsNoneOr(func(int) bool { return false }) == true {
48+
t.Error("TestIsNoneOr case 1 failed")
49+
}
50+
51+
n := None[int]()
52+
if n.IsNoneOr(func(int) bool { return false }) == false {
53+
t.Error("TestIsNoneOr case 2 failed")
54+
}
55+
}
56+
57+
func TestUnwrap(t *testing.T) {
58+
s := Some(1)
59+
if s.Unwrap() != 1 {
60+
t.Error("TestUnwrap case 1 failed")
61+
}
62+
63+
n := None[int]()
64+
if n.UnwrapOr(99) != 99 {
65+
t.Error("TestUnwrap case 2 failed")
66+
}
67+
}
68+
69+
func TestUnwrapOrElse(t *testing.T) {
70+
s := Some(1)
71+
if s.UnwrapOrElse(func() int { return 99 }) != 1 {
72+
t.Error("TestUnwrapOrElse case 1 failed")
73+
}
74+
75+
n := None[int]()
76+
if n.UnwrapOrElse(func() int { return 99 }) != 99 {
77+
t.Error("TestUnwrapOrElse case 2 failed")
78+
}
79+
}
80+
81+
func TestUnwrapOrDefault(t *testing.T) {
82+
s := Some(1)
83+
if s.UnwrapOrDefault() != 1 {
84+
t.Error("TestUnwrapOrDefault case 1 failed")
85+
}
86+
87+
n := None[int]()
88+
if n.UnwrapOrDefault() != 0 {
89+
t.Error("TestUnwrapOrDefault case 2 failed")
90+
}
91+
}

0 commit comments

Comments
 (0)