Writing a Ruby Extension in Go (Golang)

Writing a Ruby extension in Go (golang)

Go 1.5 added support for building shared libraries that are callable from C (and thus from Ruby via FFI). This makes the process easier than in pre-1.5 releases (when it was necessary to write the C glue layer), and the Go runtime is now usable, making this actually useful in real life (goroutines and memory allocations were not possible before, as they require the Go runtime, which was not useable if Go was not the main entry point).

goFuncs.go:

package main

import "C"

//export GoAdd
func GoAdd(a, b C.int) C.int {
return a + b
}

func main() {} // Required but ignored

Note that the //export GoAdd comment is required for each exported function; the symbol after export is how the function will be exported.

goFromRuby.rb:

require 'ffi'

module GoFuncs
extend FFI::Library
ffi_lib './goFuncs.so'
attach_function :GoAdd, [:int, :int], :int
end

puts GoFuncs.GoAdd(41, 1)

The library is built with:

go build -buildmode=c-shared -o goFuncs.so goFuncs.go

Running the Ruby script produces:


42

Read text file into string array (and write)

As of Go1.1 release, there is a bufio.Scanner API that can easily read lines from a file. Consider the following example from above, rewritten with Scanner:

package main

import (
"bufio"
"fmt"
"log"
"os"
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}

// writeLines writes the lines to the given file.
func writeLines(lines []string, path string) error {
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()

w := bufio.NewWriter(file)
for _, line := range lines {
fmt.Fprintln(w, line)
}
return w.Flush()
}

func main() {
lines, err := readLines("foo.in.txt")
if err != nil {
log.Fatalf("readLines: %s", err)
}
for i, line := range lines {
fmt.Println(i, line)
}

if err := writeLines(lines, "foo.out.txt"); err != nil {
log.Fatalf("writeLines: %s", err)
}
}

Stick with PHP or learn Go-lang?

Alas, I'd love to have 1 asset that I could use for all conditions but it's just not available in the world of computing. You're going to have to learn 2 or more.

PHP is very widely used, so you might as well stick with it. If you can create decent webapps using it, go for it. I would suggest learning C/C++ too so you can write any high-performance modules using that and call them from your PHP code. That's probably the best of all worlds for your webapps.

If you wanted to write for desktops, I think you'll be best off learning C++ with Qt (and look at Wt) (as it appears you're a Linux dev), or C#/VB.NET for Windows.

For mobiles, learn C/C++ as you can write apps in that no matter which platform even if you have to put up with some platform-dependant extensions - you either have to learn Java for Android, Objective-C for iOS, or (well we're not quite sure what MS has planned for Windows Phone 8, but I hear they like native code again, that means C++/CX). You can see where I'm going with this!

so anyway, if you're happy with PHP then keep with it. There is a ton of code out there that runs PHP so it's not like you're working with some bleeding-edge or hardly-used obscure language.



Related Topics



Leave a reply



Submit