ラベル Go の投稿を表示しています。 すべての投稿を表示
ラベル Go の投稿を表示しています。 すべての投稿を表示

2009年11月14日土曜日

Google GoでFizzBuzz

新しい言語に触れるときは,ループや条件分岐が必要なのでFizzBuzzを書いてみることにしている。

switchを使ったものと配列を使ったもの、それをメソッドとして呼び出すものの2+1パターンを書いた。

package main
import "fmt"

//switchを使ってみる
func fizzbuzz1(limit int)
{
for n:=1; n<=limit; n++{
switch{
case n%15==0:
fmt.Print("FizzBuzz");
case n%5==0:
fmt.Print("Buzz");
case n%3==0:
fmt.Print("Fizz");
default:
fmt.Print(n);
}
fmt.Printf("\n");
}
}

//配列を使ってみる
func fizzbuzz2(limit int)
{
var arr [15]string =
[15]string{"Fizzbuzz","","","Fizz","","Buzz","Fizz","","","Fizz","Buzz","","Fizz","",""};
for i := 1; i <= limit; i++{
if str := arr[i%15]; len(str) == 0{
fmt.Printf("%d\n",i);
}else{
fmt.Printf("%s\n",str);
}
}
}

//メソッドらしきもの
//Hoge型
type Hoge int
func (limit Hoge)fizzbuzz_hoge()
{
fizzbuzz1(int(limit));
}

func main()
{
fmt.Printf("**fizzbuzz1**\n");
fizzbuzz1(15);
fmt.Printf("**fizzbuzz2**\n");
fizzbuzz2(15);
fmt.Printf("**fizzbuzz_hoge**\n");
//明示的にHoge型だと指定しないとintだと思われてコンパイルエラー
var hoge Hoge = 15;
hoge.fizzbuzz_hoge();
}

switchはcaseの部分に色々書ける。if-elseif-elseをswitchとして書ける、ということなのだろう。

配列の要素数は型の前に書く。配列内の""のところにnilと書こうとしたけどコンパイラに怒られた。残念。

メソッドらしきもののところは、最初は(limit int)と書いて、3.fizzbuzz_hoge()で呼び出せるようにしたかったけど、intはnon-local typeじゃないので新しいメソッドを定義できないと言われる。仕方ないのでHoge型を作って呼び出すようにした。

GoogleのGoで正規表現(regexpパッケージ)

昨日インストールしたGoで遊んでみる。とりあえず、みんな大好き正規表現を使ってみつつ、雰囲気を掴もうと試みる。

package main
import( "regexp"; "fmt"; "flag";"os")

// command regexp target-str
func main()
{
flag.Parse();
if flag.NArg() < 2{
fmt.Printf("Require 2 args(now %d): regexp, target\n",flag.NArg());
}else{
var regstr string = flag.Arg(0);
var target string = flag.Arg(1);
re,err := regexp.Compile(regstr);
if err != nil
{
fmt.Printf("error@regexp.Comile:");
fmt.Print(err);
os.Exit(0);
}
strs := re.MatchStrings(target);
if l:=len(strs); l!=0
{
//substring
fmt.Printf("Match:%s\n",strs[0]);
for i:=1; i<len(strs); i++{
fmt.Printf("Match[%d]:%s\n",i,strs[i]);
}
}
else
{
fmt.Printf("No Match\n");
}
}
return;
}

mainパッケージのmain関数がエントリポイントのようだ。

importやconst(定数宣言)など、はかっことこっかで囲むことで複数同時に宣言できる。セミコロンはあってもなくても良いらしい。

変数の宣言時には、変数名の後に型(クラス?)の名前を書く。省略も可能。

//宣言
var hoge string;
//宣言+初期化
var hoge string = "hoge"
var hoge = "hoge"
hoge := "hoge"

また、Goは多値を扱える。2つ目の返り値でエラーかどうかを判定する何かを返すことが多そうだ。

flagパッケージはコマンドライン引数を処理、fmtパッケージはフォーマット入出力、以下略。パッケージについてはgolang.orgのPackage documentationにまとめられている。

ドキュメントの関数の見方は、例えば、fmtパッケージ内で

func Printf(format string, v ...) (n int, errno os.Error)
となっていれば、関数Printfは1つ目の引数に文字列,その後に可変長で引数を取り、整数とエラーを多値で返す,ということだろう。

以下、コンパイルして実行した結果

$./8.out "hoge" "fuga"
No Match
$./8.out "hoge" "hogefugapiyo"
Match:hoge
$./8.out "(ab|cd)efg" "abefghi"
Match:abeft
Match[1]:ab

もうすこしまともにチュートリアルを読んでから書くべきか・・・

Googleのプログラミング言語Goをインストールした

巷で噂のThe Go Programming Languageをインストールした。

すんなり入ったわけじゃなかったのでメモしておく。

環境はVM上のUbuntu(x86).

実際に作業したときは環境変数を後で設定しているので、少し手順がおかしいかも。

/* 一般ユーザでの作業。ホームディレクトリにいる。 */
/* Goのコマンドを入れるディレクトリを作る */
$mkdir gobin

/* 環境変数設定 */
$export GOROOT='/home/kurohuku/util/go'
$export GOBIN='/home/kurohuku/gobin'
$export GOARCH='386'
$export GOOS='linux'
$export PATH='$PATH:/home/kurohuku/gobin'

/* hgコマンドとやらをインストールする */
$sudo apt-get install python-setuptools python-dev
$sudo easy_install mercurial

/* goを持ってくる */
$cd util/
$hg clone -r release https://go.googlecode.com/hg/ $GOROOT

/* アップデート? */
$cd go/
$hg pull
$hg update

/* コンパイル+インストール+テスト */
$cd src/
$./all.bash

/* テストが問題なければインストール終了 */

GOARCH=386と指定していると、コマンドは8g,8lなどと8が頭につくものになるようだ。

また、go/miscにcgo,emacs,vim,xcodeというディレクトリがある。一応Emacs使いなので、go-mode.elとgo-mode-load.elをマイelファイルディレクトリにコピー。設定ファイルまで用意してくれてるとは素晴らしいですね。

と、思ったらインデントが気にくわない。これがデフォってことはないだろうから私がなにかを間違えているのだろうか。

以下はチュートリアルに載っているサンプルコードの表示文字を少し変更しただけのコード.

package main

import "fmt"

func main()
{
fmt.Printf("Hello, 'go' World!\n")
}

適当なファイル(hello.go)に保存してコンパイル->実行する。

$8g hello.go
$ls
hello.go hello.8
$8l hello.8
$ls
hello.go hello.8 8.out
$./8.out
Hello, 'go' World!

/* ファイルサイズ */
$ls -l|awk '{print $5 " " $8}'
581735 8.out
5192 hello.8
83 hello.go

ちなみに、気にくわないインデントというのは、こんな感じ。

func main()
{
fmt.Printf("Hello, 'go' World!\n")
}