C
GO

C to Go

10 lessons

Progress0%
1Variables & Types2Functions3Arrays & Slices4Structs & Methods5Pointers6Concurrency7Header Files → Packages8Error Handling9Testing10Standard Library
All Mirror Courses
C
GO
Error Handling
MirrorLesson 8 of 10
Lesson 8

Error Handling

Dealing with failures

Introduction

In this lesson, you'll learn about error handling in Go. Coming from C, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
C
From C:

In C, you're familiar with dealing with failures.

GO
In Go:

Go has its own approach to dealing with failures, which we'll explore step by step.

The Go Way

Let's see how Go handles this concept. Here's a typical example:

GO
Go Example
package main

import (
    "errors"
    "fmt"
    "os"
)

var ErrInvalidPath = errors.New("invalid path")

func readConfig(path string) (string, error) {
    if path == "" {
        return "", ErrInvalidPath
    }
    data, err := os.ReadFile(path)
    if err != nil {
        return "", fmt.Errorf("readConfig: %w", err)
    }
    return string(data), nil
}

func main() {
    data, err := readConfig("config.txt")
    if err != nil {
        if errors.Is(err, ErrInvalidPath) {
            fmt.Println("no path provided")
        } else {
            fmt.Println("error:", err)
        }
        os.Exit(1)
    }
    fmt.Println("config:", data)
}

Comparing to C

Here's how you might have written similar code in C:

C
C (What you know)
#include <stdio.h>
#include <errno.h>
#include <string.h>

/* Return code convention: 0 = success, non-zero = error */
int read_config(const char *path, char *buf, int len) {
    FILE *f = fopen(path, "r");
    if (!f) {
        return errno; /* set by fopen */
    }
    if (!fgets(buf, len, f)) {
        fclose(f);
        return -1;
    }
    fclose(f);
    return 0; /* success */
}

int main() {
    char buf[256];
    int err = read_config("config.txt", buf, sizeof(buf));
    if (err != 0) {
        fprintf(stderr, "error: %s\n", strerror(err));
        return 1;
    }
    printf("config: %s\n", buf);
}
Mirror Card
C
From C:

You may be used to different syntax or behavior.

GO
In Go:

Go returns error as a value; C uses errno or return codes

Mirror Card
C
From C:

You may be used to different syntax or behavior.

GO
In Go:

Go's errors.Is checks error identity; C compares integer codes

Mirror Card
C
From C:

You may be used to different syntax or behavior.

GO
In Go:

Go's fmt.Errorf %w wraps errors with context; C has no wrapping convention

Mirror Card
C
From C:

You may be used to different syntax or behavior.

GO
In Go:

Go forces you to handle errors at every call site; C's errno is global and easily ignored

Step-by-Step Breakdown

1. Error as Return Value

Go returns errors as the last return value — cleaner than C's errno global and impossible to accidentally ignore.

C
C
int err = read_config(path, buf, sizeof(buf));
if (err != 0) { ... }
GO
Go
data, err := readConfig(path)
if err != nil { ... }

2. Error Wrapping

Go's fmt.Errorf with %w adds context to errors while preserving the original, enabling errors.Is for type checking up the chain.

GO
Go
return "", fmt.Errorf("readConfig: %w", err)
// Caller can: errors.Is(err, os.ErrNotExist)

3. Sentinel Errors

Go sentinel errors (package-level variables) replace C's error code constants, enabling identity comparison with errors.Is.

C
C
#define ERR_INVALID_PATH -2
GO
Go
var ErrInvalidPath = errors.New("invalid path")

Common Mistakes

When coming from C, developers often make these mistakes:

  • Go returns error as a value; C uses errno or return codes
  • Go's errors.Is checks error identity; C compares integer codes
  • Go's fmt.Errorf %w wraps errors with context; C has no wrapping convention
Common Pitfall
Don't assume Go works exactly like C. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Go returns error values; C uses errno or int return codes
  • errors.Is replaces integer error code comparisons
  • fmt.Errorf %w adds context while wrapping original error
  • Go errors are impossible to silently ignore at compile time
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your C code in Go to practice these concepts.
PreviousNext