Go言語

Go言語のインストールの不具合(2010年1月31日)

今日(2010年1月31日)、Ubuntu9.04にGo言語をインストールしようとしたところ、

yerr.h:17: error: ‘loadsys’ undeclared here

というエラーが出てインストールできないことがわかった。

golang-nutsを調べたところ、
1月29日, 午後5:40のRuss Coxさんの記事に、

Instead of ./all.bash try LANG=C ./all.bash.
Sorry for the trouble.  This will be fixed in the
next release.

という記述を発見した。
この通りにやってみてインストールに成功した。

★WOZ★

| | コメント (0) | トラックバック (0)

Go言語のforループ

Go言語のforループには次の3つの形式がある。

// Like a C for
for init; condition; post {}

// Like a C while
for condition {}

// Like a C for(;;)
for {}

一つ目の形式のサンプルだ。
この形式はC言語プログラマも馴染みやすい。
//
package main

func main() {
        sum := 0;
        for i := 0; i < 10; i++ {
                sum += i
        }
        println(sum)
}
//

二つ目の形式のサンプルだ。
forがwhileだと思えば、問題なし。
//
package main

func main() {
        sum := 0
        i := 0
        for i < 10 {
                sum += i
                i++
        }
        println(sum)
}
//

三つ目の形式のサンプルだ。
これはCプログラマには違和感があるだろう。
//
package main

func main() {
        sum := 0;
        a := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

        for _, i := range a {
                sum += i
        }
        println(sum)
}
//
しかし、この3つ目の形式もリスト処理になれているPythonプログラマなら問題なしだ。
//
#!/usr/bin/env python
# -*- coding: utf-8 -*-

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

sum = 0
for i in a:
        sum += i

print sum
//

Go言語は、C言語の良いところとPython言語の良いところをうまく持ち合わせていると思う。

★WOZ★

| | コメント (0) | トラックバック (0)

Go言語の関数リテラル(function literals)

関数リテラル(function literals)は匿名関数のことで、Go言語では例えば次のように使う。

f := func(x, y int) int { return x+y }

関数リテラルはgo文と一緒に使うと便利だ。

★WOZ★
//
package main

func main() {

        c := make(chan int)
        var g int
        go func(i int, c chan int) {
                s := 0
                for j := 0; j < i; j++ { s += j }
                g = s

                c <- 1
        } (10, c)

        <- c
        println(g)
}
//
(Go for C++ Programmersより)

| | コメント (0) | トラックバック (0)

Go言語で並行処理の待ち合わせを書いてみた

Go言語のgoroutineとchannelを使うと、並行処理の待ち合わせを簡単に書ける。

10個の並行処理を生成して、それらが全て終わったのを待って、10個の平行処理の結果を使って何かの処理をする、という場合だと次のように書けば良い。

  1. 並行処理の呼び出し側で、待ち合わせ用のバッファなしチャンネルを一つ作って、そのチャンネルを並行処理を起動するときに渡す。
  2. それぞれの並行処理処理は、自分の計算が終わったら、そのチャンネルに完了通知を送る。
  3. 並行処理の呼び出し側では、全ての並行処理から完了通知を受け取ったら、次の処理に移る。

★WOZ★

//コードここから
package main

const NumberOfProc = 10

func myfunc(i int, c chan int) {
        println(i)
        c <- 1
}

func main() {
        c := make(chan int)

        for i := 0; i < NumberOfProc; i++ {
                go myfunc(i, c)
        }

        for i := 0; i < NumberOfProc; i++ {
                <-c
        }
        println("all done")
}      
//ここまで

| | コメント (0) | トラックバック (0)

Go言語の最新リリース(2009年12月22日版)を使ってみた

2009年12月22日にGo言語の新しいリリースが公開されていた。
Go言語は構成管理ツールにMarcurialを使っているので、次のコマンドでGoogleのリポジトリと同期できる。

$ hg pull
$ hg update release

