Carpe Diem

備忘録

ウィンドウ処理の種類

概要

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

ウィンドウ処理

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

グローバルウィンドウ

一番シンプルな、ウィンドウの区切りがなくすべてのデータが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)
続きを読む

あるIAMパーミッションがどのロール・ユーザに含まれるか調べる方法

概要

GoogleCloudのIAMにおいて、ユーザやサービスアカウントの権限の棚卸しをする際に、とあるIAMパーミッションがどのロール・ユーザ(メンバー)に含まれるか調べる方法です。

事前に以下を知っておくとイメージが付きやすいです。

christina04.hatenablog.com

手順

ロールやユーザ(メンバー)の関係図は次のようになっています。

続きを読む

Bazel + CEL でgo_default_libraryが必要になる問題の対処方法

背景

Bazelで依存関係を管理している環境で、celライブラリを導入したところ次のようなエラーが発生しました。

'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/overloads:overloads': target 'overloads' not declared in package 'common/overloads' defined by /external/com_github_google_cel_go/common/overloads/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types:types': target 'types' not declared in package 'common/types' defined by /external/com_github_google_cel_go/common/types/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types/ref:ref': target 'ref' not declared in package 'common/types/ref' defined by /external/com_github_google_cel_go/common/types/ref/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types/traits:traits': target 'traits' not declared in package 'common/types/traits' defined by /external/com_github_google_cel_go/common/types/traits/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//ext:ext': target 'ext' not declared in package 'ext' defined by /external/com_github_google_cel_go/ext/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/expression:expression'
'@com_github_google_cel_go//interpreter:interpreter': target 'interpreter' not declared in package 'interpreter' defined by /external/com_github_google_cel_go/interpreter/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/expression:expression'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/constraints:constraints'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/evaluator:evaluator'

これはcel-goに依存していた場合のBazelのターゲットの記述が本来は

go_library(
    ...
    deps = [
        ...
        "@com_github_google_cel_go//cel:go_default_library",
        ...
    ],
)

であるべきが、gazelleを使ったところ

go_library(
    ...
    deps = [
        ...
        "@com_github_google_cel_go//cel",
        ...
    ],
)

となってターゲットの記述が不適切になってしまったせいです。

今回はこの回避策方法について説明します。

続きを読む

Goのテストで一部のフィールドを対象外にしたい

背景

Goのテストを書いていると大半のフィールドは検査したいけれど

  • 自動生成しているUUIDのようにランダムになる部分
  • UpdatedAt, CreatedAtのように時刻のずれが影響する部分

を対象外としたいケースが出てきます。

単純に考えると以下のような方法が浮かびますが、それぞれ欠点があります。

  • 1つ1つのフィールドを書き出すとフィールドが追加されたときに漏れることがある
  • gomock.Any()にするとそれ以外のフィールドのテストができなくなる

そういった部分をどう除外するかを説明します。

環境

  • go v1.22.6
  • go-cmp v0.6.0
  • gomock v1.6.0
続きを読む