- 1. テストコード例(Go)
- 2. なっとく!関数型プログラミング を読んで関数型プログラミングを学んだ
- 3. Docker構築にてGO言語のバージョンが原因でmailpit コマンドをインストールできなかった場合の対処法
- 4. 配列(Array)とスライス(Slice)について
- 5. RDBの半構造化データをスキーマ定義してアプリで扱いやすくする
- 6. [GO+PostgreSQL+GitHub Actions] サービスコンテナを使ってdocker-composeを使わずにテストを実行しよう
- 7. Go言語で関数にデータを渡す方法について: 値渡しとポインタ渡しの違い
- 8. トランザクションの終了について
- 9. Goのポインタの簡単な例
- 10. エラーハンドリングの整理(Go)
- 11. Go言語について
- 12. 今後の勉強内容について(React + Go)
- 13. Makefile で同じようなコマンドのターゲット群をまとめる方法
- 14. 【Golang + Gin】JSON Web Token(JWT)でサクっとREST-API実装
- 15. 【Golang】無名関数を関数の引数もしくはリターンで使用する
- 16. golang/goのコードリーディングでVSCodeのコードジャンプが効かない
- 17. zerologでCloud Logging用の構造化ログを作る
- 18. Goで簡易なコマンドラインセレクタを作りました。
- 19. Go、Rust、Pythonで実装したAPIサーバーの負荷試験比較
- 20. 【Go】マップのキー・バリューを昇順・降順にソートする
テストコード例(Go)
## はじめに
Goを使用したテストコード例を記載します。
テスト例の記載に伴い、テストパターン、網羅性を少し検討してみました。## テストコード例
以下は、Go言語で書かれたGORMを使用して、データベースにユーザーが存在しない場合に新しいユーザーを追加するテストケースの例です。### テストケースの概要
– **関数の概要**: 特定の `UserID` と `TargetUserID` でユーザーを検索し、存在しない場合は新しいユーザーを追加する。
– **テストの目的**: ユーザーが存在しない場合に、新しいユーザーがデータベースに正しく追加されるかを確認する。### テストコード
“`go
package mainimport (
“log”
“testing”
“time”“gorm.io/driver/sqlite”
“gorm.io/gorm”
)type User struct {
UserID int `gorm:”primaryKey”`
TargetUserID i
なっとく!関数型プログラミング を読んで関数型プログラミングを学んだ
[EDOCODE](https://www.edocode.co.jp/)でエンジニアをしているYutakaです。
– こちらは社内勉強会で発表した資料を元にしています。
– 関数型言語の知識がほとんどないエンジニアが[なっとく!関数型プログラミング](https://www.shoeisha.co.jp/book/detail/9784798179803)で学んだ用語を一部まとめました。原著は[Grokking Functional Programming](https://michalplachta.com/book/)です。本書はScalaとJavaで説明がされていますが、できる限り社内で使われている言語(Go, JavaScript, TypeScript)でサンプルコードを記載しました。
– 書籍のソースコードは[こちら](https://github.com/miciek/grokkingfp-examples)に全て公開されています。
# そもそも関数型プログラミングとは?
プログラミングのパラダイムには大きく①命令型プログラミング②宣言型プログラミングがあり
Docker構築にてGO言語のバージョンが原因でmailpit コマンドをインストールできなかった場合の対処法
# Dockerfile内で
– Go 言語をインストール(mailpit コマンドを go install でインストールするために必要)
RUN apt install -y golang-go– mailpit コマンドをインストール
インストール先が /root 配下だと Web サーバーから実行できないので、
/usr/local/bin へ移動
RUN go install github.com/axllent/mailpit && mv /root/go/bin/mailpit /usr/local/bin以前はこの記述でmailpit コマンドが機能したのですが
最近、新たにDocker構築すると
RUN go install github.com/axllent/mailpit && mv /root/go/bin/mailpit /usr/local/bin
の箇所で失敗しました。
原因を調べているとGo 言語のバージョンが原因のようでした。Go 言語のインストールで仮想サーバーにインストールされるGo 言語のバージョンはgo-1.19
mailpit
配列(Array)とスライス(Slice)について
配列(Array)とスライス(Slice)について
それぞれの特徴をまとめた# 配列(Array)
・配列は固定長のデータ構造であり、要素数を宣言時に指定し、後から変更することはできない。
・配列は要素の型と要素数を指定して宣言する例えば、 var arr [5]int は、int型の要素を5つ持つ配列となる
・配列はメモリ上に連続した領域を確保し、要素のインデックスを使ってアクセスする
・配列は静的なサイズを持つため、動的に要素を追加したり削除したりする必要がある場合には適していない“`
// 配列の定義
var arrayName [size]dataType// 例: 整数型の配列を定義する
var numbers [5]int// 初期化された配列
var numbers = [5]int{1, 2, 3, 4, 5}// 要素数を省略することもできる(要素数は初期化された要素の数で決まる)
var numbers = […]int{1, 2, 3, 4, 5}// 特定のインデックスに値を設定する
numbers[0] = 10
“`#
RDBの半構造化データをスキーマ定義してアプリで扱いやすくする
## はじめに
RDBでもJSONなどで半構造化データを保存することはありますよね?データに柔軟性を持たせるためとはいえ、データのパターンやパターンごとに持ち得るプロパティ、各プロパティの型にある程度制限をかけたいケースは少なくないと思います。
今回はgo製アプリケーションでの読み書きに絞って、データの持ち方・制限のかけ方を検証してみようと思います。
記事中のコードは関連箇所のみ抽出して記述しています。リンク先のコードで実際の動作を確認できます。
https://github.com/h-rym/qiita_sample_code.git## 前準備
[docker](https://hub.docker.com/_/postgres)でもなんでも良いのでpostgresが起動している前提で進めます。
“`bash
docker run –name postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=test_database -p 5432:5432 -d postgres
“`今回はシンプルにjsonb型
[GO+PostgreSQL+GitHub Actions] サービスコンテナを使ってdocker-composeを使わずにテストを実行しよう
## 前提
– GitHub Actionsの基本的な用語についてある程度理解している
– 言語はGOを使用
– DBはPostgresを使用## サービスコンテナとは
ワークフロー中でアプリケーションをテストもしくはビルドするのに必要なサービスを提供するためのDockerコンテナです
サービスコンテナを使うことでワークフロー内で例えばdocker-composeを使って自前でDBを作成せずにテストを実行することができます
runner内のリソースは限られているのでGitHub側で用意するサービスコンテナなどを使うケースが多いです
また、docker-composeを使わずにワークフローを実行するのでコンテナの起動時間分ワークフローの時間を短縮できます
今回はPostgresのサービスコンテナを使ってテストコードを実行させます## ファイル構成
ファイル構成は以下の通りです
“`
❯ tree
.
├── .github
│ └── workflows
│ └── test.yml
└── application # GOのプロジェクトファイルおよびgo.m
Go言語で関数にデータを渡す方法について: 値渡しとポインタ渡しの違い
Go言語において、「値渡し」と「ポインタ渡し」は関数にデータを渡す二つの基本的な方法です。
– 値渡し (Value Passing)
値渡しでは、関数に値のコピーを渡します。この方法で関数に値を渡すと、関数内で値を変更しても、元の値には影響を与えません。つまり、元のデータは安全で、変更されることはありません。これにより、予期しない副作用を避けることができますが、大きなデータ構造をコピーするとパフォーマンスが低下する可能性があります。“`go
func addOne(val int) int {
val += 1
return val
}func main() {
original := 2
new := addOne(original)
fmt.Println(original) // 出力: 2
fmt.Println(new) // 出力: 3
}
“`https://go.dev/play/p/pS8rcsaUXT1
– ポインタ渡し (Pointer Passing)
ポインタ渡しでは、値のアドレス
トランザクションの終了について
## はじめに
トランザクション処理で、エラーが発生してもトランザクションが終了していない場合の対応例を記載します。Goを例にします。
変更箇所は、トランザクションを閉じる処理がないので明示する、という修正です。## 例
変更前
“`golang
result := tx.Where(“user_id = ? AND target_user_id = ?”, checkUserID, checkTargetUserID).First(&matchedUser)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
// レコードが見つからなかった場合の処理
newUser := User{UserID: checkUserID, TargetUserID: checkTargetUserID, Name: “New User”, Timestamp: time.Now()}
// newUser := User{UserID: checkUserID,
Goのポインタの簡単な例
## はじめに
Go言語での実体とポインタ、アドレスの扱いについて整理します。## 値渡しとポインタ渡しの違い
Go言語での実体とポインタ、アドレスの扱いについて、簡単な例を示します。
以下の例では、関数に値を渡す際にコピーが発生する場面と、ポインタを使って直接メモリアドレスを参照する場面を比較しています。### 実体のコピーが発生する例
値渡し(コピー渡し)
“`go
package mainimport “fmt”
type Person struct {
Name string
Age int
}// passByValue はPersonのコピーを受け取る
func passByValue(p Person) {
p.Age = 30 // この変更はコピーにのみ影響する
fmt.Println(“Inside passByValue:”, p)
}func main() {
p := Person{Name: “Alice”, Age: 25}
fmt.Println(“Original person:”, p)pa
エラーハンドリングの整理(Go)
## はじめに
Goでのエラーハンドリングについて整理します。
大体把握できたと思いますので、メモっておきます。## エラーハンドリング例
### コード例“`go
// メソッド呼び出し
if err := executeTransaction(db); err != nil {
fmt.Printf(“Transaction failed: %v\n”, err)
} else {
fmt.Println(“Transaction succeeded.”)
}func manageUser(tx *gorm.DB, checkUserID int, checkTargetUserID int) error {
var matchedUser User
result := tx.Where(“user_id = ? AND target_user_id = ?”, checkUserID, checkTargetUserID).First(&matchedUser)if result.Error != nil {
Go言語について
# Go言語についての概要と学習内容について
go言語を勉強にするにあたり、ますはgo言語についての概要をまとめていく
調べてヒットした特徴をコピペし、それぞれの感想を書いてみた### 概要
・シンプルで読みやすい構文: Go言語は、C言語のような伝統的な構文を持ちながら、冗長さを排除し、シンプルで読みやすいコードを書くことができます。
→まあ分かる・効率的な並行処理: Go言語は、ゴルーチン(Goroutine)とチャネル(Channel)という仕組みを使って並行処理をサポートしています。これにより、軽量で効率的なスレッドの生成と通信が可能になります。
→並行処理に関する知見が不足しているため正直ぱっとイメージが沸かない(要調査)・静的型付けと型推論: Go言語は静的型付け言語ですが、変数の型を推論する機能も持っています。これにより、型の記述が簡潔になります。
→いいね・ガベージコレクション: Go言語はガベージコレクションをサポートしており、メモリ管理を開発者が手動で行う必要がありません。これにより、安全で信頼性の高いコードを書くことができます。
→いいね・クロ
今後の勉強内容について(React + Go)
知人からホームページ作成を依頼されており、その中でブログの機能も追加してほしいとのことから興味があったgo+ reactで作成することにした。
こちらは無料で提供するかわりに時間がかかってもよいと言われているのでお言葉に甘えてじっくり調べながら作成していく。
goもreactも一旦は参考書を読んでいるがあまり身についていないような気がしているため備忘としてまとめていく。
3日坊主にならないよう気を付ける。。
Makefile で同じようなコマンドのターゲット群をまとめる方法
# tl;dr
– [Multiple Targets](https://www.gnu.org/software/make/manual/make.html#Multiple-Targets) 使うと、複数ターゲットを1つのターゲットで表現できて便利
– 複数ターゲットがほぼ同じコマンドで構成されるときに使えて便利
– Makefileは奥が深い
# はじめにほぼ同じコマンドで、パスだけ異なるターゲットを作成することがあり、そのときに知ったMakefileの機能を紹介します。
コードは以下においています。https://github.com/haru-256/blog-makefile-multiple-targets-20240501
# Makefileで複数ターゲットを1ターゲットで表現する方法
Golangでは、`cmd/` ディレクトリ配下に実行エンドポイントを複数置くことがあります。例えば、Web APIサーバーを開発する場合、APIサーバーの実行エンドポイント(`cmd/api/main.go`)と、APIサーバーが参照するDBのマイグレーションツール (`
【Golang + Gin】JSON Web Token(JWT)でサクっとREST-API実装
**Golang + Gin + JSON Web Token(JWT)**
![Gopher.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480626/07c43ac8-6ca2-031c-d9d6-5e5b98d304bc.png)
# はじめに
今更ながらですが、GoとJSON Web Tokenで認証認可周りを簡単に遊んでみました。
ついでに、今までEchoを多く触れていたのですが、Ginは触れていなかったのでこの機会にやってみようということでフレームワークはGinを採用しています。
Goの業務経験は半年ほどで、それ以外はプライベートで少し触るだけです。
なので私自身も完全に理解しているわけではありませんが、自身の勉強とナレッジを兼ねて記事にさせていただきます。## 成果物
早速コードから。https://github.com/chalmeal/go-gin-auth
* JSON Web Token(以下JWT)を利用してユーザーを認証し、アクセストークンを発行すること
*
【Golang】無名関数を関数の引数もしくはリターンで使用する
自分に対する備忘録として残すもの
## 無名関数を関数の引数で使用する
サンプルコード“`Go
package mainimport “fmt”
// 関数applyFunctionは、無名関数を引数に取り、その関数を実行します。
func applyFunction(f func(int) int, x int) int {
// 引数として渡された無名関数を実行し、結果を返す
return f(x)
}func main() {
// 無名関数を作成し、その場で引数として渡す
result := applyFunction(func(n int) int {
return n * 2
}, 5)// 結果を出力
fmt.Println(“Result:”, result)
}
“`引数に渡す無名関数は以下の通りでも良い。(個人的にはこちらの方が読みやすいから好き)
“`Go
package mainimport “fmt”
// 関数applyFunctionは、無名関数を引
golang/goのコードリーディングでVSCodeのコードジャンプが効かない
# 結論
developブランチを参照するのではなく、インストールされているバージョンのブランチを参照する
“`
git checkout go1.22.2
“`# memo
goplsで以下のようなエラーが出ていた。
原因はdevelopブランチが開発中のgo1.23のコードになっていたためである。“`
go env env,json,GOMOD,GOWORK: Command failed: /opt/homebrew/bin/go env -json GOMOD GOWORK go: downloading go
“`
zerologでCloud Logging用の構造化ログを作る
Google Cloud上でアプリケーションを動かす際に、[Cloud Loggingが求める構造](https://cloud.google.com/logging/docs/structured-logging)を使うと、Cloud TraceやError Reportingなどと相性がいいので、Cloud Logging用にログの形式を設定する。
**logger側**
“`go
package logimport (
“context”
“fmt”
“os”
“path”
“runtime”
“strconv”“cloud.google.com/go/compute/metadata”
“github.com/rs/zerolog”
“github.com/rs/zerolog/log”
“go.opentelemetry.io/otel/trace”
)// Google Cloud Project ID
var projectID string// init Loggerの初期設定を行う。
func init() {
project
Goで簡易なコマンドラインセレクタを作りました。
## 作成したもの
RustでCLIのメモツールを作成する際、メモ一覧を表示して選択する機能が欲しいと考え、簡易なコマンドラインセレクタを作成いたしました。本当はRustで作成したかったのですが、[Ratatui](https://ratatui.rs/)などのTUIツールをうまく使いこなすことができなかったため、Goで書くことにしました。
GoのTUIライブラリである[tview](https://github.com/rivo/tview)は非常に使いやすく、簡単に作成することができました。
mattnさんの[cho](https://github.com/mattn/cho)にとても影響を受けており、かなり簡易な作りにしてあります。
(mattnさんのchoはWindowsでも使えるため、高度な実装をしていると思います。)## 使い方
slctは、標準入力から受け取った文字列を改行で区切り、それを選択肢として表示することを目的としていますので、単体で使うことはまずないと思います。
実際に使用する際は、lsやfindなどのコマンドとパイプラインを組み合わせて
Go、Rust、Pythonで実装したAPIサーバーの負荷試験比較
## はじめに
みなさん様々な言語でAPIサーバーを立てて負荷試験を実施したことはありますか。私自身、業務でPythonのアプリケーションに対して負荷試験を実施した経験があります。
その際にPythonの速度観点の不安定さを目の当たりにしたと同時に、別の言語ではどのような違いが生まれるのだろうか、という疑問を持ちました。
そこで今回は、簡単ではありますがGoとRustとPythonでそれぞれAPIサーバーを立てて負荷試験をしてみます。
## 負荷試験対象のAPIサーバー
今回は(1) Hello, World!を返すAPI(2) ファイル読み込みAPI(3)1秒待ってから応答するAPIの3つを実装します。(1)はAPIサーバー自体の応答速度の計測、(2)はメモリを消費する処理が生じた場合のAPIの応答速度の計測、(3)は待ち時間発生している時のAPIの応答速度の計測することが目的です。
(2)について、ファイル読み込みAPIとはAPIが叩かれた際に特定のファイルを読み込んで完了メッセージを送るAPIを意図しています。(POSTではなく、 GET)
読み込む対象のファイ
【Go】マップのキー・バリューを昇順・降順にソートする
# はじめに
Goのmapは順序を保持しないため、並び替えたい場合はひと工夫が必要です。
以下のようなマップをキー・バリューそれぞれで昇順・降順に並べ替えていきます。
“`go
m := map[string]int{
“Taro”: 23,
“Keiko”: 41,
“Jun”: 11,
“Azusa”: 16,
}// マップは順序を保持しない
for k, v := range m {
fmt.Printf(“Name: %s, Age: %d\n”, k, v)
}
“`![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911578/1bd39d49-ef5d-5a21-039c-393540a67c2c.png)
## キー(文字列)でソートする
### 昇順
“`go
// 先にキーだけソート
keys := []string{}
for k := range m {
keys = append(ke