Go

Godocker

InfoQの記事「100行以下のGoでコンテナを作る」をやってみた

InfoQの「Build Your Own Container Using Less than 100 Lines of Go」という記事を読んで、コンテナが技術的にどのように成り立っているのか、大変面白く学ぶことができました。本ブログでは、その記事の内容を紹介していきます。 Build Your Own Container Using Less than 100 Lines of GoShipping containers and software containers share a lot in common, but the analogy has limits. This article explores this relationship further by demonstrating how it is possible to build a simple container using less than 100 lines of Golang code. Topics covered include namespaces, cgroups and laye…Inf
Ami Yamamoto
Ami Yamamoto
4 min read
Go

Goのサーバーでcontext canceledをハンドリングする

はじめに Goでecho [https://github.com/labstack/echo]を使って以下のようなサーバーを作っていました。 var db *sql.DB func main() { e := echo.New() e.POST("/", func(c echo.Context) error { ctx := c.Request().Context() // 自身の管理するDBに保存する db.ExecContext(ctx, "INSERT INTO ...") // 別のサーバーで管理するDBに保存する req, err := http.NewRequestWithContext( ctx, http.MethodPost, "http://localhost:8081/", nil, ) if err != nil { return err } res, err := http.DefaultClient.Do(req) ... return c.NoContent(http
Yu Takahashi
Yu Takahashi
2 min read
Go

Goで外部通信の中身を確認する

使用しているライブラリの外部通信の中身(リクエストのヘッダやレスポンスのステータス等)をデバッグのために出力したくなったのでまとめました。 方法 以下のように外部のサーバーにリクエストするようなコードがあったとします。 package main import ( "context" "fmt" "net/http" ) func main() { if err := run(); err != nil { panic(err) } } var c = &http.Client{} func run() error { ctx := context.Background() req, err := http.NewRequestWithContext( ctx, http.MethodGet, "http://localhost:8080", nil, ) if err != nil { return err } res, err := c.Do(req) if err != nil { return err } fmt
Yu Takahashi
Yu Takahashi
3 min read
Go

Goで構造体をcomparableとして使う場合の注意点

Go1.18から導入された型パラメータ comparable は、 == や != で比較可能な型のみを受け入れます。 mapのキーにジェネリックな型を指定するような関数でよく使うと思います。 func ToMap[T comparable](ss []T) map[T]struct{} { m := make(map[T]struct{}, len(ss)) for _, s := range ss { m[s] = struct{}{} } return m } int や string などの組み込み型はもちろん、構造体も comparable を満たします。 type User struct { ID int Name string } func main() { us := []User{ { ID: 1, Name: "1", }, { ID: 2, Name: "2", }, } m := ToMap(us) _, ok := m[User{ID: 1, Name: "1"}] fm
Yu Takahashi
Yu Takahashi
1 min read
Go

Goのキャッシュ実装をジェネリクスで共通化する

はじめに GoでRedisを使ったキャッシュを実装する際、同じような処理を何度も書くことになりそうだったので共通化しました。 実装 Redisへリクエストする処理をinterfaceで定義しておきます。 type Client interface { Get(context.Context, string) ([]byte, bool, error) Set(context.Context, string, []byte, time.Duration) error } このinterfaceを満たすclientを実装します。Redisへの接続には github.com/go-redis/redis [https://pkg.go.dev/github.com/go-redis/redis/v8@v8.11.5] を使いました。 type client struct { c *redis.Client } func NewClient(addr, pass string) cache.Client { c := redis.NewClient( &redis.Op
Yu Takahashi
Yu Takahashi
2 min read
Gogolang

【Go】os.OpenFileのフラグについて

Photo by Markus Spiske [https://unsplash.com/@markusspiske?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit] / Unsplash [https://unsplash.com/?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit] ※go version go1.19 darwin/amd64 ファイルを作成するGoの関数os.OpenFileは、3つの引数を取ります。 https://pkg.go.dev/os#OpenFile func OpenFile(name string, flag int, perm FileMode) (*File, error) 第2引数のflag intは以下のような値を入れられます os.OpenFile("filename.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) この縦棒でつない
Ami Yamamoto
Ami Yamamoto
2 min read
Go

Goのcontextのkeyについて

はじめに Goの標準パッケージの context.Context は context.WithValue 関数を使って任意の値を格納することができます。 context.WithValue には以下のようなコメントが書かれています。 // WithValue returns a copy of parent in which the value associated with key is // val. // // Use context Values only for request-scoped data that transits processes and // APIs, not for passing optional parameters to functions. // // The provided key must be comparable and should not be of type // string or any other built-in type to avoid collisions between // packages using c
Yu Takahashi
Yu Takahashi
6 min read
Go

Goでsliceの一部を抽出する時の注意点

sliceの構造 Goのsliceは 配列へのポインタ 長さ 容量 を持った構造体として定義されています。 go/slice.go at go1.18 · golang/goThe Go programming language. Contribute to golang/go development by creating an account on GitHub.GitHubgolang [https://github.com/golang/go/blob/go1.18/src/runtime/slice.go#L15-L19]type slice struct { array unsafe.Pointer len int cap int } sliceの構造については以下の記事が分かりやすかったです。 実装して理解するスライス #golang - Qiitaはじめに この記事はGoアドベントカレンダーの1日目の記事です。 スライスの実態 runtimeのコードをみるとGoのスライスは以下のように定義されています。 type slice struct { arr
Yu Takahashi
Yu Takahashi
4 min read
Go

Goのinterfaceのnilについて

interfaceのnilチェックをしているのにメソッド呼び出し時にpanicが起きることがあり、その時に調べたことのメモです。 該当コードを簡略化して書くと以下のような感じです。 package main import "fmt" type Message interface { Str() string } var _ Message = &Text{} type Text struct { text string } func (t *Text) Str() string { return t.text } func NewText(str string) *Text { if str == "" { return nil } return &Text{ text: str, } } NewText() は引数が空文字の場合にnilを返します。 これに対して、以下のような Print() 関数を用意して実行すると、 func Print(m Message) { if m != nil { fmt.Println(m.Str
Yu Takahashi
Yu Takahashi
1 min read
OpenAPIGogolang

OpenAPIのサーバーでインテグレーションテストを書く

自社のサービスではOpenAPIを使ってサーバーを書いています。 https://swagger.io/specification/ ほぼ全てのエンドポイントに影響のあるリファクタリングをした時に、動作確認が辛すぎたのでインテグレーションテストを書くことにしました。 できたものは以下になります。 integration-test/integration_test at main · yutakahashi114/integration-test Contribute to yutakahashi114/integration-test development by creating an account on GitHub.GitHubyutakahashi114 [https://github.com/yutakahashi114/integration-test/tree/main/integration_test] 以下、簡単に説明を書いていきます。 サンプルアプリケーション 以下のschemaを元にサーバーを実装します。ユーザーの一覧取得、ID指定の取得、登録、更
Yu Takahashi
Yu Takahashi
10 min read
GCPCloud RunGo

ついにCloud Run に always-on CPUが登場したぞ!!

※まだプレビュー版です(2021/09/18) Cloud Run gets always-on CPU allocation | Google Cloud BlogNew always-on CPU allocation for Cloud Run opens the doors to running workloads that use background processes.Google Cloud BlogSteren Giannini Senior Product Manager [https://cloud.google.com/blog/products/serverless/cloud-run-gets-always-on-cpu-allocation] 今まではRequestがきてからResponseを返すまでCPUの割当がされていました。しかしそれでは下記のSlackのような3秒以内レスポンスを返す必要があるケースにて困ることが多々有りました。基本的にこのようなAPIはレスポンスを先に返してしまい、あとで別途非同期で処理を実行するという形で対応していましたが、そ
Kohei Kondo
Kohei Kondo
5 min read
Gogolanggomock

gomockでスライスのMatcherを作る

gomockでスライスを順不同で一致させるためにMatcherを自作しました。 ※追記 v1.6.0 から InAnyOrder というMatcherが用意されているので、不要になりました。 gomock package - github.com/golang/mock/gomock - pkg.go.devGo [https://pkg.go.dev/github.com/golang/mock/gomock#InAnyOrder]gomock GolangでUTを書く際に使います。 GitHub - golang/mock: GoMock is a mocking framework for the Go programming language.GoMock is a mocking framework for the Go programming language. - GitHub - golang/mock: GoMock is a mocking framework for the Go programming language. GitHubgolang [htt
Yu Takahashi
Yu Takahashi
3 min read