if err != nil โ Why You'll Miss Ruby's begin/rescue
Go doesn't use exceptions. Errors are returned as values. Half your code becomes error handling.
This is the biggest shock for Ruby developers trying Go.
In Ruby, errors throw Exceptions that get caught by rescue somewhere up the stack. Write the happy path, handle errors in one rescue block.
Go is completely different. No exceptions. Errors are return values.
Ruby vs Go Error Handling
Ruby:
begin
data = File.read("config.yml")
config = YAML.parse(data)
save(config)
rescue => e
puts "Error: #{e.message}"
end
Go:
data, err := os.ReadFile("config.yml")
if err != nil { return err }
config, err := yaml.Unmarshal(data)
if err != nil { return err }
err = save(config)
if err != nil { return err }
See it? Ruby: 3 lines of happy path + 1 line rescue. Go: 3 lines of actual logic + 6 lines of error checking. if err != nil repeats after every function call.
Why This Design
Go team's philosophy: errors must not be ignored. In exception-based systems, forgetting rescue lets errors propagate silently. In Go, you receive the error and must handle it explicitly. Skip it and the compiler errors: "err declared but not used."
errors.Is, errors.As โ Like Ruby's is_a?
Just as Ruby catches specific exceptions with rescue ActiveRecord::RecordNotFound, Go checks error types with errors.Is(err, sql.ErrNoRows) or errors.As(err, &target).
panic/recover โ Seriously Don't
Go has panic(). Similar to Ruby's raise. But Go community reserves panic for situations where the program truly cannot continue. HTTP request errors get error returns, not panics.
Completely different culture from Ruby's everyday raise/rescue usage.
Ruby to Go
Ruby: begin/rescue/end โ Go: if err != nil { return err } (after every call)
Ruby: raise CustomError โ Go: errors.New("message") or fmt.Errorf()
Ruby: rescue SpecificError โ Go: errors.Is(err, target) / errors.As(err, &target)
Ruby: raise (everyday) โ Go: panic (only for fatal situations, don't use daily)
Pros
- ✓ Can't ignore errors โ compiler enforces it. Prevents Ruby's "forgot rescue, exploded in production" problem
- ✓ Error flow is explicit โ reading the code shows where errors occur and how they're handled
Cons
- ✗ if err != nil takes up 40-50% of code โ severe visual noise
- ✗ No Ruby-style retry pattern (rescue โ retry) โ must implement retry logic manually