M.Hiroi's Home Page

Go Language Programming

お気楽 Go 言語プログラミング入門

[ PrevPage | Golang | NextPage ]

Go 言語の基礎知識 (2)

前回は Go 言語の基本として、数と文字列、if 文と for 文について説明しました。今回は配列とスライス (slice)、連想配列 (map) について説明します。

●配列

Go 言語の「配列 (array)」はデータを一列に並べたもので、C言語やC++ の 1 次元配列と同じデータ構造です。配列に格納されたデータを要素といいます。

配列はホテルやマンションの部屋にたとえるとわかりやすいと思います。ホテル全体を配列とすると、各部屋がデータを格納する変数と考えることができます。ホテルでは、ルームナンバーによって部屋を指定しますね。配列の場合も、整数値によってデータを格納する変数を指定することができます。この整数値を「添字 (subscripts)」といいます。


                  図 : 配列の構造

たとえば、10 個のデータを格納する配列を考えてみます。これは、平屋建てのホテルで、部屋が 10 室あると考えてください。この場合は上図に示すように、データを格納する変数が並んでいて、それぞれ 0 から 9 までの添字で指定することができます。Go 言語の場合、C言語や Java と同じく、添字は 0 から順番に数えます。

Go 言語の配列は次のように宣言します。

var 変数名 [大きさ]型
var 変数名 [大きさ]型 = [大きさ]型{初期値1, ..., 初期値n} 

変数名の後ろの [大きさ] で配列の大きさを指定して、その後ろの型で配列に格納する要素の型を指定します。配列の型は "[大きさ]型" で表します。大きさが異なる配列は、要素の型が同じ場合でも異なる型になります。次の例を見てください。

var a [4]int
var b [8]int

配列 a の型は [4]int で、配列 b の型は [8]int です。大きさが異なるので、a と b は異なる型となります。

要素の初期値は型によって決まります。数値の場合は 0 に、bool の場合は false に初期化されます。Go 言語の場合、この値を「ゼロ値」と呼びます。初期値を設定したい場合は {初期値1, ..., 初期値n} で要素の値を指定します。型と値の型が一致しないとコンパイルエラーになります。

一般に、スクリプト言語の多くは配列の大きさを自由に変えることができる「可変長配列」をサポートしています。ところが、Go 言語の配列はC言語や Java と同様にあとから大きさを変更することはできません。そのかわり、Go 言語には「スライス (slice)」という型が用意されています。スライスは配列を使って実装されたデータ構造で、Go 言語では配列よりもスライスを多用するようです。スライスはあとで詳しく説明します。

簡単な例を示しましょう。

リスト : 配列の使用例 (sample21.go)

package main

import "fmt"

func main() {
    var a [4]int
    b := [...]int{1, 2, 3, 4, 5, 6, 7, 8} 
    // var b [8]int = [8]int{1, 2, 3, 4, 5, 6, 7, 8}
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(len(a))
    fmt.Println(len(b))
    fmt.Println(a[0])
    fmt.Println(b[0])
    a[0] = 10
    b[0] = 20
    fmt.Println(a)
    fmt.Println(b)
}
$ go run sample21.go
[0 0 0 0]
[1 2 3 4 5 6 7 8]
4
8
0
1
[10 0 0 0]
[20 2 3 4 5 6 7 8]

配列の要素は角カッコ [ ] を使ってアクセスします。これはC言語や Java と同じです。配列の要素を取り出して変数に代入することも、配列の要素を書き換えることもできます。配列は自分自身の大きさを知っていて、関数 len で大きさを求めることができます。

配列を局所変数として使用する場合は := を使って簡単に定義することができます。初期値を指定する場合、配列の大きさに ... を指定すると、コンパイラが初期値の要素数を数えて配列の大きさを決定します。

●多次元配列

配列は入れ子にすることができます。つまり、配列の要素に配列を入れてもかまいません。これで多次元配列を表すことができます。

簡単な例を示しましょう。

リスト : 2 次元配列 (sample22.go)

package main

import "fmt"

