uzullaがブログ

uzullaがブログです。

PHPerでも書けるgo言語

超簡単なお仕事がはいってきたんですが、ちょっとした事だったのでGo言語で書く事にしました。
わりとどうこうなかったんですが、さすがのgo、ググラビリティが微妙であり、go言語入門にイケてる感じの記事がぱっとなかったのでメモ的な感じで残してみます。

基本的にPHPer向けです。

go言語のインストール

MacだとBrewで一発ではいります。

brew install go

Helloworld

hello.go

package main

import ("fmt")

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

LLっぽく実行するには(コンパイルと実行を同時にやるには)

go run hello.go

main関数から始まる、というのがC言語っぽくてなつかしいですね。
go runをつかうとスクリプト言語と似た感じになるので、とても楽で良いです。

環境設定

Goのライブラリは

go get github.com/nsf/gocode

みたいにして入れる事ができます。

そのときに、GOPATHがないとおこられるので、設定します。
これは自分のホームディレクトリ以下に適当に設定するとよいのではないでしょうか。
私は~/.goを作成して、以下のように.bash_profileに書きました。

export GOPATH="$HOME/.go/"

環境設定 エディタ

Go言語を良い感じにしてくれるエディタはなにがいいのかわからないんですけど、まあとりあえずvimは対応しています。

http://mattn.kaoriya.net/software/vim/20130531000559.htm
こちらを参考にして、vimの設定をしました。

:Fmt のオートフォーマット便利ですね、

echo

fmt.Print、またはfmt.Printlnをつかいます。Printlnは自動的に最後に改行いれてくれる、Perlでいうところのsayです。
上のHelloworldをみてください。

標準エラーSTDERRに出力したい場合には、Fprintlnをつかいます

//fmtとosをimportしておく必要があります。
fmt.Fprintln(os.Stderr, "Error”);

簡単な文字列操作

宣言は

str := "great string"

で宣言ができます。「:=」は右辺の型からよしなに左辺の型をきめて宣言してくれる感じですね。

連結は+演算子でできます。

str = str + "!!!"
str += "???"

Substrは「str[1:2]」とかやります

    fmt.Println("Hello, world"[7:])
    // world
    fmt.Println("Hello, world"[3:5])
    // lo
    fmt.Println("Hello, world"[0:1])
    // H
    fmt.Println("Hello, world"[:4])
    // Hell

文字の数を数えるのはlen関数を使います

    fmt.Println(len("Hello, world"))
    // 12

単体でPrintlnに数値をいれるのは型キャストいりませんが、連結するならキャストが必要になります。

    fmt.Println(10)
    // 10
    fmt.Println("ten is "+strconv.Itoa(10))
    // ten is 10

文字列を数字にキャストするにはAtoiをつかいます

    num,_ := strconv.Atoi("15")
    fmt.Println(num+10)
    // 25

num,_ですが、これは返値が配列で返ってきて、第一引数には変換した数字、第二引数には成否が入ります。_を指定すると「捨てる」事になりますが、本来はここをみて「変換に成功できたか」をしらべる必要があります。

    num3,err := strconv.Atoi("a10")
    if (err!=nil) {
        fmt.Println("cast error")
    }else{
        fmt.Println(num3+10)
        // 10 (!?)
    }

ベターCっぽいですね。ただ、コード量がモリモリ増える!

ファイル読み込み

file_get_contentsみたいな感じでテキストファイルをロードするには以下のようなコードになります。
読み込むだけだとbyteの配列で返されるので、それをstringに変換しています。
stringsをimportしてください。

    byte_array, err := ioutil.ReadFile("filename.txt") 
    if err != nil {
        fmt.Println(err)
        exit
    }
    great_string := string(byte_array[:])

さらに、それを改行でくぎった配列にしたい、なんてときは以下のようになります。

    string_array := strings.Split(great_string, "\n")

連想配列とforeachなど

Go言語には連想配列的なものでMapとスライスがあるっぽいんですけど、まあ、Mapをつかいました。上のコードからのつづきで、各行をキー名として配列をつくるなら以下のようになります。

    string_map := map[string]bool{}
    for i, s := range string_array {
        if len(s) < 10 {
            continue
        }
        string_map[s] = true
    }

これはPHPでいえば以下のコードに相当します。

$string_map = [];
foreach ($string_array as $i=>$s ){
    if(strlen($s)<10){
        continue;
    }
    $string_map[$s] = true;
}

上に書いてありますが、連想配列に追加するのは

great_map[key_name] = value

となります。

いわゆるis_set()は以下のようにします

_, flag = great_map[key]
if flag {
    // found !
    return
}

これはmapにアクセスすると、配列で受け取る事ができて、取得できた値をすてつつ、成功したかのフラグを見ています。

for

goのfor文は便利というか、色々な事ができるようになっていて、

// 普通のFor
for i:=0; i<10; i++{
    //...
}

// whileみたいなの
flag = false
for i==false {
    //...
    i = true
}

// foreachみたいなの
for index, value := range great_array {
    //...
}

全部forで書きます。

forでは当然continueがつかえますが、

for i<10 {
    //...
    if hoge { 
        continue
    }
}

phpでいうところのcontinue 2 をしたい場合には、forにlabelを定義する必要があります

label_name : for i <10 {
    for x < 10{
        if hoge {
            continue label_name
        }
    }
}

書くの面倒ですけど、何個抜けるか数えなくて良いのは良いですね。

文字列の配列の宣言

こんな風に宣言できます。
[...]の部分は配列の要素数を最初に指定せず、うしろの{〜}を数えてもらう感じです。勿論自分で指定もできます。

s := [...]string{"a", "b", "c", "d",}

乱数

timeとmath/randをimportしてください

rand.Seed(time.Now().UTC().UnixNano())
rand_num: = rand.Intn(9) // 0〜9の整数の乱数を取得

初期化は必須っぽいです。
当然ですけど、これは類推が可能なseedなので、このままかいたらダメです!!!
もっとちゃんとしたseedを使いましょう(こういうこと考えたくないんだけど!?(PHP脳))

参考になったURL

http://golang.jp/go_tutorial
http://golang.jp/effective_go
http://golang.jp/go_spec
http://golang.jp/go_for_cpp_programmers
http://golang.jp/pkg

「全部公式サイトじゃねーか!!!」公式ではなかったw

まとめ

さあ、上記から今回の私のお仕事内容を考えましょう(違)


まあ特にすごい不満もないですね、go言語Cよりは書きやすいですし、バッチ的処理はさすがにPHPとかより断然高速ですし、go runつかえば(起動は一瞬かかるけど)LLみたいにかけるし、良いですね。

ただ、LLになれてると、最初からある機能だけだと結構だるい(特にPHPerには)ので、なんかいいライブラリとかないのか感はあります。

こちらからは以上です。