cgoを試す(Goから./jqを呼ぶ)

Go言語には、C言語のコードを呼べるcgoという機能があります。

jsonsed」の./jqの機能を呼んでみます。

jqを選んだのは、 * ./jqはコマンド自体はそこそこ有名 * Go言語から直接呼べれば役にたつ(かもしれない) * APIが単純 * mrubyやImageMagickのような有名所は既にやった人がいる

cgoで呼び出してみる

あらかじめ、jqのソースコードをチェックアウトし、./configure && make && sudo make install しておきます。

あとは、import "C"の上のコメントの中に、ヘッダーやリンカのオプションをを書くだけです。 C言語の関数やenum定数は、C.経由で使えます。

ほとんどシームレスにC言語を使えます。 唯一面倒なのは、文字列をC.CString <=> C.GoStringで変換しなければいけないことでした。

package main

/*
#cgo LDFLAGS: -ljq
#include <jq.h>
#include <jv.h>
*/
import "C"

func main() {
    s := C.jq_init()
    defer C.jq_teardown(&s)

    json_data := `{
        "parameters": [
            {"name": "PKG_TAG_NAME", "value": "trunk"},
            {"name": "GIT_COMMIT", "value": "master"},
            {"name": "TRIGGERED_JOB", "value": "trunk-buildall"}
        ],
        "id": "2013-12-27_00-09-37",
        "changeSet": {"items": [], "kind": "git"}
    }
    `
    data := C.jv_parse(C.CString(json_data))

    script := `.parameters[] | {"key": .name, "value": .value}`
    C.jq_compile(s, C.CString(script))

    C.jq_start(s, data, 0)
    for {
        v := C.jq_next(s)
        if C.jv_is_valid(v) == 0 {
            break
        }
        str := C.jv_dump_string(v, C.JV_PRINT_PRETTY|C.JV_PRINT_COLOUR|C.JV_PRINT_SORTED)
        defer C.jv_free(str)
        println(C.GoString(C.jv_string_value(str)))
    }
}