go: Export the latest version of internal guide. (#912)

The updates encompass renaming testing-associated package's section
heading, guidance on when to panic, and naming of subtests.
This commit is contained in:
Matt T. Proud authored and GitHub committed 2025-04-04 11:27:25 +02:00
1 parent 8e44515b72
commit 1052896258
2 files changed
+70 -13

No files matched your search

+52 -6
View File
@@ -165,7 +165,7 @@ methods:
<a id="naming-doubles"></a>
### Test double packages and types
### Test double and helper packages
There are several disciplines you can apply to [naming] packages and types that
provide test helpers and especially [test doubles]. A test double could be a
@@ -1241,11 +1241,47 @@ Another case in which panics can be useful, though uncommon, is as an internal
implementation detail of a package which always has a matching recover in the
callchain. Parsers and similar deeply nested, tightly coupled internal function
groups can benefit from this design, where plumbing error returns adds
complexity without value. The key attribute of this design is that these panics
are never allowed to escape across package boundaries and do not form part of
the package's API. This is typically accomplished with a top-level deferred
recover that translates a propagating panic into a returned error at the public
API surfaces.
complexity without value.
The key attribute of this design is that these **panics are never allowed to
escape across package boundaries** and do not form part of the package's API.
This is typically accomplished with a top-level deferred function that uses
`recover` to translate a propagated panic into a returned error at the public
API boundary. It requires the code that panics and recovers to distinguish
between panics that the code raises itself and those that it doesn't:
```go
// Good:
type syntaxError struct {
msg string
}
func parseInt(in string) int {
n, err := strconv.Atoi(in)
if err != nil {
panic(&syntaxError{"not a valid integer"})
}
}
func Parse(in string) (_ *Node, err error) {
defer func() {
if p := recover(); p != nil {
sErr, ok := p.(*syntaxError)
if !ok {
panic(p) // Propagate the panic since it is outside our code's domain.
}
err = fmt.Errorf("syntax error: %v", sErr.msg)
}
}()
... // Parse input calling parseInt internally to parse integers
}
```
> **Warning:** Code employing this pattern must take care to manage any
> resources associated with the code run in such defer-managed sections (e.g.,
> close, free, or unlock).
>
> See: [Go Tip #81: Avoiding Resource Leaks in API Design]
Panic is also used when the compiler cannot identify unreachable code, for
example when using a function like `log.Fatal` that will not return:
@@ -1270,6 +1306,16 @@ If you must die in a package initialization function (an `init` or a
["must" function](decisions#must-functions)), a panic is acceptable in place of
the fatal logging call.
See also:
* [Handling panics](https://go.dev/ref/spec#Handling_panics) and
[Run-time Panics](https://go.dev/ref/spec#Run_time_panics) in the language
specification
* [Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover)
* [On the uses and misuses of panics in Go](https://eli.thegreenplace.net/2018/on-the-uses-and-misuses-of-panics-in-go/)
[Go Tip #81: Avoiding Resource Leaks in API Design]: https://google.github.io/styleguide/go/index.html#gotip
<a id="documentation"></a>
## Documentation
+18 -7
View File
@@ -96,8 +96,15 @@ must be renamed at import time to a name that is suitable for use in Go code.
An exception to this is that package names that are only imported by generated
code may contain underscores. Specific examples include:
* Using the `_test` suffix for an external test package, for example an
integration test
* Using the `_test` suffix for unit tests that only exercise the exported API
of a package (package `testing` calls these
["black box tests"](https://pkg.go.dev/testing)). For example, a package
`linkedlist` must define its black box unit tests in a package named
`linkedlist_test` (not `linked_list_test`)
* Using underscores and the `_test` suffix for packages that specify
functional or integration tests. For example, a linked list service
integration test could be named `linked_list_service_test`
* Using the `_test` suffix for
[package-level documentation examples](https://go.dev/blog/examples)
@@ -3401,11 +3408,15 @@ command line for users of test filtering. When you use `t.Run` to create a
subtest, the first argument is used as a descriptive name for the test. To
ensure that test results are legible to humans reading the logs, choose subtest
names that will remain useful and readable after escaping. Think of subtest
names more like a function identifier than a prose description. The test runner
replaces spaces with underscores, and escapes non-printing characters. If your
test data benefits from a longer description, consider putting the description
in a separate field (perhaps to be printed using `t.Log` or alongside failure
messages).
names more like a function identifier than a prose description.
The test runner replaces spaces with underscores, and escapes non-printing
characters. To ensure accurate correlation between test logs and source code, it
is recommended to avoid using these characters in subtest names.
If your test data benefits from a longer description, consider putting the
description in a separate field (perhaps to be printed using `t.Log` or
alongside failure messages).
Subtests may be run individually using flags to the [Go test runner] or Bazel
[test filter], so choose descriptive names that are also easy to type.