github.com/Team-Kujira/tendermint@v0.34.24-indexer/STYLE_GUIDE.md (about)

     1  # Go Coding Style Guide
     2  
     3  In order to keep our code looking good with lots of programmers working on it, it helps to have a "style guide", so all
     4  the code generally looks quite similar. This doesn't mean there is only one "right way" to write code, or even that this
     5  standard is better than your style.  But if we agree to a number of stylistic practices, it makes it much easier to read
     6  and modify new code. Please feel free to make suggestions if there's something you would like to add or modify.
     7  
     8  We expect all contributors to be familiar with [Effective Go](https://golang.org/doc/effective_go.html)
     9  (and it's recommended reading for all Go programmers anyways). Additionally, we generally agree with the suggestions
    10   in [Uber's style guide](https://github.com/uber-go/guide/blob/master/style.md) and use that as a starting point.
    11  
    12  
    13  ## Code Structure
    14  
    15  Perhaps more key for code readability than good commenting is having the right structure. As a rule of thumb, try to write
    16  in a logical order of importance, taking a little time to think how to order and divide the code such that someone could
    17  scroll down and understand the functionality of it just as well as you do. A loose example of such order would be:
    18  
    19  * Constants, global and package-level variables
    20  * Main Struct
    21  * Options (only if they are seen as critical to the struct else they should be placed in another file)
    22  * Initialization / Start and stop of the service
    23  * Msgs/Events
    24  * Public Functions (In order of most important)
    25  * Private/helper functions
    26  * Auxiliary structs and function (can also be above private functions or in a separate file)
    27  
    28  ## General
    29  
    30  * Use `gofmt` (or `goimport`) to format all code upon saving it.  (If you use VIM, check out vim-go).
    31  * Use a linter (see below) and generally try to keep the linter happy (where it makes sense).
    32  * Think about documentation, and try to leave godoc comments, when it will help new developers.
    33  * Every package should have a high level doc.go file to describe the purpose of that package, its main functions, and any other relevant information.
    34  * `TODO` should not be used. If important enough should be recorded as an issue.
    35  * `BUG` / `FIXME` should be used sparingly to guide future developers on some of the vulnerabilities of the code.
    36  * `XXX` can be used in work-in-progress (prefixed with "WIP:" on github) branches but they must be removed before approving a PR.
    37  * Applications (e.g. clis/servers) *should* panic on unexpected unrecoverable errors and print a stack trace.
    38  
    39  ## Comments
    40  
    41  * Use a space after comment deliminter (ex. `// your comment`).
    42  * Many comments are not sentences. These should begin with a lower case letter and end without a period.
    43  * Conversely, sentences in comments should be sentenced-cased and end with a period.
    44  
    45  ## Linters
    46  
    47  These must be applied to all (Go) repos.
    48  
    49  * [shellcheck](https://github.com/koalaman/shellcheck)
    50  * [golangci-lint](https://github.com/golangci/golangci-lint) (covers all important linters)
    51      * See the `.golangci.yml` file in each repo for linter configuration.
    52  
    53  ## Various
    54  
    55  * Reserve "Save" and "Load" for long-running persistence operations. When parsing bytes, use "Encode" or "Decode".
    56  * Maintain consistency across the codebase.
    57  * Functions that return functions should have the suffix `Fn`
    58  * Names should not [stutter](https://blog.golang.org/package-names). For example, a struct generally shouldn’t have
    59    a field named after itself; e.g., this shouldn't occur:
    60  
    61  ``` golang
    62  type middleware struct {
    63  	middleware Middleware
    64  }
    65  ```
    66  
    67  * In comments, use "iff" to mean, "if and only if".
    68  * Product names are capitalized, like "Tendermint", "Basecoin", "Protobuf", etc except in command lines: `tendermint --help`
    69  * Acronyms are all capitalized, like "RPC", "gRPC", "API".  "MyID", rather than "MyId".
    70  * Prefer errors.New() instead of fmt.Errorf() unless you're actually using the format feature with arguments.
    71  
    72  ## Importing Libraries
    73  
    74  Sometimes it's necessary to rename libraries to avoid naming collisions or ambiguity.
    75  
    76  * Use [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)
    77  * Separate imports into blocks - one for the standard lib, one for external libs and one for application libs.
    78  * Here are some common library labels for consistency:
    79      * dbm "github.com/tendermint/tm-db"
    80      * tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
    81      * tmcfg "github.com/tendermint/tendermint/config/tendermint"
    82      * tmtypes "github.com/tendermint/tendermint/types"
    83  * Never use anonymous imports (the `.`), for example, `tmlibs/common` or anything else.
    84  * When importing a pkg from the `tendermint/libs` directory, prefix the pkg alias with tm.
    85      * tmbits "github.com/tendermint/tendermint/libs/bits"
    86  * tip: Use the `_` library import to import a library for initialization effects (side effects)
    87  
    88  ## Dependencies
    89  
    90  * Dependencies should be pinned by a release tag, or specific commit, to avoid breaking `go get` when external dependencies are updated.
    91  * Refer to the [contributing](CONTRIBUTING.md) document for more details
    92  
    93  ## Testing
    94  
    95  * The first rule of testing is: we add tests to our code
    96  * The second rule of testing is: we add tests to our code
    97  * For Golang testing:
    98      * Make use of table driven testing where possible and not-cumbersome
    99          * [Inspiration](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go)
   100      * Make use of [assert](https://godoc.org/github.com/stretchr/testify/assert) and [require](https://godoc.org/github.com/stretchr/testify/require)
   101  * When using mocks, it is recommended to use Testify [mock](<https://pkg.go.dev/github.com/stretchr/testify/mock>
   102   ) along with [Mockery](https://github.com/vektra/mockery) for autogeneration
   103  
   104  ## Errors
   105  
   106  * Ensure that errors are concise, clear and traceable.
   107  * Use stdlib errors package.
   108  * For wrapping errors, use `fmt.Errorf()` with `%w`.
   109  * Panic is appropriate when an internal invariant of a system is broken, while all other cases (in particular,
   110    incorrect or invalid usage) should return errors.
   111  
   112  ## Config
   113  
   114  * Currently the TOML filetype is being used for config files
   115  * A good practice is to store per-user config files under `~/.[yourAppName]/config.toml`
   116  
   117  ## CLI
   118  
   119  * When implementing a CLI use [Cobra](https://github.com/spf13/cobra) and [Viper](https://github.com/spf13/viper).
   120  * Helper messages for commands and flags must be all lowercase.
   121  * Instead of using pointer flags (eg. `FlagSet().StringVar`) use Viper to retrieve flag values (eg. `viper.GetString`)
   122      * The flag key used when setting and getting the flag should always be stored in a
   123     variable taking the form `FlagXxx` or `flagXxx`.
   124      * Flag short variable descriptions should always start with a lower case character as to remain consistent with
   125     the description provided in the default `--help` flag.
   126  
   127  ## Version
   128  
   129  * Every repo should have a version/version.go file that mimics the Tendermint Core repo
   130  * We read the value of the constant version in our build scripts and hence it has to be a string
   131  
   132  ## Non-Go Code
   133  
   134  * All non-Go code (`*.proto`, `Makefile`, `*.sh`), where there is no common
   135     agreement on style, should be formatted according to
   136     [EditorConfig](http://editorconfig.org/) config:
   137  
   138     ```toml
   139     # top-most EditorConfig file
   140     root = true
   141  
   142     # Unix-style newlines with a newline ending every file
   143     [*]
   144     charset = utf-8
   145     end_of_line = lf
   146     insert_final_newline = true
   147     trim_trailing_whitespace = true
   148  
   149     [Makefile]
   150     indent_style = tab
   151  
   152     [*.sh]
   153     indent_style = tab
   154  
   155     [*.proto]
   156     indent_style = space
   157     indent_size = 2
   158     ```
   159  
   160     Make sure the file above (`.editorconfig`) are in the root directory of your
   161     repo and you have a [plugin for your
   162     editor](http://editorconfig.org/#download) installed.