slog.Handlerとログレベル

※追記 2025-10-26T21:09 stdout で詰まっている説。 SetDefaultの前後でログを出力していて、AWS Lambdaのデフォルトのレポート出力と競合している? デフォルトのレポート出力中に、SetDefaultがスイッチをしようとしてロック? 解決策 「関数の起動直後のSetDefaultをしてかついる場合は、ログを極力出さない」かもです。こんなんでいいのか、という気もします。 経過見て、余力あれば追記します。

以下、発生していた問題です。

独自に slog.Handler 実装して slog.HandlerOptions.Levelを指定すると、slog.SetDefaultした瞬間に動かなくなる。

// main.go
logger := slog.New(mylog.NewJSONHandler(os.Stdout, 
    &slog.HandlerOptions{Level: slog.LevelDebug},
))
slog.SetDefault(logger) // ここで死ぬ

// mylog.go

type mylogHandler struct {
	slog.Handler
}

func NewJSONHandler(w io.Writer, opts *slog.HandlerOptions) slog.Handler {
	return &mylogHandler{Handler: slog.NewJSONHandler(w, opts)}
}

※ AWS Lambda だと動かない問題が発生して、ローカルで動かすとなんの問題もない、という不思議状態。

問題点以上。上のコードに加えて、前後でslog.Debugなどを2,3コ出力していた。 以下、誤った解決策。

一応、下で解決した。

logger := slog.New(mylog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)
slog.SetLogLoggerLevel(slog.LevelDebug)

// いける
// slog.HandlerOptions で渡さずに、 slog.SetLogLoggerLevel で指定する。

内部でデッドロックしているかもで、関連するISSUEもあるよう。 原因は正直不明で、気が向いたら調査します。 わからん。

go 

React.useStateは2種類ある

React.useStateにはある点で2種類あると考えている。 UI制御専用のもの そうでないもの これはUIコンポーネントに含められるかどうか、の違いがある。 UIコンポーネント UI制御専用のものとは。 テキストをマスクしたりしなかったりするコンポーネントを考える。(type=“password"は便宜上使用。) const [mask, setMask] = React.useState(false); return ( <> <input type={view ? "text" : "password"} /> <span onClick={() => setMask(!v => v)}>toggle</span> </> ) 入力された文字を表示するかどうかを、UIの責務の範囲内で完結されるべきと言えるときは、React.useStateが使って実装するのが良い(かもしれない)。 言い換えれば、UIコンポーネントとして表示/非表示を制御すると決めた場合、React.useStateを使っても問題はない。 強めに言えば、大体のUIコンポーネント内のReact.useStateは、表示/非表示を制御するのみと言っても良い。逆に言えば、それ以外のReact.useStateは、UIコンポーネントに含めるべきではないと考え始めると良いかもしれない。 UIコンポーネント外 先の例で言えば、input.valueに何を入力しているかは、UIコンポーネントの責務範囲外で、外部から受け入れるべき。 type Props = Pick<React.ComponentProps<"input">, "value">; function MaskedTextInput(props: Props) { } 便利なUIコンポーネントを作ろうとしてか、ビジネスロジックや他APIとの通信までコンポーネントに含まれてしまうパターンはよくありがちか。 設計方針次第ではあるが、ピュアなUIコンポーネントを作ろうと思ったときには、参考になるかもしれない。 例 いくつか例がある方がわかりやすいかもしれない。 React.useStateよりもコンポーネントの責務や命名のほうが主題かもしれない。 クリップボードにコピーするコンポーネント クリップボードに表示する値が動的に変化する場合は、それはおそらく呼び出し元で定義され流し込まれるべきかもしれない。 ここで利用したReact.useStateは、コピーしたらチェックマークを表示するようにするために利用されている。 function CopyInput(inputProps: React.ComponentProps<"input">) { const [copied, setCopied] = useState(false); const buttonProps = { onClick: () => { navigator. [続きを読む]

Go/iter でPipelineパターンやってみた

Goのv1.23で追加されたiterパッケージでPipelineパターンをやってみる。 Pipelineパターンはiterと併用できる? Pipelineパターンをiterと併用するメリットは? Pipelineパターンやiterはどこで使うべき? 要件 アプリケーションのバックエンド開発を想定。 商品を単価と個数をrepositoryから取り出して、単価x個数の合計金額をserviceで計算、最後handlerで計算結果を確認という流れ。 実装 iterパターンの実装を確認。 type Repository struct { items [][2]int // [][2]int{price, num} } func (r Repository) Generate() iter.Seq2[int, [2]int] { // r.itemsはコンストラクタによってlenは100 return slices.All(r.items) } type Service struct { r Repository } func (s Service) Iter() iter.Seq[int] { return func(yield func(int) bool) { for _, item := range s.r.Generate() { p := s.sumPrice(item[0], item[1]) _ = yield(p) } } } type Router struct { s Service } func (r Router) HandleWithIter() { var count int for sum := range r. [続きを読む]

ブログ始めました。

/img/top.jpg

ブログを始めました。目的は、これまでQiitaやnote、はてなブログに書いたものを集約することと、作ったものを紹介する記事を書くため。

フルリモートでエンジニアをやっています。

好きな言語はGo。

自己紹介は、こちらから。https://blob.yyyoichi.com/page/about/