You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 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
+
}
271
271
}
272
272
```
273
273
@@ -281,36 +281,51 @@ Example:
281
281
282
282
```go
283
283
funcreadFile(filenamestring) ([]byte, error) {
284
-
file, err:= os.Open(filename)
285
-
if err != nil {
286
-
returnnil, 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
-
returnnil, 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
+
returnnil, 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
+
returnnil, fmt.Errorf("failed to read file: %w", err)
293
+
}
294
+
295
+
return data, nil
296
296
}
297
297
298
298
funcprocessFile(filenamestring) 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
-
returnnil
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
+
returnnil
305
305
}
306
306
307
307
funcmain() {
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
313
312
}
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))
314
329
```
315
330
316
331
## Logging
@@ -334,24 +349,24 @@ Below are some general guidelines to follow for writing concurrent code:
334
349
reentrant, you _must_ document that in the comments. Make it clear and obvious.
335
350
-**Don't leak goroutines**: Goroutines are not garbage collected by the runtime, so every goroutine you start must also
336
351
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].
340
355
-**Blocking operations within a goroutine must be preemptable**: This allows goroutines to be cancelled and prevents
341
356
goroutine leaks.
342
357
-**Leverage contexts**: Contexts allow you to enforce deadlines and send cancellation signals to multiple goroutines.
343
358
-**Avoid buffered channels**: Use unbuffered channels unless there is a very good reason for using a buffered channel.
344
359
Unbuffered channels provide strong synchronization guarantees. Buffered channels are asynchronous and will not block
345
360
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.
348
363
-**Never copy sync types**: see [above section](#do-not-copy-sync-entities).
349
364
-**Choose primitives or channels based on use case**: In general, the Go language writers tell us to prefer channels
350
365
and communication for synchronization over primitives in the sync package such as mutexes and wait groups. "Do not
351
366
communicate by sharing memory. Instead, share memory by communicating". However, in practice, there are some cases
352
367
where sync primitives are the better choice. For example, you should use primitives if you are working with a
353
368
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.
355
370
-**When possible, write code that is implicitly concurrent-safe**: Code that is implicitly concurrent-safe can be
356
371
safely accessed by multiple goroutines concurrently without any synchronization. For example, immutable data is
357
372
implicitly concurrent-safe. Concurrent processes can operate on the data, but they can't modify it. Another example is
0 commit comments