func main() {
    var a [3][3]int
    b := [3][3]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }
    // var b [3][3]int = [3][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(len(a))
    fmt.Println(len(b))
    fmt.Println(a[0][0])
    fmt.Println(b[2][2])
    a[0][0] = 10;
    b[2][2] = 20;
    fmt.Println(a)
    fmt.Println(b)
}
$ go run sample22.go
[[0 0 0] [0 0 0] [0 0 0]]
[[1 2 3] [4 5 6] [7 8 9]]
3
3
0
9
[[10 0 0] [0 0 0] [0 0 0]]
[[1 2 3] [4 5 6] [7 8 20]]

多次元配列は [ ] を複数付けることで宣言します。2 次元配列の場合、var a [3][3] int のように [ ] を 2 つ付けて指定します。これで配列 a の大きさは 3 で、その要素は大きさ 3 の配列になります。また、初期値を指定する場合は、{ } の中で {1, 2, 3} のように初期値付きで要素を指定します。これで 2 次元配列を初期化することができます。

要素のアクセスは簡単で、最初の [ ] で配列に格納されている配列を取り出し、次の [ ] で取り出した配列の要素を指定します。たとえば、b[2][2] は b[2] に格納されている配列 {7, 8, 9} を取り出し、次の [2] でその配列の 2 番目の要素を指定します。したがって、b[2][2] の値は 9 になります。b[2][2] = 20 とすると 9 が書き換えられて 20 になります。

●配列の代入

配列 a, b の型が一致している場合、a = b で配列を代入することができます。このとき、b の要素は a にコピーされます。次の例を見てください。

リスト : 配列の代入 (sample23.go)

package main

import "fmt"

func main() {
    var a [8]int
    b := [8]int{1,2,3,4,5,6,7,8}
    fmt.Println(a)
    fmt.Println(b)
    a = b
    fmt.Println(a)
    fmt.Println(b)
    c := b
    fmt.Println(c)
}
$ go run sample23.go
[0 0 0 0 0 0 0 0]
[1 2 3 4 5 6 7 8]
[1 2 3 4 5 6 7 8]
[1 2 3 4 5 6 7 8]
[1 2 3 4 5 6 7 8]

配列 a, b は同じ型です。a は 0 クリアされていて、b は {1,2,3,4,5,6,7,8} で初期化されています。a = b とすると、a は [1 2 3 4 5 6 7 8] になり、b の要素がコピーされていることがわかります。c := b も同じです。配列の領域が確保されて、そこに b の要素がコピーされます。

●定数

Go 言語は const で定数を宣言することができます。定数として定義できるのは数値、文字列、真偽値だけです。

const 名前 型 = 値

const (
    名前1 型1 = 値1
    名前2 型2 = 値2
      .....
    名前n 型n = 値n
)

値が数値の場合、型を省略すると整数は int に、浮動小数点数は float64 になります。値が型の範囲内に収まらない場合はコンパイルエラーになります。const のカッコの中で値を省略すると、一つ前の値がそのまま適用されます。

連続した値を定義したい場合は iota を使うと便利です。

const (
    foo = iota   // foo = 0
    bar          // bar = 1
    baz          // bar = 2
)

const の中で iota が使用されると、最初は 0 に初期化され、次からは +1 した値を返します。foo = iota の場合、const の中で iota が最初に使われているので値は 0 になります。bar は値が指定されていないので、ひとつ前の値 iota が適用されます。したがって、bar の値は 1 になり、baz の値は 2 になります。

●素数を求める

それでは簡単な例題として、100 以下の素数を求めるプログラムを作ってみましょう。いちばん簡単な方法は、奇数 3, 5, 7, 9, ... をそれまでに見つけた素数で割ってみることです。見つけた素数は配列に格納しておけばいいでしょう。プログラムは次のようになります。

リスト : 素数を求める (prime.go)

package main

import "fmt"

func main(){
    var primeTable [100]int
    primeTable[0] = 2
    primeSize := 1
    for n := 3; n <= len(primeTable); n += 2 {
        isPrime := true
        for i := 1; i < primeSize; i++ {
            p := primeTable[i]
            if p * p > n { break }
            if n % p == 0 {
                isPrime = false
                break
            }
        }
        if isPrime {
            primeTable[primeSize] = n
            primeSize++
        }
    }
    for i := 0; i < primeSize; i++ {
        fmt.Print(primeTable[i], " ")
    }
    fmt.Print("\n")
}
$ go run prime.go
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