今回のリリースではセミコロンを省略できるケースが大幅に増えているようだ。
例えば以前のバージョンの場合、文と文の間はセミコロンで区切る必要があった。

//以前のバージョン
package main

import "fmt"

func main() {
        fmt.Printf("hello world\n");
        fmt.Printf("こんにちは\n")
}
//ここまで

12月22日のバージョンでは、次のようにセミコロンを省略できる。

//新しいバージョン
package main

import "fmt"

func main() {
        fmt.Printf("hello world\n")  //ここのセミコロンが不要
        fmt.Printf("こんにちは\n")
}
//ここまで

この改良はうれしい。
見た目もすっきりするし、セミコロンのつけ忘れでコンパイルエラーになることもなくなるので、思考を中断することなくコーディングできそうだ。

★WOZ★

| | コメント (0) | トラックバック (0)

Go言語のfor文

Goではコレクションを処理するのにforとrangeを使う。
例えば、配列[1, 2, 3, 4, 5]の和を求めるコードは次のように書く。

//コードここから
package main

var col =[...]int {1, 2, 3, 4, 5}

func main() {
        sum := 0;
        for _, value := range col {
                sum += value
        }      
        println(sum)
}
//ここまで

ちなみに、同じ処理をPythonなら次のように書く。
Pythonのコレクション処理に慣れていれば、Goのコレクション処理に違和感はないだろう。

//コードここから
col = [1, 2, 3, 4, 5]
sum = 0
for i in col:
    sum += i

print sum
//ここまで

★WOZ★

| | コメント (0) | トラックバック (0)

Go言語の型変換(Conversions)

12月20日のブログでは、次のようなコードを書いた。

type Sequence []int
func (s Sequence) String() string {
        sort.Sort(s);
        str := "[";
        for i, elem := range s {
                if i > 0 {
                        str += " "
                }
                str += fmt.Sprint(elem)
        }
        return str + "]"
}

しかし、実はSequence型を[]int型に変換すると、このメソッドを簡潔に書くことができる。(コード1参照)

func (s Sequence) String() string {
        sort.Sort(s);
        return fmt.Sprint([]int(s))
}

さらに、ソートする前にSequence型をsort.IntArray型に変換すると、sort.IntArray型が、

  • Len() int
  • Less(i, j int) bool
  • Swap(i, j int)

を実装しているので、Sequence型はそれらのインタフェースを実装する必要もなくなり、コードが簡単になる。(コード2参照)

func (s Sequence) String() string {
    sort.IntArray(s).Sort();
    return fmt.Sprint([]int(s))
}

★WOZ★

にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村

//コード1ここから
package main

import (
        "sort";
        "fmt"
)

type Sequence []int
func (s Sequence) Len() int {
        return len(s)
}
func (s Sequence) Less(i, j int) bool {
        return s[i] < s[j]
}
func (s Sequence) Swap(i, j int) {
        s[i], s[j] = s[j], s[i]
}

func (s Sequence) String() string {
        sort.Sort(s);
        return fmt.Sprint([]int(s))
}

func main() {
        var seq Sequence = &[...]int{5, 2, 1, 3, 4};
        str := seq.String();

        println(str);
}
//ここまで

//コード2ここから
package main

import (
    "sort";
    "fmt"
)

type Sequence []int

func (s Sequence) String() string {
    sort.IntArray(s).Sort();
    return fmt.Sprint([]int(s))
}

func main() {
    var seq Sequence = &[...]int{5, 2, 1, 3, 4};
    str := seq.String();

    println(str);

}
//ここまで

| | コメント (0) | トラックバック (0)

Go言語のインタフェース

Go言語の型(type)は複数のインタフェースを実装することができる。
例えば、int型の要素をソートしてから出力するコレクション型を考える。

type Sequence []int

まず、このSequence型は、コレクションの要素をsortパッケージの機能でソートするために、sort.Interfaceを実装しなければならない。

