数値型

Go にはたくさんの数値型がある。

説明
int8 8bit整数
int16 16bit整数
int32 32bit整数
int64 64bit整数
int 32bitまたは64bit整数(処理系依存)
uint8 8bit符号なし整数
byte uint8の別名
uint16 16bit符号なし整数
uint32 32bit符号なし整数
uint64 64bit符号なし整数
uint 32bitまたは64bit符号なし整数(処理系依存)
float32 32bit単精度浮動小数点数
float64 64bit倍精度浮動小数点数
complex64 float32の実数部と虚数部をもつ複素数
complex126 float64の実数部と虚数部をもつ複素数

整数は通常10進数だけど、頭に 0 をつけると8進数、0x をつけると16進数と解釈される。

型が異なると計算できない。例えば同じ整数でも int と int64 の計算をしようとすると、次のようにエラーになる。

package main

import "fmt"

func main() {
    var a int
    var b int64

    a = 10
    b = 20

    fmt.Println(a + b)
}
^o^ > go run numbers.go
# command-line-arguments
.\numbers.go:12: invalid operation: a + b (mismatched types int and int64)

こういう場合は明示的に変換しなければならない。

package main

import "fmt"

func main() {
    var a int
    var b int64

    a = 10
    b = 20

    fmt.Println(int64(a) + b)
}
^o^ > go run numbers2.go
30

変数の宣言と初期化

変数を使うには宣言をする必要がある。変数の宣言は var 変数名 型 という形で行う。

var a int

宣言と同時に初期化もできる。この場合には型を省略できる。

var a = 10

初期化しないとゼロ値に初期化される。ゼロ値とは、数値型では 0、文字列型では空文字列、bool型では false のこと。

package main

import "fmt"

func main() {
    var a int
    var b string
    var c bool

    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}
^o^ > go run var3.go
0

false

コマンドライン引数

コマンドライン引数は C のように main 関数の引数で受け取るのではなく、os パッケージの os.Args 関数を使う。

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println(os.Args)
}
^o^ > go build args.go

^o^ > args foo  bar baz
[args foo bar baz]

os.Args の返り値は文字列の配列。最初の要素は実行ファイル名、これは C と同じだな。

import

使用するライブラリ(パッケージ)の読み込みは import 文で行う。

import "fmt"

読み込むパッケージが複数の場合、import 文を並べて書いてもいいけど、下のようにカッコで囲んで一つにしてもいい。

import (
    "fmt"
    "os"
)

こっちのほうが、読みやすいな。

はてなダイアリーからはてなブログへ

はてなダイアリーに置いてある以前の古い記事をはてなブログに移行した。特に理由があったわけではないんだけど、なんとなく。はてなブログができてずいぶん経つし、ダイアリーはいつまであるかなー、と思ったからかな。
ともかく、はてなブログへは次のリンクからアクセスできます。

 cf. Haskellはスケるよ

文字コード

Go のソースコードは UTF-8 で書くと決まっている。UTF-8 で書いてあれば、日本語も問題なく使える。たとえ Windows でも。

package main

import "fmt"

func main() {
    fmt.Println("こんにちは!")
}
^o^ > go run hello_ja_utf8.go
こんにちは!

UTF-8 以外の文字コード、例えば Shift JIS で書くと次のようにエラーになる。

^o^ > go run hello_ja_sjis.go
# command-line-arguments
.\hello_ja_sjis.go:6: invalid UTF-8 encoding

Hello, world!

気が付けば今月も20日を過ぎている。まずいな。
まあ、いい。日にちが開いてしまってけど、ちょっとずつ Go をやっていこう。

今日は定番の Hello, world プログラムを作った。

package main

import "fmt"

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

Go のプログラムはパッケージから構成される。package 文で宣言する。ここでは main という名前でパッケージを作っている。
Go のプログラムは main パッケージの main 関数がエントリポイントになる。だからプログラムのパッケージ名は main で、main という名前の関数がなければいけない。
関数の定義は func 関数名 で行う。上の例では main 関数だけがある。
import 文は、ライブラリの読み込み。ライブラリ(パッケージ)名をクォートでくくって指定する。ここでは出力のために fmt パッケージを読み込んでいる。
そして、fmt.Println 関数が標準出力への出力。引数の文字列に改行をつけて出力する。

じゃあ、実行してみよう。

^o^ > go run hello.go
Hello, world!

今日はここまで。

Go言語のインストール

気が付けば夏休みも最終日だ。このままでは今月ブログの更新なしになってしまうところだ。
大したネタもないので、Go 言語のインストールのことでも書いておこう。ダウンロードはここから。

 cf. https://golang.org/dl/

Windows 用には msi インストーラがあるので、それをダウンロードして実行するだけ。すごく簡単。

Go言語に手を出した

Elixir は先月うまくいかなくてめげてしまったので、ここ最近は Go 言語に手を出している。ま、Web ページを見ながら見様見真似でやってるんだけど、言語の雰囲気はなんとなくわかったってところかな。OS ネイティブの実行ファイルが作れるのはいいね。ツールを作って他人に配るのにはいい。goroutine はよくわかんない。

で、ちょっと整数の素因数分解をするプログラムを作ってみた。

package main

import (
    "fmt"
    "os"
    "flag"
    "strconv"
)

func primes(n int) []int {
    p := make([]bool, n + 1)
    // スライス p はゼロ値(false)で初期化されるので、2 と 3 以上の奇数だけ true に初期化する。
    if 2 < n {
        p[2] = true
        for i := 3; i <= n; i += 2 {
            p[i] = true
        }
    }
    // 3 以上の奇数を順にふるいにかける。
    for i := 3; i * i < n; i += 2 {
        if p[i] {
            for j := i + i; j <= n; j += i {
                p[j] = false
            }
        }
    }
    // 素数だけ pn に追加。
    pn := make([]int, 0)
    for i := 2; i <= n; i++ {
        if p[i] {
            pn = append(pn, i)
        }
    }
    return pn
}

func primeFactors(n int) []int {
    // n が合成数だと仮定すると、可能性として考えられる最大の素因数は n/2。
    ps := primes(n / 2)
    // n/2 以下の素数の中から素因数を探す。
    facts := make([]int, 0)
    for _, p := range ps {
        for n != 1 {
            if n % p == 0 {
                facts = append(facts, p)
                n = n / p
            } else {
                break
            }
        }
    }
    // n/2 までに素因数が見つからない場合、n 自身が素数。
    if len(facts) == 0 {
        facts = append(facts, n)
    }
    return facts
}

func main() {
    Usage := func() {
        fmt.Fprintf(os.Stderr, "Usage: %s \n", os.Args[0])
    }
    opt_help := flag.Bool("h", false, "Help message")
    flag.Parse()

    if *opt_help || flag.NArg() < 1 {
        Usage() os.Exit(0)
    }
    n, err := strconv.Atoi(flag.Arg(0))
    if err != nil {
        fmt.Fprintln(os.Stderr, "Invalid argument.")
        os.Exit(1)
    }
    if n < 2 {
        fmt.Println("Nothing prime factors.")
    } else {
        f := primeFactors(n)
        s := fmt.Sprintf("%v", f)
        l := len(s) fmt.Println(s[1:l-1])
    }
}

コンパイルせずにそのまま実行するには go run コマンド。

^o^ > go run primefactors.go 12345
3 5 823

コンパイルするには go build コマンド。

^o^ > go build primefactors.go

^o^ > ls
primefactors.exe  primefactors.go

^o^ > primefactors 12345
3 5 823