変数 primeTable は素数を格納する配列で 0 番目の要素を 2 に初期化します。変数 primeSize は格納されている素数の個数を表します。変数 n を 3 に初期化して、for ループで n の値を 2 ずつ増やしていきます。これで奇数列を生成することができます。

このプログラムのポイントは変数 isPrime の使い方です。for ループの先頭で isPrime を true に初期化します。次の for ループで、primeTable に格納されている素数を取り出し、変数 p にセットします。n は奇数なので、2 で割り算する必要はありません。primeTable の 1 番目の要素から順番に primeSize - 1 番目までの要素を調べます。

n が素数か判別する場合、実際には primeTable の素数をすべて調べる必要はなく、√n より小さい素数を調べるだけで十分です。p > √n のかわりに p * p > n をチェックし、真であれば break で for ループを脱出します。n % p が 0 ならば、isPrime を false にセットしてから break します。

そして、for ループが終了した後、isPrime が true であれば n を primeTable に追加して、primeSize の値を +1 します。これで、primeTable の先頭から順番に素数を格納していくことができます。最後に for ループで求めた素数を表示します。

ところで、prime.go のプログラムはちょっとわかりにくいのが欠点です。この場合、関数を使うとわかりやすいプログラムを作ることができます。

●エラトステネスの篩

もう一つ、素数を求める簡単な方法を紹介しましょう。最初に、2 から N までの整数列を生成します。先頭の 2 は素数なので、この整数列から 2 で割り切れる整数を取り除き除きます。2 で割り切れる整数が取り除かれたので、残った要素の先頭が素数になります。先頭要素は 3 になるので、今度は 3 で割り切れる整数を取り除けばいいのです。このように、素数を見つけたらそれで割り切れる整数を取り除いていくアルゴリズムを「エラトステネスの篩 (ふるい)」といいます。

プログラムは次のようになります。

リスト : エラトステネスの篩 (sieve.go)

package main

import "fmt"

func main() {
    var primes [100]bool
    for n := 2; n < len(primes); n++ {
        if primes[n] { continue }
        for m := 2 * n; m < len(primes); m += n {
            primes[m] = true
        }
        fmt.Print(n, " ")
    }
    fmt.Print("\n")
}
$ go run sieve.go
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

bool 型の配列 primes で整数列を表します。false で素数を表し、素数でない場合は true をセットします。bool 型の配列は false で初期化されるので、最初はすべての数が素数ということになります。次に、for ループで primes から素数 n を探します。n = 2 の場合、primes[n] は false なので n は素数になります。primes[n] が true の場合は continue で for ループの更新処理へ移ります。

n が素数の場合は、次の for ループで primes から n の倍数を取り除きます。変数 m を 2 * n に初期化し、for ループの更新処理で m に n を加算していけば、m の値は n の倍数になります。あとは primes[m] に true をセットして、素数 n を表示するだけです。

なお、このプログラムは改善の余地があります。奇数だけを調べるように工夫すると、配列の大きさを半分にすることができ、実行時間も速くなるでしょう。興味のある方はプログラムを改造してみてください。

●スライス (slice)

スライスは配列の部分列を簡単に取り出すことができるデータ構造です。スライスは次のように宣言します。

var 変数名 []型
var 変数名 []型 = []型{初期値1, ..., 初期値n} 

配列の宣言と違って、スライスは [ ] の中に大きさを指定しません。スライスの型は "[]型" で表します。初期値を指定しない場合、スライスは nil という値に初期化されます。ここでは、nil は空を表す特別なデータと考えてください。

スライスは配列にスライス操作を適用することでも生成することができます。スライス操作は配列やスライスから部分列を取り出す操作です。下表にスライス操作を示します。

表 : スライス操作
操作意味
S[start:end] start から end - 1 まで
S[start:] start から最後尾まで
S[:end] 先頭から end - 1 まで
S[:] 先頭から最後尾まで

S はスライスまたは配列を表します。start と end で部分列を指定します。start の位置の要素が部分列の先頭になり、end - 1 の要素が最後尾になります。start が省略されると先頭 (0) に、end が省略されると len(S) に設定されます。どちらも省略すると S[0:len(S)] と同じになります。

