Go言語マスター 〜リスト処理・Map〜

公開日:2022-09-25
go

https://youtu.be/htJXUu0GL3w

はじめに

今回は、前回と同様、配列やスライスを学習します。

Range

スライスなどを、forループで反復処理をするための方法を学習します。
今回のサンプルコードはつぎのようです。

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
  for i, v := range pow {
    fmt.Printf("2**%d = %d\n", i, v)
  }
  // 出力結果
  // 2**0 = 1
  // 2**1 = 2
  // 2**2 = 4
  // 2**3 = 8
  // 2**4 = 16
  // 2**5 = 32
  // 2**6 = 64
  // 2**7 = 128
}

サンプルコードのように for i, v := range 配列名のようにfor文を行うと、変数iには配列のindex、変数vには配列のindexの位置にある要素となります。

Range continued

今回のサンプルコードはつぎのようです。

package main

import "fmt"

func main() {
  pow := make([]int, 10)
  for i := range pow {
    pow[i] = 1 << uint(i) // == 2**i
  }
  for _, value := range pow {
    fmt.Printf("%d\n", value)
  }

  // 出力結果
  // 1
  // 2
  // 4
  // 8
  // 16
  // 32
  // 64
  // 128
  // 256
  // 512
}

1つ目のfor文では、indexの取得のみを行いため、2つ目の値を省略しました。
2つ目のfor文では、indexの値が必要でなかったため、_を使用して値を代入せずに、省略しました。また、この手法は、他の文法でも使用できます。

Maps

次は、配列と似たMapについて説明します。
今回のサンプルコードはつぎのようです。

package main

import "fmt"

type Vertex struct {
  Lat, Long float64
}


func main() {
  var m = make(map[string]Vertex)
  m["Bell Labs"] = Vertex{
    40.68433, -74.39967,
  }
  fmt.Println(m["Bell Labs"]) // {40.68433 -74.39967}
}

Mapというのは、キーと値を関連付けた物です。
まず、マップの初期値は何も入っておらず、nilマップになります。
サンプルでは、var m = make(map[string]Vertex)のところでnilマップ作成しています。
mapに対して、キーを指定することで値に代入や、アクセスできます。
作成した変数mに対してキーをBell Labsとして、m["Bell Labs"] = Vertex{ 40.68433, -74.39967, }のように代入をします。
つぎは、fmt.Println(m["Bell Labs"])のようにMapにアクセスをして出力します。

Maps literals

今回はMapにおけるリテラルについて説明します。リテラルとはソースコード中に直接記述する値のことで、リテラルを使うことで宣言時に値を代入できます。
今回のサンプルコードはつぎのようです。

package main

import "fmt"

type Vertex struct {
  Lat, Long float64
}

var m = map[string]Vertex{
  "Bell Labs": Vertex{
    40.68433, -74.39967,
  },
  "Google": Vertex{
    37.42202, -122.08408,
  },
}

func main() {
  fmt.Println(m)
}

今回のサンプルでいうところのリテラル(定数)はつぎのところです。

var m = map[string]Vertex{
  "Bell Labs": Vertex{
    40.68433, -74.39967,
  },
  "Google": Vertex{
    37.42202, -122.08408,
  },
}

このようにリテラルを定義しています。structの定数に似ていますが、Mapはキーが必要です。

Maps literals continued

今回は、Mapにおけるリテラルを定義する時に、型宣言を省略する方法を説明します。

package main

import "fmt"

type Vertex struct {
  Lat, Long float64
}

var m = map[string]Vertex{
  "Bell Labs": {40.68433, -74.39967},
  "Google":    {37.42202, -122.08408},
}

func main() {
  fmt.Println(m)
}

先ほどの章では、つぎのようにリテラルを定義しました。

var m = map[string]Vertex{
  "Bell Labs": Vertex{
    40.68433, -74.39967,
  },
  "Google": Vertex{
    37.42202, -122.08408,
  },
}

そして、今回サンプルのように型を省略したらつぎのようになります。

var m = map[string]Vertex{
  "Bell Labs": {40.68433, -74.39967},
  "Google":    {37.42202, -122.08408},
}

このようにVertex型を省略できました。Mapの型が単純な型名である場合は、型を推測できるので、型名を省略できます。

Mutating Maps

次に、Mapの操作について説明します。
サンプルコードは次のようです。

package main

import "fmt"

func main() {
  m := make(map[string]int)

  m["Answer"] = 42
  fmt.Println("The value:", m["Answer"]) // The value: 42

  m["Answer"] = 48
  fmt.Println("The value:", m["Answer"]) // The value: 48

  delete(m, "Answer")
  fmt.Println("The value:", m["Answer"]) // The value: 0

  v, ok := m["Answer"]
  fmt.Println("The value:", v, "Present?", ok) // The value: 0 Present? false
}

挿入や更新にはm["Answer"] = 42というようにキーを指定して代入します。
また、値の取得も同様に、m["Answer"]というようにキーを指定することで、値を取得できます。
要素の削除にはdelete関数を用います。delete(変数,キー)という書式で指定することで、要素を削除できます。
最後に、Mapの値が存在するかを確かめる方法について説明します。
サンプルコードのように、v, ok := m["Answer"]というように2つの変数に結果を代入します、 1つ目の変数vにはMapの値が代入され、2つ目のokには真理値が代入されます。値が存在する時には2つ目の値がtrueとなり、存在しない場合にひはfalseとなります。
この方法を使うと、初期値の0なのか、要素の削除が行われた0なのかを判断できます。

おわりに

今回は、Mapのループや定数、基本的な操作方法を学習しました。次回からは、function(関数)の話になります。