Carpe Diem

備忘録

Go Toolchainの挙動を確認する【理論編】

概要

前回は実際に動かしてみて挙動を確認してみました。今回はそのロジックを理解します。

christina04.hatenablog.com

GoのToolchainはv1.21以降で導入された機能で、次のような課題を解決するために生まれました。

  • go.modに記載のバージョンは直感的じゃない
    • 実際にビルドに使われるのはローカルにインストールされているGo
    • ビルドでコケたらgo.modに記載のバージョンで module requires Go 1.xxと言ってくるが、実際に必要な最低バージョンの保証ではない
      • もしかしたらもう少し低いバージョンでもBuildできる可能性もある
  • Go 1.19.4でバグが入ったが、Go 1.19.3, Go 1.19.5 であればBuildできる状態。けれどそれをgo.modで表現できない

またGoでは後方互換性が保証されてはいるものの、複数のプロジェクトにまたがっているとプロジェクトによって使うGoバージョンが決まっていたりするため、何だかんだ複数のバージョン管理ができると良かったりします。

環境

  • Go v1.21以上
  • macOS v15.1.1
続きを読む

Go Toolchainの挙動を確認する【検証編】

概要

Go Toolchainはモジュールで使うバージョン管理をgoディレクティブだけの頃よりも正確に制御できます。

しかしビルドバージョンは以下の要素の組み合わせから決定されるため、ちゃんと理解していないと期待しない挙動になることがあります。

  • GOTOOLCHAIN環境変数
  • ローカルバージョン
  • go.modのgoディレクティブ
  • go.modのtoolchainディレクティブ

今回は簡単に検証できる環境を紹介して、どうなるのか確認してみます。

続きを読む

振る舞いをデータとしてモデル化する

背景

モデリングでは要件に対して

  • データの要件(〜を持つ。〜がある)
  • 振る舞いの要件(〜ができる。〜しなければならない)

のどちらかをまず判断します。

そしてオブジェクト指向では、オブジェクトが

  • データ(属性、フィールド)
  • 振る舞い(メソッド)

を持つという形で、先ほどの要件を表現します。

一方関数型プログラミングでは、振る舞い自体もできるだけデータとしてモデル化していく指向になります。

今回はそれを具体例を交えながら説明します。

続きを読む

ウィンドウ処理の種類

概要

よく使うウィンドウ処理の種類をユースケースとともにまとめます。

ウィンドウ処理

ウィンドウとは集計範囲のことであり、その範囲をどう捉えるか色々な方法があります。

グローバルウィンドウ

一番シンプルな、ウィンドウの区切りがなくすべてのデータが1つのウィンドウに蓄積されるパターンです。

ユースケース

  • 全体集計や最終結果の計算
    • ストリーミングデータを一括で集計して、システム全体の動作を確認する最終レポート作成時など。
続きを読む

Goのジェネリクスのユースケース

背景

Go 1.18からジェネリクスが導入されました。
とはいえ具体的にどういう時に使えば良いの?と疑問に思う人も多いと思うので、ユースケースの例をいくつか挙げてみます。

環境

Go v1.23.0

ユースケース

ユースケースを挙げていきます。

コレクション操作

ジェネリクスユースケースで代表的なのがリスト、コレクションの操作です。
ただGoの場合はsamber/loでほぼ解決できます。

func Filter[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {
    result := make(Slice, 0, len(collection))

    for i := range collection {
        if predicate(collection[i], i) {
            result = append(result, collection[i])
        }
    }

    return result
}

https://github.com/samber/lo/blob/407b62d3f12eece919463f556c798661f5aabbbf/slice.go#L12-L22

このように中の実装でジェネリクスを利用しています。

続きを読む

go get でアップデートすると、なぜか別のライブラリがダウングレードする

背景

go get でアップデートすると、なぜか別のライブラリがダウングレードする不思議な現象に出会いました。

$ go get github.com/userA/hoge
go: downgraded github.com/userB/foo v1.2.1 => v1.0.0
go: downgraded github.com/userB/bar v1.10.0 => v1.1.0
go: upgraded github.com/userA/hoge v1.4.0 => v1.5.0

環境

Go v1.23.2

原因

原因は

  • GoがMVS(Minimal version selection)を採用している
  • ライブラリが循環参照している

ためでした。

続きを読む

代数的データ型を用いたデータモデリング

概要

データモデリングをする際に、エンジニアは次のことに注意しなくてはいけません。

  1. パラメータの順序
  2. パラメータを組み合わせの意味
  3. 一部のパラメータの値を有限集合にする

これらを解決する手法として、関数型プログラミングでは代数的データ型があります。

要件

例えば以下の様な要件があるとします。

図書館の書籍

  1. 書籍のリストを検索できなければならない。
  2. 各検索では、ジャンル、著者、出版年、利用可能かどうか、貸出中の期間など、様々な組み合わせをサポートする必要がある。
  3. 書籍にはそれぞれ名前、ジャンル、著者、出版年、利用可能かどうか、貸出中の期間、がある。

これを愚直に考えたBookモデルを以下の様に表現してみます。

case class Book(title: String,
                author: String,
                genre: String, 
                publicationYear: Int,
                isAvailable: Boolean, 
                checkoutDate: Int,
                returnDate: Int)
続きを読む