簡単な例を示します。

リスト : スライス (sample24.go)

package main

import "fmt"

func main() {
    a := [4]int{1, 2 ,3, 4}
    b := []int{1, 2, 3, 4, 5, 6, 7, 8}
    c := a[:]
    d := b[2:6]
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
    c[0] = 10
    d[0] = 100
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
}
$ go run sample24.go
[1 2 3 4]
[1 2 3 4 5 6 7 8]
[1 2 3 4]
[3 4 5 6]
[10 2 3 4]
[1 2 100 4 5 6 7 8]
[10 2 3 4]
[100 4 5 6]

スライス操作は元のスライス (配列) の本体を共有することに注意してください。配列 a からスライス c を作成した場合、c[0] のアクセスは a[0] のアクセスと同じになります。また、スライス d は b[2:6] から生成されたので、d[0] は b[2] のアクセスと同じになります。したがって、c[0] を 10 に、d[0] を 100 に書き換えると、a[0] も 10 に、b[2] も 100 に書き換えられます。

スライスは、配列本体を指し示すポインタ (ptr)、配列の長さ (len)、配列の容量 (cap) を保持したデータ構造です。len と cap は関数 len, cap で求めることができます。次の図を見てください。

配列 a からスライス c を生成すると、c の ptr は配列 a の先頭に、len はスライス操作で指定した部分列の長さ 4 に、cap は a の大きさ 4 になります。

スライス b を生成した場合、まず配列本体が確保されて、b の ptr は配列の先頭に、len は要素数に、cap は配列の大きさになります。次に、b[2:6] でスライス d を生成します。d の ptr は配列本体の 2 番目に、len は部分列の長さ 4 に、cap は 2 番目の位置から最後までの 6 になります。

スライス s において、len(s) < cap(s) ならば、len を cap(s) まで増やすことができます。ただし、cap(s) よりも大きくすることはできません。たとえば、上図で e := d[:cap(d)] とすると、e は [3 4 5 6 7 8] と表示されます。

●make と append

このほかに、スライスは組み込み関数 make を使って生成することができます。

slice = make(type, len, [cap])

type にはスライスの型、len は配列の長さ、cap は配列の容量を指定します。cap を省略すると、容量は len と同じになります。配列の要素はゼロ値に初期化されます。

簡単な使用例を示します。

リスト : make の使用例 (sample25.go)

package main

import "fmt"

func main() {
    a := make([]int, 10, 20)
    fmt.Println(a)
    fmt.Println(len(a))
    fmt.Println(cap(a))
}
$ go run sample25.go
[0 0 0 0 0 0 0 0 0 0]
10
20

スライスに要素を追加したい場合は組み込み関数 append を使うと簡単です。

newSlice = append(slice, x1, ..., xn)

append はスライスの最後尾にデータ x1, ..., xn を追加します。配列本体の容量が足りない場合、append は容量を増やした新しい配列を確保します。このとき、元の配列からデータがコピーされます。append は新しいスライスを返すことに注意してください。

簡単な使用例を示します。

リスト : append の使用例 (sample26.go)

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4}
    for i := 5; i <= 10; i++ {
        a = append(a, i)
        fmt.Println(a)
        fmt.Println(len(a))
        fmt.Println(cap(a))
    }
}
$ go run sample26.go
[1 2 3 4 5]
5
8
[1 2 3 4 5 6]
6
8
[1 2 3 4 5 6 7]
7
8
[1 2 3 4 5 6 7 8]
8
8
[1 2 3 4 5 6 7 8 9]
9
16
[1 2 3 4 5 6 7 8 9 10]
10
16

append はデータを配列末尾に追加して、len を +1 した新しいスライスを返します。容量が足りなくなったら、新しい配列を確保するので、cap の値が増えていることがわかります。

●スライスの代入

スライス a と b の型が一致している場合、スライスを a = b で代入することができます。このとき、配列とは違って配列本体の要素はコピーされないことに注意してください。代入時にコピーされるのはスライスの構造 (prt, len, cap) だけです。次の例を見てください。

リスト : スライスの代入 (sample27.go)

package main

import "fmt"

