Upgrade to Pro — share decks privately, control downloads, hide ads and more …

アンドパッドの Go 勉強会「 gopher 会」とその内容の紹介

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

アンドパッドの Go 勉強会「 gopher 会」とその内容の紹介

小島 夏海 @replu5
2025 年 6 月 18 日
golang.tokyo #39

アンドパッドの社内勉強会の一つ "gopher 会" では技術顧問の tenntenn さんを招き、 Go に対しても知見を深めています。今回は gopher 会をどのように運営しているかや、そこで得られた知見を紹介します。

Avatar for ANDPAD inc

ANDPAD inc

June 18, 2025

More Decks by ANDPAD inc

Other Decks in Programming

Transcript

  1. © 2024 ANDPAD All Rights Reserved. 2 自己紹介 小島 夏海

    (こじま なつみ) : replu : replu5 geminiに読みを聞いたら「リプル」 • 2021 年にアンドパッド入社 • Go Conference 2023/2024で登壇 • 「gopher」会の運営 • ポケモン Go/読書/🍺/☕ 2023年の発表 2024年の発表
  2. © 2024 ANDPAD All Rights Reserved. Confidential ANDPADとは 社内 現場

    営業 / 監督 / 設計 事務 / 管理職 職人 / 業者 メーカー / 流通 現場の効率化から経営改善まで一元管理できる クラウド型建設プロジェクト管理サービス 案件管理 資料 工程表 写真 報告 チャット 黒板 図面 受発注 • • • 
 
 3
  3. © 2024 ANDPAD All Rights Reserved. Confidential Go を間接的に使っているプロダクト ANDPAD

    の Go のプロダクト Go がメインのプロダクト 施工管理 引合粗利管理 受発注 検査 図面 黒板 ボード 資料承認 おうちノート … 4 請求管理 リモート通話
  4. © 2024 ANDPAD All Rights Reserved. 6 gopher会とは 当初は「プログラミング言語Go完全入門」の静的解析とコード生成[1]につ いて説明してもらいながら問題を解いていた

    現在はproposal: review meeting minutes[2] 眺めるのを中心にしつつ、go に関連する話題について雑談する会になっている [1] https://docs.google.com/presentation/d/1I4pHnzV2dFOMbRcpA-XD0TaLcX6PBKpls6WxGHoMjOg [2] https://github.com/golang/go/issues/33502
  5. © 2024 ANDPAD All Rights Reserved. 最近の話題 7 • range

    over funcのハンズオン開催 ◦ tenntenn Conference 2024で実際されていたものを社内でも開催 • 新しいエラーハンドリングについてわいわい ◦ 「discussion: spec: reduce error handling boilerplate using ?」についてみんなで 眺めながらわいわい • gRPC Streamのテストどうしよう ◦ gRPC Streamのテスト書いたことないけどいいサンプルないかな • Context に何入れよう ◦ t.OutputがAccept[1]された話からcontextに入れたい情報と入れたくない情報の話に ついてわいわい • t.Fatalとt.Errorの違い ◦ testと別のgoroutineでt.Fatal使うとおかしくなる ◦ t.Fatalはruntime#Goexitが呼ばれるmainのgoroutineじゃなくなる [1] https://github.com/golang/go/issues/59928
  6. © 2024 ANDPAD All Rights Reserved. 最近の話題 8 • API以外の用途でk8s上にデプロイしたPodのヘルスチェックをどうするか

    ◦ ヘルスチェック用のエンドポイントを準備するのがお手軽 • CACHEPROG ◦ 結局使い時はいつなのか ▪ この時は結論でなかった ▪ ビルドよりもテストで時間かかってる • https://pkg.go.dev/golang.org/x/[email protected]/cover を使って変更したいとこだけにテスト絞るとよさそう • 開発時だけ使用するツールの管理のベストプラクティス ◦ tool ディレクティブがでたよ ◦ golangci-lintはgo get非推奨だからどうするのがいいか • go の smtpのリクエストにタイムアウトを設定したい ◦ net/smtpのpkgはフリーズされている #36209[1] ◦ 利用しているサービスにHTTPのエンドポイントがあるならそちらにしたほうがよさげ [1] https://github.com/golang/go/issues/36209
  7. © 2024 ANDPAD All Rights Reserved. 最近の話題 • 「A Tour

    of Go」の次に何を見ればいいのかわからない 9
  8. © 2024 ANDPAD All Rights Reserved. 最近の話題 10 • Connect

    Serverでtyped nilが返ってくる ◦ 簡単にいうと値は空だが、型情報をもっているnilに対して if value == nil が trueに ならない ◦ 基本的にtyped nilは避けるようにするのがいい ◦ issue[1]あげたが、if err != nil と先にエラー確認すれば問題ないので対応しないという 結論でドキュメントに追記する方針 [1] https://github.com/connectrpc/connect-go/issues/827
  9. © 2024 ANDPAD All Rights Reserved. 11 package main import

    "fmt" type ( myInterface interface { f() } myType struct{} ) func (m *myType) f() {} func f() myInterface { var v *myType return v } func main() { v := f() if v == nil { fmt.Println("v is nil") } fmt.Printf("v value is: %v\n", v) } >> go run ./main.go v value is: <nil> typed nilの例
  10. © 2024 ANDPAD All Rights Reserved. 問題になった実装 12 connect serverのインターセプター

    func sampleInterceptor() connect.UnaryInterceptorFunc { return func(next connect.UnaryFunc) connect.UnaryFunc { return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { res, err := next(ctx, req) if res != nil { res.Header().Add("example", "example") } return res, err } } }
  11. © 2024 ANDPAD All Rights Reserved. 問題になった実装 13 connect serverのインターセプター

    func sampleInterceptor() connect.UnaryInterceptorFunc { return func(next connect.UnaryFunc) connect.UnaryFunc { return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { res, err := next(ctx, req) if res != nil { res.Header().Add("example", "example") <- ここでresがnilのためpanicになる } return res, err } } }
  12. © 2024 ANDPAD All Rights Reserved. 実際はどうなっているのか 15 untyped :=

    UnaryFunc(func(ctx context.Context, request AnyRequest) (AnyResponse, error) { if err := ctx.Err(); err != nil { return nil, err } typed, ok := request.(*Request[Req]) if !ok { return nil, errorf(CodeInternal, "unexpected handler request type %T", request) } res, err := unary(ctx, typed) if res == nil && err == nil { // This is going to panic during serialization. Debugging is much easier // if we panic here instead, so we can include the procedure name. panic(procedure + " returned nil *connect.Response and nil error") //nolint: forbidigo } return res, err })
  13. © 2024 ANDPAD All Rights Reserved. 実際はどうなっているのか 16 untyped :=

    UnaryFunc(func(ctx context.Context, request AnyRequest) (AnyResponse, error) { if err := ctx.Err(); err != nil { return nil, err } typed, ok := request.(*Request[Req]) if !ok { return nil, errorf(CodeInternal, "unexpected handler request type %T", request) } res, err := unary(ctx, typed) <- ここでtyped nilが返ってくることがあり if res == nil && err == nil { // This is going to panic during serialization. Debugging is much easier // if we panic here instead, so we can include the procedure name. panic(procedure + " returned nil *connect.Response and nil error") //nolint: forbidigo } return res, err <-ここで戻り値をそのまま返すので typed nilを返すことがある })
  14. © 2024 ANDPAD All Rights Reserved. 実際はどうなっているのか 17 untyped :=

    UnaryFunc(func(ctx context.Context, request AnyRequest) (AnyResponse, error) { if err := ctx.Err(); err != nil { return nil, err } typed, ok := request.(*Request[Req]) if !ok { return nil, errorf(CodeInternal, "unexpected handler request type %T", request) } res, err := unary(ctx, typed) if res == nil && err == nil { // This is going to panic during serialization. Debugging is much easier // if we panic here instead, so we can include the procedure name. panic(procedure + " returned nil *connect.Response and nil error") //nolint: forbidigo }  if err != nil { return nil, err } return res, nil })
  15. © 2024 ANDPAD All Rights Reserved. 4年間開催して 18 • 目的は特に定めていないが無くてはない会になっている

    ◦ Goについて困ったらここで聞けばいいという場の提供 ◦ 事前準備が必要ないので継続しやすい ◦ メンバーは流動的だがコアメンバー的な人が自然と生まれ上手く回っている ▪ コアメンバーも特に何かをしているわけではない • 最先端のことを喋っているので知らない間に詳しくなっている ◦ さらに深掘りするきっかけになっている ◦ Go Conference の採択率が高いプロポーザルがかけている ▪ 4/4で通ってる