diff --git a/README.md b/README.md index 7d9f5f7..e22cd19 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ A curated collection of idiomatic design & application patterns for Go language. | Pattern | Description | Status | |:-------:|:----------- |:------:| +| [Empty Struct](/idiom/empty-struct.md) | Uses a struct with no fields to clarify intent and reduce memory usage | ✔ | | [Functional Options](/idiom/functional-options.md) | Allows creating clean APIs with sane defaults and idiomatic overrides | ✔ | ## Anti-Patterns diff --git a/idiom/empty-struct.md b/idiom/empty-struct.md new file mode 100644 index 0000000..5ca571e --- /dev/null +++ b/idiom/empty-struct.md @@ -0,0 +1,84 @@ +# Empty Struct +The empty struct is a struct type with no fields. +It has a couple of interesting properties. + +- Its size is zero bytes, so values of this type occupy no storage +- It is often used when no data needs to be stored, but the type itself conveys intent + +## Implementation +### Zero Size +```go +package main + +import ( + "fmt" + "unsafe" +) + +var i int16 +var c complex128 +var s struct{} + +func main() { + fmt.Println(unsafe.Sizeof(i)) // 2 bytes + fmt.Println(unsafe.Sizeof(c)) // 16 bytes + fmt.Println(unsafe.Sizeof(s)) // 0 bytes +} +``` + + +### Signal-only Channel +```go +package main + +func main() { + done := make(chan struct{}) + + go func() { + // do work... + close(done) + }() + + <-done +} +``` + +### Set +```go +type S map[string]struct{} + +func (s S) Add(key string) { + s[key] = struct{}{} +} + +func (s S) Has(key string) bool { + _, ok := s[key] + return ok +} +``` + +## Usage +### Signal-only Channel +```go +done := make(chan struct{}) + +go func() { + close(done) +}() + +<-done // blocks until goroutine signals completion +``` + +### Set +```go +s := make(S) +s.Add("go") +s.Add("patterns") + +fmt.Println(s.Has("go")) // true +fmt.Println(s.Has("rust")) // false +``` + +## Rules of Thumb +- Prefer `chan struct{}` over `chan bool` when no data needs to be sent +- Prefer `map[K]struct{}` over `map[K]bool` when implementing a set