func main() {
    var a []int
    b := []int{1,2,3,4,5,6,7,8}
    a = b
    fmt.Println(a)
    fmt.Println(b)
    a[0] = 10
    b[7] = 80
    fmt.Println(a)
    fmt.Println(b)

    a = append(a, 100)
    fmt.Println(a)
    fmt.Println(b)
    a[0] = 200
    fmt.Println(a)
    fmt.Println(b)
}
$ go run sample27.go
[1 2 3 4 5 6 7 8]
[1 2 3 4 5 6 7 8]
[10 2 3 4 5 6 7 80]
[10 2 3 4 5 6 7 80]
[10 2 3 4 5 6 7 80 100]
[10 2 3 4 5 6 7 80]
[200 2 3 4 5 6 7 80 100]
[10 2 3 4 5 6 7 80]

変数 a の型は []int で、b の型も同じ []int です。a = b と代入すれば、a からも b の配列本体にアクセスすることができます。当然ですが、a[0] の値を書き換えると、b の値も変化します。同様に、b[7] の値を書き換えると a の値も変化します。

ただし、append で要素を追加したときに新しい配列が割り当てられると、a と b で参照している配列本体が異なることになります。この場合、a[0] の値を 200 に書き換えても、b の値は同じままになります。

●文字列のスライス

スライス操作は文字列にも適用することができます。ただし、文字列のスライスが生成されるのではなく、取り出した部分列は通常の文字列になります。

簡単な例を示しましょう。

リスト : 文字列のスライス操作 (sample28.go)

package main

import "fmt"

func main() {
    var a = "1234567890"
    for i := 0; i <= len(a); i++ {
        var s string = a[i:]
        fmt.Println(s)
        fmt.Println(len(s))
    }
}
$ go run sample28.go
1234567890
10
234567890
9
34567890
8
4567890
7
567890
6
67890
5
7890
4
890
3
90
2
0
1

0

●多重代入

演算子 = の左辺がカンマで区切られいる場合、複数の代入を一度で行うことができます。これを「多重代入」といいます。

簡単な例を示しましょう。

リスト : 多重代入 (sample29.go)

package main

import "fmt"

func main() {
    var a, b int
    c := make([]int, 4)
    a, b = 10, 20
    c[0], c[1], c[2], c[3] = 10, 20, 30, 40
    fmt.Println(a, b)
    fmt.Println(c)
    a, b = b, a
    fmt.Println(a, b)
    c[0], c[3] = c[3], c[0]
    fmt.Println(c)
}
$ go run sample29.go
10 20
[10 20 30 40]
20 10
[40 20 30 10]

変数 a と b に 10 と 20 を代入しています。また、スライス (配列) にも多重代入することができます。a と b の値を交換したり、配列の要素を交換することも多重代入を使えば簡単に行うことができます。

●連想配列 (マップ, map)

配列が整数値を使って要素を指定するのに対し、連想配列はキー (key) というデータを使って要素を指定するデータ構造です。Go 言語では「マップ (map)」と呼びます。他のプログラミング言語、たとえば Python では辞書 (dictionary)、Ruby ではハッシュ (hash) と呼ばれています。 一般に、連想配列のキーには文字列が用いられますが、Go 言語では比較演算子 (==, !=) で等値を判定できるデータであればキーとして用いることができます。

マップは次のように宣言します。

var 変数名 map[key]value
var 変数名 map[key]value = map[key]value{key1: value1, key2: value2, ..., key2: valuen}

map の後ろの [ ] にキーの型を、その後ろに値の型を指定します。初期値を指定しない場合、変数は nil (nil マップ) に初期化されます。ただし、nil マップは要素を格納することができません。初期値は { } の中に記述します。このとき、キーの後ろにはコロン (:) を付けて値と区別します。要素のアクセスは配列と同じく角カッコ [ ] を使います。

簡単な例を示しましょう。

リスト : マップの使用例 (sample2a.go)

package main

import "fmt"

var a map[string]int = map[string]int{"foo": 10, "bar": 20}

