ただのアニメ感想ブログ

主にアニメの感想を書いていきます。

GoLangを触ってみた#その1

大型連休中に特にすることもなく家でごろごろしているのも良くないと思い、新しいプログラミング言語であるGoについて勉強してみることにしました。


まずはGoの実行環境を整える事から始めます。まずは普段使っているWindows端末上でGoが使えるようにします。
参考にしたのは以下のサイト。
http://golang.jp/


・・・ですが、インストールに関してはあまり参考にならないので、以下のサイトからWindows用のMSIファイルを落としてきて実行しました。
https://golang.org/dl/


インストール先のフォルダはデフォルトではC:\Goになります。
これは変更できますが、その場合は環境変数を色々と書かないといけないようなので、自分はそのままにしました。
で、早速Goを実行してみたのですがC:\Go\bin\go.exeにパスが通らない!何事かと思い環境変数を見てみたのですが特におかしな所はなし。仕方がないので環境変数を保存して再度コマンドプロンプトを立ち上げたら今度は上手くいきました。何だったんだ今のは。


で、待ちに待った動作確認。
以下のファイルを作成して実行してみる。

ファイル名:hello.go 
package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}


実行結果は以下のようになりました。

>go run hello.go
hello, world


う~ん、実行してから結果が帰ってくるのに少しラグがあったような気がするけど、まあ良いか。


Goが使える事が確認できたので、お次はクイックソートでも書いてみましょう。
そもそもリストとしてGoはどんなものが使えるのだろう。そこから調べてみないと。
・・・と言うわけで、調べてみるとGoは配列が普通に使えるようなので、それを利用しましょう。


まずはファイルから配列を読み込む部分を実装します。


早速はまったのは、

> non-declaration statement outside function body

と言うメッセージが実行時に出て来ました。
どうやらGoのファイルはimport→const→関数の順で書かないといけないらしい。自分はconstをimportの前に書いていたので、順序を入れ替えたことでエラーが出なくなりました。


できた関数は以下の様な感じ。

func readList(filename string) []int {
    var fp *os.File
    var error error

    fp, error = os.Open(filename)
    if error != nil {
        panic(error)
    }
    defer fp.Close()

    reader := csv.NewReader(fp)
    reader.Comma = ','
    reader.LazyQuotes = true

    record, error := reader.Read()
    if error != nil {
        panic(error)
    }

    var list []int
    for i := 0; i < len(record); i++ {
        var element int
        element, error = strconv.Atoi(record[i])
        if error != nil {
            panic(error)
        }

        list = append(list, element)
    }

    return list
}


CSV形式のファイルからrecord変数(配列)に読み込んで、for文の中でintに変換してlist変数(配列)に加えています。


う~ん・・・これもうちょっと賢いやり方は無いのかなぁ。最初から整数で読み込むとか。
いちいちappendするあたりが凄く計算の無駄に見えます。


で、肝心のqsortの中身はこちら。

func qsort(list []int) []int {
    var left, right []int
    var pivot int

    if len(list) < 1 {
        return list
    }

    pivot = list[0]
    for i := 1; i < len(list); i++ {
        if list[i] < pivot {
            left = append(left, list[i])
        } else {
            right = append(right, list[i])
        }
    }

    left = qsort(left)
    right = qsort(right)

    list = append(left, pivot)
    list = append(list, right...)

    return list
}


クイックソートアルゴリズムに関する詳しい説明は省略するとして、再起している以外は非常にシンプルな中身になっています。


むしろこれで動くのかってくらい手抜きですけど、大丈夫、ちゃんと動きますしクイックソートアルゴリズムに従っています。
と言うか、ファイルからの読み込みに手間取り過ぎたので真面目に頑張る気力が尽きました。
リスト同士をappendするときは後ろに"..."を付けないといけないらしいので注意。


ソース全体としてはこんな感じ。

ファイル名:qsort.go
package main

import (
    "encoding/csv"
    "fmt"
    "os"
    "strconv"
)

const (
    filename = "list.txt"
)

func readList(filename string) []int {
    var fp *os.File
    var error error

    fp, error = os.Open(filename)
    if error != nil {
        panic(error)
    }
    defer fp.Close()

    reader := csv.NewReader(fp)
    reader.Comma = ','
    reader.LazyQuotes = true

    record, error := reader.Read()
    if error != nil {
        panic(error)
    }

    var list []int
    for i := 0; i < len(record); i++ {
        var element int
        element, error = strconv.Atoi(record[i])
        if error != nil {
            panic(error)
        }

        list = append(list, element)
    }

    return list
}

func printList(list []int) {
    fmt.Println(list)
}

func qsort(list []int) []int {
    var left, right []int
    var pivot int

    if len(list) < 1 {
        return list
    }

    pivot = list[0]
    for i := 1; i < len(list); i++ {
        if list[i] < pivot {
            left = append(left, list[i])
        } else {
            right = append(right, list[i])
        }
    }

    left = qsort(left)
    right = qsort(right)

    list = append(left, pivot)
    list = append(list, right...)

    return list
}

func main() {
    var list []int
    list = readList(filename)
    printList(list)
    list = qsort(list)
    printList(list)
}


で、実行結果は以下のとおり。

>go run qsort.go
[8 2 7 3 1 9 5 6 0 4]
[0 1 2 3 4 5 6 7 8 9] 


無事ソートができました。


そんなわけで、今日はこれまで。
それでは、ごきげんよう。