Skip to content

Commit c0937dd

Browse files
committed
Add functional options idiom
1 parent abcdf32 commit c0937dd

File tree

3 files changed

+91
-66
lines changed

3 files changed

+91
-66
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ __Idioms__:
104104

105105
| Pattern | Description |
106106
|:-------:| ----------- |
107-
| [Functional Options](functional_options.go) | Allows creating clean APIs with sane defaults and idiomatic overrides |
107+
| [Functional Options](idiom/functional_options.md) | Allows creating clean APIs with sane defaults and idiomatic overrides |
108108

109109
__Anti-Patterns__:
110110

functional_options.go

Lines changed: 0 additions & 65 deletions
This file was deleted.

idiom/functional_options.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Functional Options
2+
Functional options are a method of implementing clean/eloquent APIs in Go.
3+
Options implemented as a function set the state of that option.
4+
5+
## Implementation
6+
7+
### Options
8+
```go
9+
package file
10+
11+
type Options struct {
12+
UID int
13+
GID int
14+
Flags int
15+
Contents string
16+
Permissions os.FileMode
17+
}
18+
19+
type Option func(*Options)
20+
21+
func UID(userID int) Option {
22+
return func(args *Options) {
23+
args.UID = userID
24+
}
25+
}
26+
27+
func GID(groupID int) Option {
28+
return func(args *Options) {
29+
args.GID = groupID
30+
}
31+
}
32+
33+
func Contents(c string) Option {
34+
return func(args *Options) {
35+
args.Contents = c
36+
}
37+
}
38+
39+
func Permissions(perms os.FileMode) Option {
40+
return func(args *Options) {
41+
args.Permissions = perms
42+
}
43+
}
44+
```
45+
46+
### Constructor
47+
```go
48+
package file
49+
50+
func New(filepath string, setters ...Option) error {
51+
// Default Options
52+
args := &Options{
53+
UID: os.Getuid(),
54+
GID: os.Getgid(),
55+
Contents: "",
56+
Permissions: 0666,
57+
Flags: os.O_CREATE | os.O_EXCL | os.O_WRONLY,
58+
}
59+
60+
for _, setter := range setters {
61+
setter(args)
62+
}
63+
64+
f, err := os.OpenFile(filepath, args.Flags, args.Permissions)
65+
if err != nil {
66+
return err
67+
} else {
68+
defer f.Close()
69+
}
70+
71+
if _, err := f.WriteString(args.Contents); err != nil {
72+
return err
73+
}
74+
75+
return f.Chown(args.UID, args.GID)
76+
}
77+
```
78+
79+
## Usage
80+
```go
81+
emptyFile, err := file.New("/tmp/empty.txt")
82+
if err != nil {
83+
panic(err)
84+
}
85+
86+
fillerFile, err := file.New("/tmp/file.txt", file.UID(1000), file.Contents("Lorem Ipsum Dolor Amet"))
87+
if err != nil {
88+
panic(err)
89+
}
90+
```

0 commit comments

Comments
 (0)