func main() {
    fmt.Println(a)
    fmt.Println(len(a))
    fmt.Println(a["foo"])
    a["foo"] = 100
    fmt.Println(a["foo"])
    a["baz"] = 30
    fmt.Println(a["baz"])
    fmt.Println(a)
    fmt.Println(len(a))
}
$ go run sample2a.go
map[bar:20 foo:10]
2
10
100
30
map[bar:20 baz:30 foo:100]
3

最初に、マップを生成して変数 a にセットします。a["foo"] でキー "foo" のデータを取り出したり、そこにデータを代入すれば、a["foo"] の値を書き換えることができます。また、新しいキー "baz" を追加する場合は、a["baz"] に値を代入すると、ハッシュに "baz" とその値が追加されます。マップの要素数は組み込み関数 len で求めることができます。

このほかにも、マップを操作する便利な関数が用意されています。

var 変数 マップ型 = make(マップ型)

空のマップは組み込み関数 make で生成することができます。

マップからキーとその値を削除するには組み込み関数 delete を使います。

delete(マップ, キー)

角カッコ [ ] で値を求めるとき、キーの有無を判定することができます。

value, ok = マップ[キー]

角カッコでマップから値を取り出すと 2 つの値を返します。それを 2 つの変数 value, ok で受け取ります。キーが見つかった場合、value には値、ok には true がセットされます。キーが見つからない場合、value には値のゼロ値、ok には false がセットされます。

値が不要の場合はブランク識別子 (アンダーライン(_)) を使うことができます。ブランク識別子を使うと、値を代入せずに破棄することができます。キーの有無が知りたい場合は _, ok = マップ[キー] として ok の値を調べればよいでしょう。

簡単な例を示します。

リスト : マップの使用例 (sample2b.go)

package main

import "fmt"

func main() {
    a := make(map[string]int)
    a["foo"] = 10
    a["bar"] = 20
    a["baz"] = 30
    fmt.Println(a)
    delete(a, "baz")
    v, ok := a["baz"]
    fmt.Println(v)
    fmt.Println(ok)
    fmt.Println(a)
}
$ go run sample2b.go
map[bar:20 baz:30 foo:10]
0
false
map[bar:20 foo:10]

●for 文の range 節

一般に、複数の要素を格納するデータ構造を「コレクション (collection)」とか「コンテナ (container)」と呼びます。これまでに説明した配列、スライス、マップはコレクションになります。for 文は range 節でコレクションを指定すると、コレクションから順番に要素を取り出して変数に代入し、ブロックに書かれている処理を繰り返し実行します。

for k, v := range コレクション {
    処理A
    ...
    処理Z
}

      図 : for 文の range 節

配列とスライスの場合、k には添字、v に要素がセットされます。マップの場合は k にキー、v に値がセットされます。

簡単な例を示します。

リスト : range 節の使用例 (sample2c.go)

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5}
    b := map[string]int{"foo": 10, "bar": 20, "baz": 30}
    for i, v := range a {
        fmt.Println(i, v)
    }
    for k, v := range b {
        fmt.Println(k, v)
    }
}
$ go run sample2c.go
0 1
1 2
2 3
3 4
4 5
foo 10
bar 20
baz 30

もう一つ簡単な例を示します。普通の for 文と range 節を使った for 文で配列の要素の合計を求めてみましょう。次のリストを見てください。

リスト : 配列の合計値を求める (sample2d.go)

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    sum1 := 0
    for i := 0; i < len(a); i++ {
        sum1 += a[i]
    }
    fmt.Println(sum1)
    sum2 := 0
    for _, v := range a {
        sum2 += v
    }
    fmt.Println(sum2)
}
$ go run sample2d.go
55
55

通常の for 文の場合は、変数 i を 0 に初期化して、更新処理で i を +1 していくことで、配列の先頭から順番にアクセスします。条件部で i の値が len(a) 以上になったならば、配列の範囲を超えるので繰り返しを終了します。range 節の場合、配列 a の要素を先頭から順番に取り出して変数 v にセットします。このような単純な処理の場合は range 節を使ったほうが簡単ですね。

今回はここまでです。次回は関数について詳しく説明します。


初版 2014 年 2 月 2 日
改訂 2021 年 12 月 11 日

Copyright (C) 2014-2021 Makoto Hiroi
All rights reserved.

[ PrevPage | Golang | NextPage ]