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
How to Count the Frequencies of the Letters in User Input
PDF Generation Hangs Using PDFkit and Wkhtmotopdf
How to Get Order Username and Provisiondate for All Softlayer MAChines Using Ruby
Ruby Selenium Web Drive: How to Find Specific Element by Xpath Div Id and CSS Class
Need Help on Join Table, Limiting Results to Only the Resource Id
How to Convert a Large Gem to Standalone Rails App
Selenium Can't Find Fields with Type Number
How to Link to a Nested Route Path Inside a Loop
Prawn Gem: How to Create the .Pdf from an *Existing* File (.Xls)
Emulating Int64 Overflows in Ruby
Ruby Before_Validation Triggers Infinite Loop of Call Back
Local Server Error After Upgrading Ruby from 1.8.7 to 1.9.2 (With Rails 3.1.1)
Why Doesn't This Code Produce the Desired Result