Functions should return errors explicitly to callers rather than terminating the program, hiding errors in boolean returns, or using implicit error handling. This allows higher-level code to make appropriate decisions about error handling, recovery, and program flow.
Key principles:
return fmt.Errorf(...)
instead of log.Fatalf()
or t.Fatalf()
Example of problematic pattern:
func fileExists(filename string) bool {
_, err := os.Stat(filename)
if err != nil && !os.IsNotExist(err) {
log.Warnf("Unexpected error checking file %s: %v", filename, err)
}
return err == nil
}
func initBpfObjects() {
if err := os.Mkdir(MapsPinpath, os.ModePerm); err != nil {
log.Fatalf("unable to create ambient bpf mount directory: %v", err)
}
}
Improved pattern:
func fileExists(filename string) (bool, error) {
if filename == "" {
return false, nil
}
_, err := os.Stat(filename)
if err != nil && !os.IsNotExist(err) {
return false, fmt.Errorf("unexpected error checking file %s: %v", filename, err)
}
return err == nil, nil
}
func initBpfObjects() error {
if err := os.Mkdir(MapsPinpath, os.ModePerm); err != nil {
return fmt.Errorf("unable to create ambient bpf mount directory: %v", err)
}
return nil
}
This approach provides callers with the flexibility to implement appropriate error handling strategies, retry logic, or graceful degradation based on their specific context and requirements.
Enter the URL of a public GitHub repository