func (s Sequence) Len() int {
        return len(s)
}
func (s Sequence) Less(i, j int) bool {
        return s[i] < s[j]
}
func (s Sequence) Swap(i, j int) {
        s[i], s[j] = s[j], s[i]
}

次に、出力用のStringメソッドを実装する。これはSequence型に固有のインタフェースだ。

func (s Sequence) String() string {
        sort.Sort(s);
        str := "[";
        for i, elem := range s {
                if i > 0 {
                        str += " "
                }
                str += fmt.Sprint(elem)
        }
        return str + "]"
}

このように、sort.Interfaceの3つのメソッド

  • Len() int
  • Less(i, j int) bool
  • Swap(i, j int)

と、独自のメソッド

  • String() String

とを実装することにより、コレクションの要素をソートしてから出力するSequence型を作ることができた。
(Effective Goより抜粋)

★WOZ★

にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村

//コードここから
package main

import (
        "sort";
        "fmt"
)

type Sequence []int
func (s Sequence) Len() int {
        return len(s)
}
func (s Sequence) Less(i, j int) bool {
        return s[i] < s[j]
}
func (s Sequence) Swap(i, j int) {
        s[i], s[j] = s[j], s[i]
}

func (s Sequence) String() string {
        sort.Sort(s);
        str := "[";
        for i, elem := range s {
                if i > 0 {
                        str += " "
                }
                str += fmt.Sprint(elem)
        }
        return str + "]"
}

func main() {
        var seq Sequence = &[...]int{5, 2, 1, 3, 4};
        str := seq.String();

        println(str);
}
//ここまで

| | コメント (0) | トラックバック (0)

Go言語のgoroutine間の同期(4)

Go言語は、syncパッケージに含まれるロックデータ型sync.Mutexを使って簡単にgoroutine間の同期をとることができる。

それは、あるsync.Mutex型の変数lに対して、n回目のl.Unlock()は、必ずm回目のl.Lockが終わる前に起こる、というルールがあるためである。(ただし、n ≦ m)

例えば、下のコードでは、関数fの中のl.Unlock()は、関数mainの中の2回目のl.Lock()が終わる前に終わるので、”hello, world"が表示されることが保証される。

channelを使う同期と同様に、sync.Mutexを使う同期も、他の言語と比べて簡単かつ安全に書くことができる。

★WOZ★

//コードここから
package main

import (
        "sync"
)

var l sync.Mutex
var a string

func f() {
        a = "hello, world";
        l.Unlock();
}

func main() {
        l.Lock();
        go f();
        l.Lock();
        println (a);
}
//ここまで

にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村

| | コメント (0) | トラックバック (0)

Go言語のgoroutine間の同期(3)

Go言語のchannelを使うと、ある処理をバックグランドで起動しておいて、その処理が完了するのを、起動元が待ち合わせるという処理が、簡単に書ける。
channelにはSenderとReceiverがあり、またchannelにはバッファありとバッファなしがある。
バッファなしのchannelの場合、Receiverは受信データが来るまで、つまりSenderがデータ送信を完了するまで、処理を先に進めずに待っている。

下のコードは、そのchannelの機能とgoroutineを使って書いた、バックグランドでソート処理を起動し、そのソート処理が終わるのを起動元が待ち合わせるサンプルプログラムだ。
Go言語はこのような並行処理を実に簡単に安全に書ける。

★WOZ★

//コードここから

package main
import (
        "fmt";
        "sort"
)

func sortTest(s []int) {
        c := make(chan int);
       
        go func() {
                sort.SortInts(s);
                c <- 0;
        }();

        <-c;
}

func main() {
        s := make([]int, 10);
        a := [...]int{1, 5, 4, 2, 3};
        s = &a;
       
        sortTest(s);

        for i := 0; i < len(s); i++ {
                fmt.Println(s[i])
        }
}
//ここまで
ブログランキング・にほんブログ村へ
にほんブログ村

| | コメント (0) | トラックバック (0)

より以前の記事一覧