After all, sometimes Ruby just isn’t enough to handle to the task at hand, and there have been times where we’ve had to rewrite parts of some applications with something a bit faster. Case in point: the birth of imgproxy came about via Go while we were working on a Ruby project for eBay.

So, why not just use Go? The serious answer to that question is…

…well, actually, who needs the serious answer? What’s the point in yet another article covering when to use Go versus when to use Ruby? Let’s just toss that idea out! Instead, let’s approach this article through the lens of fantasy and pretend that—because of (possibly apocalyptic) circumstances beyond our control—we need to write literally everything in Go!

Assessing the situation

So, let’s say all of our projects have already been written in Ruby, but in this fantasy world, we’ll need to abandon that language. How can we “let it Go? (“It” being Ruby, of course). There are a few options available here:

Our goal is to take a new class, written in Go, and have it work right in the middle of the old Ruby codebase. That way, when it’s actually time to migrate, we’ll already be 80% ready to go. To test this idea, let’s take the “Hello World” example from A Tour of Go and change the file extension so that main.go will be main.go.rb:

# main.go.rb

package main

import "fmt"

func main() {
  fmt.Println("Hello, 世界")
}

To start, let’s just try running it:

$ ruby main.go.rb
main.go.rb:1:in `<main>': undefined local variable or method `main' for main:Object (NameError)

Well, unfortunately, it didn’t work. This means we’ll have to handwrite some code—a rare case with Ruby, but it does happen from time to time.

Implementing Go packages in Ruby

First, we are going to implement the package method. Here is how Ruby sees package main:

package main #=> package(main())

package foo #=> package(foo())

Ruby calls the main method and passes the result to the package method. But main and foo are undefined… so there is only one way to make it work.

Let’s add method_missing, which will always return the name of a method:

This method would be just perfect for actual, real-world production code, no? 😏