Skip to content

Commit 4a09894

Browse files
author
Kate Osborn
committed
Add section on panic
1 parent 07d0027 commit 4a09894

File tree

1 file changed

+96
-81
lines changed

1 file changed

+96
-81
lines changed

docs/developer/go-style-guide.md

Lines changed: 96 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ recommendations tailored to the project's specific requirements and coding style
2222

2323
### Use the empty struct `struct{}` for sentinel values
2424

25-
Empty structs as sentinels unambiguously signal an explicit lack of information. For example, use empty struct for
26-
sets and for signaling via channels that don't require a message.
25+
Empty structs as sentinels unambiguously signal an explicit lack of information. For example, use empty struct for sets
26+
and for signaling via channels that don't require a message.
2727

2828
DO:
2929

@@ -52,37 +52,37 @@ DO:
5252

5353
```go
5454
func longFunctionDefinition(
55-
paramX int,
56-
paramY string,
57-
paramZ bool,
55+
paramX int,
56+
paramY string,
57+
paramZ bool,
5858
) (string, error){}
5959

6060
// and
6161

6262
s := myStruct{
63-
field1: 1,
64-
field2: 2,
65-
field3: 3,
63+
field1: 1,
64+
field2: 2,
65+
field3: 3,
6666
}
6767
```
6868

6969
DO NOT:
7070

7171
```go
7272
func longFunctionDefinition(paramX int, paramY string,
73-
paramZ bool,
73+
paramZ bool,
7474
) (string, error){}
7575

7676
// or
7777

7878
func longFunctionDefinition(
79-
paramX int, paramY string,
80-
paramZ bool,
79+
paramX int, paramY string,
80+
paramZ bool,
8181
) (string, error){}
8282

8383
// or
8484
s := myStruct{field1: 1, field2: 2,
85-
field3: 3}
85+
field3: 3}
8686

8787
```
8888

@@ -92,12 +92,12 @@ Example:
9292

9393
```go
9494
cfg := foo.Config{
95-
Site: "example.com",
96-
Out: os.Stdout,
97-
Dest: c.KeyPair{
98-
Key: "style",
99-
Value: "well formatted",
100-
},
95+
Site: "example.com",
96+
Out: os.Stdout,
97+
Dest: c.KeyPair{
98+
Key: "style",
99+
Value: "well formatted",
100+
},
101101
}
102102
```
103103

@@ -176,7 +176,7 @@ DO NOT:
176176

177177
```go
178178
func(int required, int optional) {
179-
if optional {...}
179+
if optional {...}
180180
}
181181
```
182182

@@ -186,15 +186,15 @@ DO:
186186
type Option func (o *Object)
187187

188188
func Optional(string optional) Option {
189-
return func (o *Object) {
190-
o.optional = optional
191-
}
189+
return func (o *Object) {
190+
o.optional = optional
191+
}
192192
}
193193

194194
func (int required, ...Options) {
195-
for o := range Options {
196-
o(self)
197-
}
195+
for o := range Options {
196+
o(self)
197+
}
198198
}
199199
```
200200

@@ -217,22 +217,22 @@ DO NOT:
217217

218218
```go
219219
func badAtStuff(noData string) error {
220-
if len(noData) == 0 {
221-
fmt.Printf("Received no data")
222-
}
220+
if len(noData) == 0 {
221+
fmt.Printf("Received no data")
222+
}
223223

224-
return errors.New("received no data")
224+
return errors.New("received no data")
225225
}
226226
```
227227

228228
DO
229229

230230
```go
231231
func badAtStuff(noData string) error {
232-
if len(noData) == 0 {
233-
return errors.New("received no data")
234-
}
235-
...
232+
if len(noData) == 0 {
233+
return errors.New("received no data")
234+
}
235+
...
236236
}
237237
```
238238

@@ -249,25 +249,25 @@ Example:
249249

250250
```go
251251
func onError(err error) {
252-
// got an asynchronous error
252+
// got an asynchronous error
253253
}
254254

255255
func ReadAsync(r io.Reader, onError) {
256-
err := r()
257-
if err != nil {
258-
onError(err)
259-
}
256+
err := r()
257+
if err != nil {
258+
onError(err)
259+
}
260260
}
261261

262262
go ReadAsync(reader, onError)
263263

264264
// OR errs := make(chan error)
265265

266266
func ReadAsync(r io.Reader, errs chan<- error) {
267-
err := r()
268-
if err != nil {
269-
// put error on errs channel, but don't block forever.
270-
}
267+
err := r()
268+
if err != nil {
269+
// put error on errs channel, but don't block forever.
270+
}
271271
}
272272
```
273273

@@ -281,36 +281,51 @@ Example:
281281

282282
```go
283283
func readFile(filename string) ([]byte, error) {
284-
file, err := os.Open(filename)
285-
if err != nil {
286-
return nil, fmt.Errorf("failed to open file: %w", err)
287-
}
288-
defer file.Close()
289-
290-
data, err := ioutil.ReadAll(file)
291-
if err != nil {
292-
return nil, fmt.Errorf("failed to read file: %w", err)
293-
}
294-
295-
return data, nil
284+
file, err := os.Open(filename)
285+
if err != nil {
286+
return nil, fmt.Errorf("failed to open file: %w", err)
287+
}
288+
defer file.Close()
289+
290+
data, err := ioutil.ReadAll(file)
291+
if err != nil {
292+
return nil, fmt.Errorf("failed to read file: %w", err)
293+
}
294+
295+
return data, nil
296296
}
297297

