- 1. GoでgRPC API超入門
- 2. GoとRedisで作る簡単従業員管理アプリ
- 3. Go | 同じ名前の関数で引数の数を変える
- 4. Go | Strategy + Null Object
- 5. Go | Union を Interface で実現する
- 6. [備忘録] Go CloudFunctionsでChain Middlewareを利用する
- 7. InteractionとWebhookでサーバレースなDiscord Bot作成
- 8. github.com/aws/aws-sdk-go-v2のEndpointが非推奨になっていた件
- 9. 【Go言語】スキルチェックを解くための開発環境とコーディングの考え方
- 10. goのエラーハンドリング
- 11. goのエラー作成
- 12. gormを使ったクエリーのロギング
- 13. Cloudbuildとgoのginを使用してCloudRunとcloudFunctions(gen2)へデプロイする
- 14. キー一発でOCR+Linterかけてコマメに日本語をメンテナンスするツール書いた!
- 15. 【地図】日本の市区町村ごとの犯罪率/賃貸/年収/人口のステータスが一覧できるWebサイトを作りました。【個人開発】
- 16. ProxmoxをiPXEでいれてみた
- 17. GORM Saveメソッドの挙動を追ってみた
- 18. Dockerでgoのマルチステージビルドでexisted(0)で落ちる件を解決した
- 19. 【Go】Ginでhealth_checkのログを表示したくない
- 20. Go構造体のバリデーション: スペースの落とし穴
GoでgRPC API超入門
自分の中で少しずつ理解できてきたので、小分けにして整理していきたくこの記事を書きました。
同じ初学者のお役に立てれば。::: note
当記事は実装メインで解説します。
protoって何の略?これは内部でどうなってるの?的な細かい話は省いています。
気になるところがあったら他記事で補完してください🙏
:::## 構成
今回は最小限の超簡単な構成とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821214/f317ee38-fcdc-4807-dd65-089a1af1f128.png)
初学者はHello,World!を出力しなければならないという法律に則り、Hello,World!を出力するAPIを実装していきます。実装では、クライアントのインスタンス、gRPCサーバのインスタンスをそれぞれ立ち上げ、リクエスト〜レスポンスまでの流れを確認する、ということをやります。
## 大まかな手順
ゆるふわ概念図を記しておきます。
### 全体像
まずは作成するものの全体
GoとRedisで作る簡単従業員管理アプリ
# GoとRedisの勉強のために作りました
こんにちは!今回は、Go言語とRedisを使って、シンプルだけど便利な従業員管理アプリを作っていきます。プログラミング初心者の方も、ベテランの方も、一緒に楽しく学んでいきましょう!
## 1. 環境設定
まずは開発環境を整えましょう。GoとRedisをインストールして、必要なパッケージも用意します。
“`go
go mod init employee-app
go get github.com/go-redis/redis/v8
“`これで準備オッケーです!さぁ、コーディングを始めましょう。
## 2. Redisクライアントの設定
次に、Redisに接続するためのクライアントを設定します。
“`go
package mainimport (
“context”
“github.com/go-redis/redis/v8”
)var ctx = context.Background()
func newRedisClient() *redis.Client {
return redi
Go | 同じ名前の関数で引数の数を変える
雑めも
– https://xuri.me/excelize/en/sheet.html#SearchSheet を使ってて
`f.SearchSheet(sheet, kw, true)`
と
`f.SearchSheet(sheet, kw)`が許容されてるのに気づいたのでメモ
## 末尾に1つ要素の有無をコントロールする
– [Playground](https://goplay.tools/snippet/qLiuZ23dLjM)
“`go
package mainimport (
“fmt”
)func main() {
// opt arg なし
fmt.Println(“>> no opt arg”)
f1(“:D”)
fmt.Println()// false
fmt.Println(“>> false”)
f1(“:D”, false)
fmt.Println()// true
fmt.Println(“>> true”)
f1(“:D”, true)
fmt.Println()// invalid
Go | Strategy + Null Object
## 雑めも
– ストラテジーパターン
– アルゴリズム(ストラテジー)を注入して使う。Excelストラテジー、PDFストラテジー、Nilストラテジーのどれか。
– それぞれのストラテジーごとに、構造体が違うため保持できるデータも異なる(`Excel.excel` と `Pdf.pdf` の箇所)– Null Object
– Nilストラテジーは Null Objectパターンで、`nil` ではなくて処理をしない構造体を渡しておくと実行時に nil チェックが必要なくなる– インジェクション
– ストラテジーを注入するタイミングがコンストラクタによる生成時かメソッドを実行時によってやり方が異なる## ストラテジーパターン(コンストラクタインジェクション)
– [Playground](https://goplay.tools/snippet/pKsizrTUHne)
“`golang
package mainimport “fmt”
func main() {
var ct Content// Excel
ct = Content{
Go | Union を Interface で実現する
最近はもっぱらGoを書いてるがメンタルモデルがTypeScriptに引きづられていたのでコード例を交えて比較して書いてみる。
## Go
– [Playground](https://goplay.tools/snippet/ETypdOB7qVv)
– Go らしくならInterfaceで実現する
– identifyなどのようにAやBごとのそれぞれの処理は、それぞれの構造体に対してメソッドを生やす形で実現する
– ダックタイピングなので、AとBはInterfaceのAorBのことを知らない。また、`echo(str string, aorb AorB)` の `aorb` は `AorB` のInterfaceを満たすものならA、B以外でも入れられる
– kind のように、AやBごとに必ず値を持っているものはInterfaceに`Kind`を定義してメソッドで実現する“`go
package mainimport (
“fmt”
)func main() {
// a
a := A{IamA: “なんかの値A”}
echo(“A: “, a)
[備忘録] Go CloudFunctionsでChain Middlewareを利用する
# Go CloudFunctionsでChain Middlewareを利用する
経緯
フト思った時に変態っぽいコードの書き方をしていたので、備忘録。
###### TL;DR
呼び出し元のfunctionsで、http.HandlerFunc(handler).ServeHttp(w, r)で実施する。
“`middleware.go
package middlewareimport “net/http”
type Middleware func(http.Handler) http.Handler
func ChainMiddleware(h http.Handler, m …Middleware) http.Handler {
if len(m) < 1 { return h } wrapped := h for i := len(m) - 1; i >= 0; i– {
wrapped = m[i](wrapped)
}return wrapped
}func LoggerMiddleware(next http.Ha
InteractionとWebhookでサーバレースなDiscord Bot作成
# InteractionとWebhookでサーバーレスなDiscord Bot作成
[Interaction](https://discord.com/developers/docs/interactions/overview)ベースのDiscord Botを作ってみていい感じだったのでメモします。## Discord Bot の2種類の作り方
Discord Botはユーザからのイベントを受け取って何らかの動作を行いますが、そのイベントの受け取り方は2種類あります:
– WebSocket
– 人間のユーザと同じようにクライアント -> Discord へ接続します
– Botプロセスを常駐させる必要があります
– Webhook
– イベントが起こると Discord からあらかじめ定めたHTTPエンドポイント(Interaction Endpoint URL)へWebhookが飛びます
– リクエストベースで起動する Lambda や Cloud Run などのサービスと相性が良いですWebhookはWebSocketベースのBotよりも受信できるイベン
github.com/aws/aws-sdk-go-v2のEndpointが非推奨になっていた件
# 概要
新しいサービスを作るにあたってGo言語からR2に読み書きする必要があり、[github.com/aws/aws-sdk-go-v2](github.com/aws/aws-sdk-go-v2)を使ったS3クライアントの初期化処理を既存サービスから流用しようとしました。その際、`EndpointResolverWithOptionsFunc`などの関数がDeprecatedになっていました。
これについて言及している記事があまり無かったので、メモがてら記事にしてみました。
# 内容
調べたところSDKの[aws/endpoints.go](https://github.com/aws/aws-sdk-go-v2/blob/main/aws/endpoints.go)内の構造体や関数が非推奨になっていました。`EndpointResolver`のインターフェース定義部分に以下のようなコメントがありました。
“`golang
// Deprecated: The global endpoint resolution interface is deprecated. T
【Go言語】スキルチェックを解くための開発環境とコーディングの考え方
# 概要
コラボキャンペーンが面白そうなので、久しぶりにPaizaの問題を解いてみました。
せっかくなので、ローカルの環境でもテストができる環境構築も整え、解説してみようかと思います。
少し前まで、Paizaのエディターで直接書いて提出していました。もちろんテストなしでした(笑)提出コードは Go言語を使用しています。(私の一番得意な言語なので)
## 想定する読者
– 就職活動でPaizaを利用している人
– エンジニアになってまだ経験が浅い人## この記事の目的
– Paizaのスキルチェックを受け、エンジニアへの就職(転職)を成功させる
## この記事で解説すること
– 実務のコードと競技プログラミングのコードの考え方
– Paizaの問題をローカル環境で書いて試すローカルでの開発環境を整えることで、より効果的、効率的にPaizaのスキルチェックを受ける。
ただスキルチェックを受けるだけでなく、企業の目に止まりやすいコーディングができるようになる。
これらを目指して、就職(転職)を成功させてほしいと思います。## この記事では解説していないこと
提
goのエラーハンドリング
実用Go言語 第5章 エラーハンドリング より
### エラーハンドリングの基本
エラーハンドリングとしては多くの場合以下のような方針が考えられる。
1. 呼び出し元に関数の引数などの情報を付与してエラーを返す
2. ログを出力して処理を継続する
3. リトライを実施する
4. リソースをクローズするGoではpanicを多用せずエラーハンドリングを行いエラーを返すべき。
### 呼び出し元に情報を付与して返す
エラーが発生した場合そのまま返していては発生個所の特定がむずかしいため、情報を付加して返す。
“`
user, err := getInvitedUserWithEmail(ctx, email)
if err != nil {
return fmt.Errorf(“fail to get invited user with email(%s): %w”, email, err)
}
“`### ログを出力して処理を継続
ex. データベースに指定されたレコードが存在しないとデフォルトの値を用いて処理を継続するなど
“`
//func featchCap
goのエラー作成
実用Go言語 第五章 エラーハンドリングよりメモ
goアプリケーションでエラーを作成する方法は大きく二つに分けられる。
1. 標準ライブラリの関数を使って作成
2. アプリケーション独自のエラー型を定義### errors.new
もっともシンプルなエラー生成法。変数に保存すると区別してハンドリングしやすい。
“`
var ErrNotFound = errors.New(“not found`)
func findBook(isbn string) (*Book, error) {
return nil, ErrNotfound
}
“`### fmt.Errorf
フォーマットされた文字列を元にエラーを作成
“`
func validate(length int) error {
if length <= 0 { return fmt.Errorf("length must be greater than 0, length = %d", length) } return nil } ``` ### 独自のエラー型
gormを使ったクエリーのロギング
実用Go言語 9.9.4 クエリーのロギングより メモ
– 標準ライブラリのdatabase/sqlパッケージはロギングをサポートしていない
– サードパーティ側で用意されている場合積極的にライブラリ側のAPIを使うとよい“`
newLogger := logger.New(
log.New(os.Stdout, “\r”, log.LstdFlags), //出力設定、改行方法、プロパティ
logger.Config{LogLevel: logger.Info}, //Silent, Error, Warn, Info がある
)db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{Logger: newLogger})
if err != nil {
log.Fatal(err)
}
“`※log.LstdFlags とは
logを yyyy/mm/dd HH:MM:SS で表示する。
他にもLmicrosecondsマイクロセカンド表示などがある表示されたログ
“`
Cloudbuildとgoのginを使用してCloudRunとcloudFunctions(gen2)へデプロイする
## ディレクトリ構造
“`
./
├─/cmd
│ └── main.go
├─/handlers
│ └── handlers.go
├── Dockerfile
├── go.mod
├── go.sum
├── cloudbuild.yaml
└── router.go
“`
## goのソース
“`main.go
package mainimport (
“context”
“log”router “github.com/yourname/gin”
“github.com/GoogleCloudPlatform/functions-framework-go/funcframework”
)
func main() {ctx := context.Background()
gin := router.GinHandler
// 実行する関数の登録
if err := funcframework.RegisterHTTPFunctionContext(ctx, “/”, gin); err != nil {
log.Fatalf(“fu
キー一発でOCR+Linterかけてコマメに日本語をメンテナンスするツール書いた!
# 日本語の乱れはコンテキストの乱れ
日本人だけど日本語力に乏しいと言われ続けて生きてきました・・・
「~の、~の、って二度出てきて読み辛い」
「実装を行う、じゃなくて、実装するで良いんじゃない?」
「アプリなのかい?アプリケーションなのかい?どっちなんだい?」みなさんも経験があると思うけど、こういう些細なミスは口語だったら言い直しと説明で済む。
でも、資料だけを見て、内容を判断しなきゃならない場合誤読を呼び込んでしまう。
「てにおはを正しく!」って昔、先輩に言われてた事、そういう事だって良いオジサンになってから思い返してる。
読み辛い文はコンテキストを乱し、伝えたいメッセージを弱めてしまう、そういうことだったのサ!**リンター入れますか?**
# リンター入れられません・・・
Markdownとかテキスト形式ならtextlint使うなりのエコシステムに乗っかれた。
でもそうはいかない状況はしばしば発生する・・・– Powerpoint
– ブラウザのスプシ
– PDFとかリッチなフォーマット
– そもそも画像フォーマット元ソースがテキスト文章に寄せてないフォー
【地図】日本の市区町村ごとの犯罪率/賃貸/年収/人口のステータスが一覧できるWebサイトを作りました。【個人開発】
# 1.概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201311/7d141c74-2cff-c27e-8e46-1fe866940383.png)– サイト名: 日本まとめ地図
– URL: https://prod.jpn-map-status.com/「日本地図ステータス」は、日本の各都道府県のさまざまな統計情報を視覚的に表示するウェブサイトです。このサイトは、次のような特徴を持っています。
1. Leafletを使って視覚的に情報を表示しています。
– 地図ライブラリはフリーのleafletを使用しています。
2. 各市区町村ごとにステータス16段階色分け
– 平均年収・賃貸・人口密度・治安で順位づけしてます。
– 治安は1000人あたりの犯罪認知件数から算出
– ヘッダーのメニューから項目の切り替え
3. 各地域をクリックすることで詳細を表示
– 具体的な数値を表示**情報元**
政府統計ポータル[e-St
ProxmoxをiPXEでいれてみた
## 概要
ProxmoxをiPXE経由で起動して自動セットアップをしてみる## 流れ
1. iPXEBoot可能なPCを起動する
1. DHCPによりインストーラの場所を取得
1. HTTPサーバーよりインストーラの取得
1. 同じくHTTPサーバーより初期セットアップ用の回答ファイルの取得
1. 自動起動!## 環境
| 機器 |
|——|
|NEC IX2215|
|動いてるPROXMOXサーバー 8.1.4|## 手順
#### iPXEBoot可能なPCを準備する
検証につき自前proxmoxサーバーにてVMを準備
マシン: i440fx
BIOS: SeaBIOS
OSタイプ: Linux 6.x
CPU: HOST
メモリ: 6,144:::note warn
メモリが6GB以下だとインストールができないことがあった
:::一度起動し、BIOS設定にて起動順序を`iPXE ipv4` のみにしておく
#### インストーラの準備
https://pve.proxmox.com/wiki/Automated_Installation
ここを参考
GORM Saveメソッドの挙動を追ってみた
#### GORMのsaveメソッドはupsertをやってくれて便利だが、update時にCreatedAtは更新されるのか?あれupdateなのになんかinsert動いてない?みたいなことがあって調べた
## 知ってないとハマるポイント1
#### SaveメソッドはUpdateして0件だとINSERTするよちょっと意外だったのが、Updateを実行した際に結果が0件だと、INSERTが実行されます。
これは便利ともいえるけど、何らかのバグでプライマリフィールドに意図しないIDが渡るとエラーにならずに、レコードがINSERTされてしまいます。https://github.com/go-gorm/gorm/blob/master/finisher_api.go#L73
“`go:finisher_api.go
func (db *DB) Save(value interface{}) (tx *DB) {
tx = db.getInstance()
tx.Statement.Dest = valuereflectValue := reflect.Indir
Dockerでgoのマルチステージビルドでexisted(0)で落ちる件を解決した
## 初めに
筆者はDocker初心者であんまりDockerについて理解してません。ご了承ください## 結論
必要なファイルは実行用コンテナにもコピーしよう
“`dockerfile
COPY –from=builder /app/config ./config
“`## 経緯
– あるプロジェクトでgoの環境を作る必要があった
– 容量が1GB近くとかなり大きいイメージだった
– CI/CDを意識すると容量を削減したいと考えていました## マルチステージビルド
調べていく中でマルチステージビルドというものがあるのを発見
これを使おうとしました
## existed(0)の症状
– マルチステージビルドを使わない環境だと立ち上がる
“`dockerfile
FROM golang:1.20-alpine
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /main ./cmd
“`
– マルチステージビルド環境で立ち上がらない
“`dockerfil
【Go】Ginでhealth_checkのログを表示したくない
# はじめに
health_checkのログが多すぎて大事なログが見つけられない…みたいなことありますよね。
Ginの環境を作っている際にその問題にぶち当たったので、そんなお悩みを解決できる方法を備忘録としてまとめました。# 結論
以下の2通りの方法で、特定のパス(ここでは/health)についてログ出力を抑制することができます。
“`go
router := gin.New()
router.Use(gin.LoggerWithWriter(gin.DefaultWriter, “/health”))
router.Use(gin.Recovery())
“`“`go
router := gin.New()
router.Use(gin.LoggerWithConfig(gin.LoggerConfig{SkipPaths: []string{“/health”}}))
router.Use(gin.Recovery())
“`通常、基本的なルーターの設定にはgin.Default()を使用することが多いと思います。
この関数はデフォルトで`Logger`と
Go構造体のバリデーション: スペースの落とし穴
# はじめに
ウェブアプリケーションを開発する際、HTTPメッセージボディのデータの検証を行う場合があります。
例えば、ユーザーが入力した情報が必須項目を満たしているか、数値が適切な範囲に収まっているかなど。
Go言語でバックエンド開発を行うときには、構造体を使用したバリデーションが一般的です。## Go言語でのバリデーション
Go言語では構造体を定義しそのフィールドに対してバリデーションルールを設定することができます。これにより、データの一貫性と正確性を確保し、エラーを未然に防ぐことができます。“` struct.go
type Person struct {
Name string `json:”name” binding:”required,min=3″`
Age int `json:”age” binding:”required,min=0,max=100″`
}
// required: `Name`, `Age`共にフィールドは必須で、空の値は許可されない
// min=3: `Name`フィールドの値は最低でも3文字以上でなければならない