2012/09/14


そろそろWeb周りだけでなくDB周りも揃ってきて、本格的なアプリケーションが書ける様になってきました。
DBを扱うには、SQLを実行する様な物は標準でサポートしていましたが、gorp を使うと極力SQLを書かずにデータベースを扱う事が出来ます。
coopernurse/gorp - GitHub

Go Relational Persistence I hesitate to call gorp an ORM.

https://github.com/coopernurse/gorp
まずエンティティとなる構造体を宣言します。ここでは Person という構造にします。 type Person struct {
    Id int32
    Name string
}
次に、データベースマッパーを作ります。 db, err := sql.Open("sqlite3""./foo.db")
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
ドライバはSQLite3を使いましたが、MySQLとPostgreSQLもサポートしている様です。 なお、gorp では使えませんが、Go言語で使えるデータベースは以下のWikiにエントリされています。
SQLDrivers - go-wiki - SQL database drivers - Go Language Community Wiki - Google Project Hosting

SQL database drivers The database/sql and database/sql/driver packages are designed for using databa...

http://code.google.com/p/go-wiki/wiki/SQLDrivers
手前味噌ですが、SQLite3 と Oracle(OCI8)、Microsoft ADODB のドライバは僕が作った奴です。バグあったら教えて下さい。

さて、データベースマッパーが出来たらテーブルと構造体の紐付けを行います。 t := dbmap.AddTableWithName(Person{}, "person").SetKeys(true"Id")
t.ColMap("Id").Rename("id")
t.ColMap("Name").Rename("name")
person というテーブル名で Person 構造体を登録し、Id がキーである事を教えています。その後、カラム名のリネームも行っています。テーブルのフィールド名先頭が大文字とか気持ち悪いとか、UserName というフィールドが "USER_NAME" というカラムに割り当てたい場合に使います。
この後、テーブルを作ります。 dbmap.DropTables()
err = dbmap.CreateTables()
今回は1つしかテーブルを扱っていませんが、一度に複数登録して一括で作成する事が多いと思います。
ではデータを登録しましょう。dbmap.Insert でも登録出来ますが、ここではトランザクションを使いましょう。
tx, _ := dbmap.Begin()
for i := 0; i < 100; i++ {
    tx.Insert(&Person{0, fmt.Sprintf("mattn%03d", i)})
}
tx.Commit()
今度はデータを取得してみましょう。dbmap.Get でキーを指定して1行取得する事も出来ますし、Select を使う事も出来ます。
list, _ := dbmap.Select(Person{}, "select * from person")
for _, l := range list {
    p := l.(*Person)
    fmt.Printf("%d, %s\n", p.Id, p.Name)
}
なんだか便利になってきましたね。全体のコードは以下の通り。
package main

import (
    "database/sql"
    "github.com/coopernurse/gorp"
    _ "github.com/mattn/go-sqlite3"
    "fmt"
)

type Person struct {
    Id int32
    Name string
}

func main() {
    db, err := sql.Open("sqlite3""./foo.db")
    if err != nil {
        panic(err.Error())
    }
    dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
    t := dbmap.AddTableWithName(Person{}, "person").SetKeys(true"Id")
    t.ColMap("Id").Rename("id")
    t.ColMap("Name").Rename("name")
    dbmap.DropTables()
    err = dbmap.CreateTables()
    if err != nil {
        panic(err.Error())
    }

    tx, _ := dbmap.Begin()
    for i := 0; i < 100; i++ {
        tx.Insert(&Person{0, fmt.Sprintf("mattn%03d", i)})
    }
    tx.Commit()

    list, _ := dbmap.Select(Person{}, "select * from person")
    for _, l := range list {
        p := l.(*Person)
        fmt.Printf("%d, %s\n", p.Id, p.Name)
    }
}
Go言語もだんだん仕事で使えそうな言語になってきましたね。

Posted at by



2012/09/13


Webのお仕事をやってると、Webサーバのインスタンスと同時にワーカープロセスを起動する事も結構多く、ジョブキューサーバも含めて一括で起動したくなったりします。
ruby 製の foreman という物を使うと Procfile というファイルに書かれた内容でプロセスを起動して、個別に上げたり落としたり出来る様になります。ただしwindowsでは重くて使えない(windows上のrubyどうにかしてる)し、kazeburoさんが作ってるperl製のProcletはParallel::Preforkがwindowsで動かないので困ってました。 ここまで来たら自分で書くしかないかなーとか考えながら、C言語で書くの面倒臭いと思ったのでGo言語で書きました。
mattn/goreman - GitHub

foreman clone written in go language

https://github.com/mattn/goreman
今のところ以下の様に動きます。
まず以下の様なProcfileを用意します。 web1: plackup --port 5000
web2: plackup --port 5001
このファイルのある場所で、 $ goreman start とすると Procfileにエントリされているプロセスを起動します。
goreman1
この様に色付きで標準出力されながら起動します。
別の端末で $ goreman run stop web1 とすると
goreman2
停止し $ goreman run start web1 とすると
goreman3
再度web1に割り当てられたプロセスが起動します。
$ goreman run restart web1 もあります。rpcの警告が出てるのはそのうち直します。
Windows と Linux で動作します。
今のところ、foreman の様に .env ファイルを読み込んだり、.foreman ファイルに従って起動したりはしていませんが、そのうちやるかもしれません。
機能はまだまだですが、そのうち便利になってく気がします。
Posted at by



2012/09/03


[twitter-fire?]twitterコミュニティの報告速度は素晴らしい。現に先日の渋谷シエスパ爆発事故でもtwitterユーザの報告はニュースとなる1時間程前から報告されていた。

この速度を生かし、災害対策ネットワークとして使うという案はどうだろう。


普段ユーザが手に持っている物といえば携帯電話。その携帯電話から送信された報告が、PULLではなくPUSHとしてIMユーザに通知される。 マスメディアに対する第一報という点では速度、報告者の拡散という意味で優れていると思う。さらにtwitterでは、あるユーザが書き込んだ報告が皆に伝わり、さらにその報告を聞いた者が別の者に報告する、といった情報拡散作用もある。もちろん匿名性の高いコミュニティーでもある事から、虚実な報告や誤報もありえる為に幾分怖い気もするが、このtwitterというシステムを災害対策システムの1モデルとして参考にするのも、あながち間違いではないのでは無いか?と思った。

Posted at by