GoLang

第4回「プログラミング言語Go」オンライン読書会

第3回目を書いていません〜

今回は4回目の参加でした。

はじめに、軽く自己紹介。参加者は20名くらいでした。

まえふり

Javaバージョンたくさんあって、コードのメンテが大変。
Goは8年たった言語仕様はあまりかわってない。大幅な変更は来年かも。
GoのGenerics搭載は、はやくて1.17。

今日は第3章の続きから。

第3章続きから

3.6 定数

  • 定数同士の計算を書くことができる。コンパイル時にやってくれる。(需要はあるのかな〜?)
  • iota(いおた)
    • const宣言の最初にかかないといけない。でないと0から始まらない。
    • iotaはAPL言語(IBMのメインフレームで動いてた)からきている。
    • iotaはconstブロックで囲まれた行ごとのindexを返しているだけ。

輪読会後の質問&雑談タイムでのメモ

Javaのfinalについてちょっと聞いてみた。
constは定数。
finalは変数、一度値をいれたら変更できない(実行時に決まる)

  • Goは型が違うと演算させてくれないけど、定数は演算させてくれる。(型がないから.....?)

定数を代入するときは、キャストとかせずそのまま代入できる。型によっては精度がおちる?

const Pi 64 float64 = math.Pi

var x float32 = float32(Pi64)
var y float65 = Pi64
var z complex128 = complex128(Pi64) // これはなんて言ってたっけ?

runeは int32 とおんなじ。

Goは型が違うと計算できないのに、定数はできる..なんで?とおもったらこの章を思い出してね、とのこと。

第4章 コンポジット型

4.1 配列

var q[3]int = [3]int{1, 2, 3}
var r[3]int = [3]int{1, 2}
fmt.Println(r[2]) // 結果 0 ←初期値が入る
  • [2]int == [3]int 要素数が違うとコンパイルエラー(使うことないけど)
[]byte("Hello 日本")
[]rune("Hello 日本")
// 異なる結果が返る。
  • Goの配列コピーは、値のコピー(どんなに大きくても!)。C言語の配列コピーはアドレスコピー。

↑これは関数のときね(岩田プロ)

https://twitter.com/qt_luigi/status/1302119046574268416?s=20

4.2 スライス

楽しいスライス。

  • スライスは、配列の要素の部分へアクセスする軽量なデータ構造をしている。
  • 複数のスライスが同じ基底配列を共有することができる。
  • スライス演算子は新たなスライスを生成する。
  • スライス型のゼロ値はnil。
  • nilスライスは基底配列を持たない。

スライスが空かチェックするとき

s == nil      // ✕
len(s) == 0   // ○
  • appendしたら、同じスライス変数に代入するのが普通。
    (Gopher道場でも言ってた)
// スライスのデータ構造イメージ
type IntSlice struct {
  p *int
  len, cap int
}

4.3 マップ

  • Goは型に応じてハッシュテーブルを生成する。(Javaの場合は型を指定してから作る)

ハッシュテーブルの話になる。

  • N個ある配列に、ある値が入っているか調べるために何回検査をするか。
  • 値がランダム順の場合→O(N)
  • 値がソートされている場合→O(log2N)、真ん中から左右に向かって探し始める。(二分検索法)
  • O(1)は、検索時間が常に一定。どうやってい一定にするかを実現するか
    →ハッシュテーブルで実現
  • hash % M →ハッシュテーブルにいれる?
  • ハッシュテーブルに入れるタイミングで indexがぶつかったときは、
    隣にいれる(単純な方法)。実装によってちがう。
  • %vでMapを表示するときは、現在ではランダムではない。↓こちら..
  • Mapをfmt.Printで出力するとキーで昇順ソートされて出力されるのはGo 1.12から導入されました。(岩田プロ)

https://golang.org/doc/go1.12#fmt

  • ソートされるのは出力結果(見え方)だけ!(岩田プロ)
  • rangeは相変わらずランダム。
  • ハッシュテーブルにValueを持たせたのがマップ
  • マップが大きくなる際に既存の要素が再びハッシングされて新たなメモリ位置へ移動することがある。(keyからハッシュ値を出す→ハッシュテーブルに対し、データが入り切らなくなった場合とか)。なので、マップ要素のアドレスは得ることができない

質問&雑談タイム

  • len(s)は、内部のUTF-8表現のバイト数が🐸。文字数じゃない。
  • []byte(s) は、内部のUTF-8表現のバイト配列をコピーしたものを基底配列とするスライス。
  • []urne(s) 内部のUT-8の各文字をruneへデコードしたものを基底配列とするスライス。

    rune(uint32)の配列
    H E L L O △ 世 界

    マルチバイトの文字列を数える。
    utf8.RuneCountInString()
  • ジェネリクスについてけっこう話していた。柴田さんが自分で作ってるやつとか説明してくれた(難しかったけど)

柴田さんも岩田プロも、私のしょーもない質問に答えてくれたりで、とても貴重なお時間をいただいたのでした。

また次回♪

-GoLang