diff --git a/.gitignore b/.gitignore index 5e56e040..769c4893 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ /bin + +.DS_Store +.env +.envrc +.idea/ +.vscode/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 7b847717..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at oss-conduct@uber.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/README.md b/README.md index 125755ab..1996e6d5 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,10 @@ -This repository holds the [Uber Go Style Guide](style.md), which documents -patterns and conventions used in Go code at Uber. +This repository holds the [Velmie Go Style Guide](style.md), which documents +patterns and conventions used in Go code at Velmie. ## Style Guide -See [Uber Go Style Guide](style.md) for the style guide. +See [Velmie Go Style Guide](style.md) for the style guide. -## Translations +## Contributing -We are aware of the following translations of this guide by the Go community. - -- **中文翻译** (Chinese): [xxjwxc/uber_go_guide_cn](https://github.com/xxjwxc/uber_go_guide_cn) -- **繁體中文** (Traditional Chinese):[ianchen0119/uber_go_guide_tw](https://github.com/ianchen0119/uber_go_guide_tw) -- **한국어 번역** (Korean): [TangoEnSkai/uber-go-style-guide-kr](https://github.com/TangoEnSkai/uber-go-style-guide-kr) -- **日本語訳** (Japanese): [knsh14/uber-style-guide-ja](https://github.com/knsh14/uber-style-guide-ja) -- **Traducción al Español** (Spanish): [friendsofgo/uber-go-guide-es](https://github.com/friendsofgo/uber-go-guide-es) -- **แปลภาษาไทย** (Thai): [pallat/uber-go-style-guide-th](https://github.com/pallat/uber-go-style-guide-th) -- **Tradução em português** (Portuguese): [lucassscaravelli/uber-go-guide-pt](https://github.com/lucassscaravelli/uber-go-guide-pt) -- **Tradução em português** (Portuguese BR): [alcir-junior-caju/uber-go-style-guide-pt-br](https://github.com/alcir-junior-caju/uber-go-style-guide-pt-br) -- **Tłumaczenie polskie** (Polish): [DamianSkrzypczak/uber-go-guide-pl](https://github.com/DamianSkrzypczak/uber-go-guide-pl) -- **Русский перевод** (Russian): [sau00/uber-go-guide-ru](https://github.com/sau00/uber-go-guide-ru) -- **Français** (French): [rm3l/uber-go-style-guide-fr](https://github.com/rm3l/uber-go-style-guide-fr) -- **Türkçe** (Turkish): [ksckaan1/uber-go-style-guide-tr](https://github.com/ksckaan1/uber-go-style-guide-tr) -- **Український переклад** (Ukrainian): [vorobeyme/uber-go-style-guide-uk](https://github.com/vorobeyme/uber-go-style-guide-uk) -- **ترجمه فارسی** (Persian): [jamalkaksouri/uber-go-guide-ir](https://github.com/jamalkaksouri/uber-go-guide-ir) -- **Tiếng việt** (Vietnamese): [nc-minh/uber-go-guide-vi](https://github.com/nc-minh/uber-go-guide-vi) - -If you have a translation, feel free to submit a PR adding it to the list. +Make changes according to the [guide](CONTRIBUTING.md) and makes a pull-request. The CI generates the result `style.md` file. diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6ea20440..2629eb1c 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -1,4 +1,4 @@ -# Uber Go Style Guide +# Go Style Guide - [Introduction](intro.md) - Guidelines @@ -10,6 +10,7 @@ - [Defer to Clean Up](defer-clean.md) - [Channel Size is One or None](channel-size.md) - [Start Enums at One](enum-start.md) + - [String() for enums](enum-string.md) - [Use `"time"` to handle time](time.md) - Errors - [Error Types](error-type.md) @@ -63,4 +64,3 @@ - Patterns - [Test Tables](test-table.md) - [Functional Options](functional-option.md) -- [Linting](lint.md) diff --git a/src/container-copy.md b/src/container-copy.md index ada04893..927d5f6a 100644 --- a/src/container-copy.md +++ b/src/container-copy.md @@ -103,4 +103,31 @@ snapshot := stats.Snapshot() +## Always return a slice if a function modifies one + + + + + + + + + +
Bad Good
+ +```go +func Add(trips []int) { + trips = append(trips, 1) +} +``` + + + +```go +func Add(trips []int) []int { + return append(trips, 1) +} +``` + +
diff --git a/src/enum-start.md b/src/enum-start.md index ec46602b..778d5902 100644 --- a/src/enum-start.md +++ b/src/enum-start.md @@ -41,6 +41,8 @@ const ( There are cases where using the zero value makes sense, for example when the zero value case is the desirable default behavior. +Example 1: + ```go type LogOutput int @@ -53,4 +55,23 @@ const ( // LogToStdout=0, LogToFile=1, LogToRemote=2 ``` - +Example 2: + +```go +type CardType int + +const ( + CardType_UNDEFINED CardType = iota + CardType_PLASTIC + CardType_VIRTUAL +) + +// CardType_UNDEFINED=0, CardType_PLASTIC=1, CardType_VIRTUAL=2 +``` + +--- +**NOTE** + +You also can use the package . + +--- diff --git a/src/enum-string.md b/src/enum-string.md new file mode 100644 index 00000000..c446c53b --- /dev/null +++ b/src/enum-string.md @@ -0,0 +1,32 @@ +# String() for enums + +Prefer to implement the `String()` method for custom enum types. + +```go +type CardType int + +const ( + CardType_UNDEFINED CardType = iota + CardType_PLASTIC + CardType_VIRTUAL +) + +func (s CardType) String() string { + switch s { + case CardType_PLASTIC: + return "plastic" + case CardType_VIRTUAL: + return "virtual" + } + + return "undefined" +} + +``` + +--- +**NOTE** + +You also can use the package . + +--- diff --git a/src/import-group.md b/src/import-group.md index 384c8acc..65bec4b9 100644 --- a/src/import-group.md +++ b/src/import-group.md @@ -2,8 +2,9 @@ There should be two import groups: -- Standard library -- Everything else +- Standard(builtin) library +- External packages +- Internal packages This is the grouping applied by goimports by default. @@ -18,6 +19,7 @@ import ( "os" "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "your-project/internal/package" ) ``` @@ -30,6 +32,8 @@ import ( "go.uber.org/atomic" "golang.org/x/sync/errgroup" + + "your-project/internal/package" ) ``` diff --git a/src/intro.md b/src/intro.md index e50dacf3..29235feb 100644 --- a/src/intro.md +++ b/src/intro.md @@ -5,33 +5,6 @@ misnomer, since these conventions cover far more than just source file formatting—gofmt handles that for us. The goal of this guide is to manage this complexity by describing in detail the -Dos and Don'ts of writing Go code at Uber. These rules exist to keep the code +Dos and Don'ts of writing Go code. These rules exist to keep the code base manageable while still allowing engineers to use Go language features productively. - -This guide was originally created by [Prashant Varanasi] and [Simon Newton] as -a way to bring some colleagues up to speed with using Go. Over the years it has -been amended based on feedback from others. - - [Prashant Varanasi]: https://github.com/prashantv - [Simon Newton]: https://github.com/nomis52 - -This documents idiomatic conventions in Go code that we follow at Uber. A lot -of these are general guidelines for Go, while others extend upon external -resources: - -1. [Effective Go](https://go.dev/doc/effective_go) -2. [Go Common Mistakes](https://go.dev/wiki/CommonMistakes) -3. [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments) - -We aim for the code samples to be accurate for the two most recent minor versions -of Go [releases](https://go.dev/doc/devel/release). - -All code should be error-free when run through `golint` and `go vet`. We -recommend setting up your editor to: - -- Run `goimports` on save -- Run `golint` and `go vet` to check for errors - -You can find information in editor support for Go tools here: - diff --git a/src/lint.md b/src/lint.md deleted file mode 100644 index 03d83010..00000000 --- a/src/lint.md +++ /dev/null @@ -1,35 +0,0 @@ -# Linting - -More importantly than any "blessed" set of linters, lint consistently across a -codebase. - -We recommend using the following linters at a minimum, because we feel that they -help to catch the most common issues and also establish a high bar for code -quality without being unnecessarily prescriptive: - -- [errcheck] to ensure that errors are handled -- [goimports] to format code and manage imports -- [golint] to point out common style mistakes -- [govet] to analyze code for common mistakes -- [staticcheck] to do various static analysis checks - - [errcheck]: https://github.com/kisielk/errcheck - [goimports]: https://pkg.go.dev/golang.org/x/tools/cmd/goimports - [golint]: https://github.com/golang/lint - [govet]: https://pkg.go.dev/cmd/vet - [staticcheck]: https://staticcheck.dev - -## Lint Runners - -We recommend [golangci-lint] as the go-to lint runner for Go code, largely due -to its performance in larger codebases and ability to configure and use many -canonical linters at once. This repo has an example [.golangci.yml] config file -with recommended linters and settings. - -golangci-lint has [various linters] available for use. The above linters are -recommended as a base set, and we encourage teams to add any additional linters -that make sense for their projects. - - [golangci-lint]: https://github.com/golangci/golangci-lint - [.golangci.yml]: https://github.com/uber-go/guide/blob/master/.golangci.yml - [various linters]: https://golangci-lint.run/usage/linters/ diff --git a/src/performance.md b/src/performance.md index 88edb7e3..6babb314 100644 --- a/src/performance.md +++ b/src/performance.md @@ -1,3 +1 @@ # Performance - -Performance-specific guidelines apply only to the hot path. diff --git a/src/struct-field-key.md b/src/struct-field-key.md index f08b0775..6bdf09f1 100644 --- a/src/struct-field-key.md +++ b/src/struct-field-key.md @@ -27,7 +27,7 @@ k := User{ -Exception: Field names *may* be omitted in test tables when there are 3 or +Exception #1: Field names *may* be omitted in test tables when there are 3 or fewer fields. ```go @@ -39,3 +39,45 @@ tests := []struct{ {Subtract, "subtract"}, } ``` + +Exception #2: Field names *should* be omitted in function-constructor + + + + + +
BadGood
+ +```go + +type Consumer struct { + logger string + svc string +} + +func NewConsumer(logger string, svc string) *Consumer { + return &Consumer{ + logger: logger, + svc: svc, + } +} + +``` + + + +```go +type Consumer struct { + logger string + svc string +} + +func NewConsumer(logger string, svc string) *Consumer { + return &Consumer{ + logger, + svc, + } +} +``` + +
diff --git a/style.md b/style.md index bf0d20bb..3774b31c 100644 --- a/style.md +++ b/style.md @@ -5,7 +5,7 @@ -# Uber Go Style Guide +# Go Style Guide - [Introduction](#introduction) - [Guidelines](#guidelines) @@ -17,6 +17,7 @@ - [Defer to Clean Up](#defer-to-clean-up) - [Channel Size is One or None](#channel-size-is-one-or-none) - [Start Enums at One](#start-enums-at-one) + - [String() for enums](#string-for-enums) - [Use `"time"` to handle time](#use-time-to-handle-time) - [Errors](#errors) - [Error Types](#error-types) @@ -70,7 +71,6 @@ - [Patterns](#patterns) - [Test Tables](#test-tables) - [Functional Options](#functional-options) -- [Linting](#linting) ## Introduction @@ -79,34 +79,10 @@ misnomer, since these conventions cover far more than just source file formatting—gofmt handles that for us. The goal of this guide is to manage this complexity by describing in detail the -Dos and Don'ts of writing Go code at Uber. These rules exist to keep the code +Dos and Don'ts of writing Go code. These rules exist to keep the code base manageable while still allowing engineers to use Go language features productively. -This guide was originally created by [Prashant Varanasi](https://github.com/prashantv) and [Simon Newton](https://github.com/nomis52) as -a way to bring some colleagues up to speed with using Go. Over the years it has -been amended based on feedback from others. - -This documents idiomatic conventions in Go code that we follow at Uber. A lot -of these are general guidelines for Go, while others extend upon external -resources: - -1. [Effective Go](https://go.dev/doc/effective_go) -2. [Go Common Mistakes](https://go.dev/wiki/CommonMistakes) -3. [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments) - -We aim for the code samples to be accurate for the two most recent minor versions -of Go [releases](https://go.dev/doc/devel/release). - -All code should be error-free when run through `golint` and `go vet`. We -recommend setting up your editor to: - -- Run `goimports` on save -- Run `golint` and `go vet` to check for errors - -You can find information in editor support for Go tools here: -https://go.dev/wiki/IDEsAndTextEditorPlugins - ## Guidelines ### Pointers to Interfaces @@ -469,6 +445,35 @@ snapshot := stats.Snapshot() +#### Always return a slice if a function modifies one + + + + + + + + + + +
Bad Good
+ +```go +func Add(trips []int) { + trips = append(trips, 1) +} +``` + + + +```go +func Add(trips []int) []int { + return append(trips, 1) +} +``` + +
+ ### Defer to Clean Up Use defer to clean up resources such as files and locks. @@ -592,6 +597,8 @@ const ( There are cases where using the zero value makes sense, for example when the zero value case is the desirable default behavior. +Example 1: + ```go type LogOutput int @@ -604,7 +611,61 @@ const ( // LogToStdout=0, LogToFile=1, LogToRemote=2 ``` - +Example 2: + +```go +type CardType int + +const ( + CardType_UNDEFINED CardType = iota + CardType_PLASTIC + CardType_VIRTUAL +) + +// CardType_UNDEFINED=0, CardType_PLASTIC=1, CardType_VIRTUAL=2 +``` + +--- + +**NOTE** + +You also can use the package https://github.com/abice/go-enum. + +--- + +### String() for enums + +Prefer to implement the `String()` method for custom enum types. + +```go +type CardType int + +const ( + CardType_UNDEFINED CardType = iota + CardType_PLASTIC + CardType_VIRTUAL +) + +func (s CardType) String() string { + switch s { + case CardType_PLASTIC: + return "plastic" + case CardType_VIRTUAL: + return "virtual" + } + + return "undefined" +} + +``` + +--- + +**NOTE** + +You also can use the package https://github.com/abice/go-enum. + +--- ### Use `"time"` to handle time @@ -2150,8 +2211,6 @@ See [Wait for goroutines to exit](#wait-for-goroutines-to-exit). ## Performance -Performance-specific guidelines apply only to the hot path. - ### Prefer strconv over fmt When converting primitives to/from strings, `strconv` is faster than @@ -2568,8 +2627,9 @@ func (c *client) request() { There should be two import groups: -- Standard library -- Everything else +- Standard(builtin) library +- External packages +- Internal packages This is the grouping applied by goimports by default. @@ -2584,6 +2644,7 @@ import ( "os" "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "your-project/internal/package" ) ``` @@ -2596,6 +2657,8 @@ import ( "go.uber.org/atomic" "golang.org/x/sync/errgroup" + + "your-project/internal/package" ) ``` @@ -3413,7 +3476,7 @@ k := User{ -Exception: Field names *may* be omitted in test tables when there are 3 or +Exception #1: Field names *may* be omitted in test tables when there are 3 or fewer fields. ```go @@ -3426,6 +3489,48 @@ tests := []struct{ } ``` +Exception #2: Field names *should* be omitted in function-constructor + + + + + +
BadGood
+ +```go + +type Consumer struct { + logger string + svc string +} + +func NewConsumer(logger string, svc string) *Consumer { + return &Consumer{ + logger: logger, + svc: svc, + } +} + +``` + + + +```go +type Consumer struct { + logger string + svc string +} + +func NewConsumer(logger string, svc string) *Consumer { + return &Consumer{ + logger, + svc, + } +} +``` + +
+ #### Omit Zero Value Fields in Structs When initializing structs with field names, omit fields that have zero values @@ -4081,29 +4186,3 @@ See also, - -## Linting - -More importantly than any "blessed" set of linters, lint consistently across a -codebase. - -We recommend using the following linters at a minimum, because we feel that they -help to catch the most common issues and also establish a high bar for code -quality without being unnecessarily prescriptive: - -- [errcheck](https://github.com/kisielk/errcheck) to ensure that errors are handled -- [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) to format code and manage imports -- [golint](https://github.com/golang/lint) to point out common style mistakes -- [govet](https://pkg.go.dev/cmd/vet) to analyze code for common mistakes -- [staticcheck](https://staticcheck.dev) to do various static analysis checks - -### Lint Runners - -We recommend [golangci-lint](https://github.com/golangci/golangci-lint) as the go-to lint runner for Go code, largely due -to its performance in larger codebases and ability to configure and use many -canonical linters at once. This repo has an example [.golangci.yml](https://github.com/uber-go/guide/blob/master/.golangci.yml) config file -with recommended linters and settings. - -golangci-lint has [various linters](https://golangci-lint.run/usage/linters/) available for use. The above linters are -recommended as a base set, and we encourage teams to add any additional linters -that make sense for their projects.