298298
func processFile(filename string) error {
299-
data, err := readFile(filename)
300-
if err != nil {
301-
return fmt.Errorf("failed to process file: %w", err)
302-
}
303-
// Process the file data here
304-
return nil
299+
data, err := readFile(filename)
300+
if err != nil {
301+
return fmt.Errorf("failed to process file: %w", err)
302+
}
303+
// Process the file data here
304+
return nil
305305
}
306306

307307
func main() {
308-
filename := "example.txt"
309-
err := processFile(filename)
310-
if err != nil {
311-
fmt.Printf("Error processing file: %v\n", err) // caller handles the error
312-
}
308+
filename := "example.txt"
309+
err := processFile(filename)
310+
if err != nil {
311+
fmt.Printf("Error processing file: %v\n", err) // caller handles the error
313312
}
313+
}
314+
```
315+
316+
### Use panics for unrecoverable errors or programming errors
317+
318+
Panics should be used in the following cases:
319+
320+
1. Unrecoverable errors. An unrecoverable error is when NKG cannot continue running or its behavior or internal state
321+
cannot be guaranteed. One example of this is if an error occurs when adding the Kubernetes API types to the Scheme,
322+
or if an error occurs when marking a CLI flag as required.
323+
2. Programming errors. A programming error is an error that is only possible if there was a programming mistake. For
324+
example, if the wrong type is passed or a go template is passed an invalid value.
325+
326+
When using panics, pass an error as the argument. For example:
327+
```go
328+
panic(fmt.Errorf("unknown event type %T", e))
314329
```
315330

316331
## Logging
@@ -334,24 +349,24 @@ Below are some general guidelines to follow for writing concurrent code:
334349
reentrant, you _must_ document that in the comments. Make it clear and obvious.
335350
- **Don't leak goroutines**: Goroutines are not garbage collected by the runtime, so every goroutine you start must also
336351
be cleaned up. Here's a couple of related principles:
337-
- "If a goroutine is responsible for creating a goroutine, it is also responsible for ensuring it can stop the
338-
goroutine." -- [Concurrency in Go][cig]
339-
- "Before you start a goroutine, always know when, and how, it will stop." -- [Concurrency Made Easy][cheney].
352+
- "If a goroutine is responsible for creating a goroutine, it is also responsible for ensuring it can stop the
353+
goroutine." -- [Concurrency in Go][cig]
354+
- "Before you start a goroutine, always know when, and how, it will stop." -- [Concurrency Made Easy][cheney].
340355
- **Blocking operations within a goroutine must be preemptable**: This allows goroutines to be cancelled and prevents
341356
goroutine leaks.
342357
- **Leverage contexts**: Contexts allow you to enforce deadlines and send cancellation signals to multiple goroutines.
343358
- **Avoid buffered channels**: Use unbuffered channels unless there is a very good reason for using a buffered channel.
344359
Unbuffered channels provide strong synchronization guarantees. Buffered channels are asynchronous and will not block
345360
unless the channel is full. Buffered channels can also be slower than unbuffered channels.
346-
- **Protect maps and slices**: Maps and slices cannot be accessed concurrently (when at least one goroutine is writing) without locking. Doing so can lead to
347-
data races.
361+
- **Protect maps and slices**: Maps and slices cannot be accessed concurrently (when at least one goroutine is writing)
362+
without locking. Doing so can lead to data races.
348363
- **Never copy sync types**: see [above section](#do-not-copy-sync-entities).
349364
- **Choose primitives or channels based on use case**: In general, the Go language writers tell us to prefer channels
350365
and communication for synchronization over primitives in the sync package such as mutexes and wait groups. "Do not
351366
communicate by sharing memory. Instead, share memory by communicating". However, in practice, there are some cases
352367
where sync primitives are the better choice. For example, you should use primitives if you are working with a
353368
performance-critical section, or protecting the internal state of a struct. However, you should use channels if you
354-
are transferring ownership of data (e.g. producer/consumer) or trying to coordinate multiple pieces of logic.
369+
are transferring ownership of data (e.g. producer/consumer) or trying to coordinate multiple pieces of logic.
355370
- **When possible, write code that is implicitly concurrent-safe**: Code that is implicitly concurrent-safe can be
356371
safely accessed by multiple goroutines concurrently without any synchronization. For example, immutable data is
357372
implicitly concurrent-safe. Concurrent processes can operate on the data, but they can't modify it. Another example is
@@ -398,27 +413,27 @@ FAVOR:
398413

399414
```go
400415
type Object struct{
401-
subobject SubObject
416+
subobject SubObject
402417
}
403418

404419
func New() Object {
405-
return Object{
406-
subobject: SubObject{},
407-
}
420+
return Object{
421+
subobject: SubObject{},
422+
}
408423
}
409424
```
410425

411426
DISFAVOR:
412427

413428
```go
414429
type Object struct{
415-
subobject *SubObject
430+
subobject *SubObject
416431
}
417432

418433
func New() *Object {
419-
return &Object{
420-
subobject: &SubObject{},
421-
}
434+
return &Object{
435+
subobject: &SubObject{},
436+
}
422437
}
423438
```
424439

@@ -440,8 +455,8 @@ DO NOT:
440455

441456
```go
442457
func(s string) *string {
443-
s := s + "more strings"
444-
return &s // this will move to heap
458+
s := s + "more strings"
459+
return &s // this will move to heap
445460
}
446461
```
447462

0 commit comments

Comments
 (0)