Go関連のことを調べてみた2022年09月02日

Go関連のことを調べてみた2022年09月02日

Four keys を計測する CLI ツールを作った

# はじめに

Four keys とはソフトウェア開発の生産性を測定するのに利用される以下の4つの指標のことである([参考](https://www.devops-research.com/quickcheck.html))。

– デプロイ頻度(Deployment Frequency) ソフトウェアのデプロイ頻度
– 変更リードタイム(Lead time for changes) ある変更をソフトウェアに適用してから、その変更がリリースされるまでの時間
– 障害修正時間(Time to restore) ソフトウェアに障害が発生してから、その障害が修正されるまでにかかった時間
– 障害率(Change failure rate)ソフトウェアのデプロイのうち障害が発生したデプロイの割合

これらの指標を簡易に測定するための CLI ツールを作成した。

https://github.com/hmiyado/four-keys

この記事では、この CLI ツールについて紹介する。

# 使い方

## インストール

[Releases](https://github.com/hm

元記事を表示

はじめてのGo Modules

初めてGoの開発案件にアサインされたのですが、前担当から引き継いだGoのバージョンが1.10なのに対して今回の開発では1.18だったので色々戸惑いました。
その際Go Modulesって何?となって調べたので備忘録。

# Go Modules
– Go1.11以降で利用できる依存パッケージ管理ツール。
– go mod init [モジュールパス] と go mod tidyでgo.modとgo.sumを作成してソースコード内でimportに記載してる外部パッケージのダウンロードと依存関係の処理を行ってくれる。
– Go1.10まではGOPATH モード (GOPATH mode)でコード管理を行なっており、コード管理とビルドをGOPATHで指定されたディレクトリ下で行っていた。Go1.11以降はモジュール対応モード (module-aware mode)を使用することで任意のディレクトリでコード管理とビルドが行えるようになった。

## 前提
– Go 1.18
– 環境変数GO111MODULEは on 又は未指定
– MacOS Monterey 12.5.1

#

元記事を表示

wfs – Go で書き込み可能な io/fs

## wfs とは

[jarxorg/wfs](https://github.com/jarxorg/wfs) で開発している Go標準 の io/fs を拡張したライブラリです。 現在は以下のファイルシステムをサポートしています。

– osfs
– memfs
– s3fs
– gcsfs

## 開発の動機

Go で S3 や GCS を使うほとんどのプロジェクトで、クラウドストレージにアクセスするためのインタフェースを新しく定義し、開発用にローカルファイルシステムの実装、テスト用にメモリ上での実装をして切り替えれるようなコードを書いてきました。

Go1.16 から登場した io/fs は今のところ読み取り専用で、書き込みについては [proposal: io/fs: add writable interfaces](https://github.com/golang/go/issues/45757) などで議論されていますが簡単には進まなそうです。

その Issue でも紹介されている afero や billy は非常に優秀ですが S3 に対応していなかったりして微妙

元記事を表示

Goの構造体をJSON形式で出力するいくつかの方法

## はじめに

Goの構造体をJSON出力する方法をまとめてみました。

### 検証方法

以下のようなPerson構造体をJSON出力していきます。

“`go
type Person struct {
Name string
Age int
gender string
}
“`

また、JSON出力した結果を見やすくするために、`Mrashal`ではなく`MrashalIndent`を使ってフォーマットしたものを出力するようにしています。

“`go:main.go
package main

import (
“fmt”
“encoding/json”
)

func main() {
p := Person{
Name: “Mike”,
Age: 20,
gender: “male”,
}

m, _ := json.MarshalIndent(p,””,” “)
fmt.Println(string(m))
}
“`

## 方法1: そのままMarshalする

まずは、特に何もせずにそのまま出力すると以下のような

元記事を表示

GoでGormを利用してmigrateしたがDBの制約が反映されない

# はじめに

Goのテストを書いていた時にメールアドレスが一致したらエラーを返すテストを書いていました
なのになぜか200の成功ステータスが返ってくるので調べたところレコードが作成されていました
Gormで設定したユニークが効いていないようです

# 問題

以下のようなコードでテーブル定義を書いていました

“`go:user.go
Email string `gorm:”size:256 , not null , unique” json:”email”`
“`

しかしこれでは`non nul`や`unique`の制限がついていませんでした

MySQLで`desc users;`を確認してもやはり制約はついていません

# 解決方法

以下のように変更することで解決しました

“`go:user.go
Email string `gorm:”size:256;not null;unique” json:”email”`
“`

なんとなくで書いていたようです
テストを書くまで気づきませんでした

# おわりに

公式ドキュメントをしっかりみるようにすれば解

元記事を表示

GoのテストでJSONのレスポンスから値を取得して比較したい

# はじめに

Goのテストを書くときに、レスポンスのBodyの内容を比較する際に以下のようなコードを書いていました

“`
assert.Equal(t, w.Body.String(), “{\”msg\”:\”pong\”}”)
“`

しかし、この中の要素を取得してテストを書く機会が訪れたのでまとめます

# 問題

` bcrypt`を利用して、レスポンスのBodyにはいっている暗号化されたパスワードを取得して、それを複合して比較して同じことを確かめるテストを書こうとしました

そこでレスポンスから暗号化したパスワードのみを取得する必要がありました

# 解決方法

以下のようにすることでレスポンスからパスワードのみを取得することができました

“`go:controller_test.go
req, _ := http.NewRequest(“POST”, “/sign_up”, body)
req.Header.Set(“Content-Type”, “application/x-www-form-urlencoded”)
w := httptest.

元記事を表示

GORMを使用してMySQLに接続し、データベースの作成・削除とCRUD機能を実装する

# 概要
[GORM](https://gorm.io/ja_JP/)を初めて使用したので、基本的な使用方法をアウトプットのため投稿する。

■ Go version
go1.15.7
■ MySQL version
5.7.37

## GORMを導入する
以下のコードで必要なパッケージをインストールすることができる。
“`
go mod init [任意の値]
go get -u gorm.io/gorm
go get -u github.com/go-sql-driver/mysql
“`

# テーブルの作成
以下のコードでテーブルの作成・削除が可能であった。

### GOのコード
“`migrate.go
package main

import (
“gorm.io/driver/mysql”
“gorm.io/gorm”
)

type Data1 struct {
gorm.Model
Title string
Content string
}

func main() {
dsn := “[ユーザー名]:[パスワード]@tcp(

元記事を表示

【Go】Go言語の入門ーコメント、変数

# はじめ
  Go言語を勉強しはじめました。
  ポイントをメモします。

# コメント
インラインコメント
“`go
// コメント
“`
複数行コメント
“`go
/* 
  コメント
  コメント
  コメント
*/
“`

# 自動整形

goファイルを自動整形してくれる

“`go
$ gofmt [file-name]

“`

# 実行する時の入り口
実行する時、最初に呼び出す関数はmain関数である。

“`go
package main

func main(){
//main関数内に処理内容を記入する
}

“`

# 変数

## 変数宣言と代入

“`go
var 変数名 データ型 // 変数宣言
変数名 = 値 // 変数に値を代入

//例
var num int
num = 10
“`

注意点

– 変数を宣言した時点に、デフォルト値を代入される。 intとfloatの場合、デフォルト値は0である。
– データ型が自動推測されることができる。

“`go
var num = 10 //numのデータ型はin

元記事を表示

GCPのWorkbenchにgoを入れる

# はじめに
GCPのWorkbench(JupyterLab)にgoを入れたので備忘録として残します
Jupyter環境であれば同様の手順で入れられるかと思います。
goをgcpのワークベンチでインタラクティブに実行したいというニーズはほぼない気はしますが、そんなニッチな誰かの役に立てれば

# goをインストール

go**インストール**

“`
cd /usr/local
wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.14.2.linux-amd64.tar.gz
rm -rf go1.14.2.linux-amd64.tar.gz
“`

パッケージインストール先のディレクトリ作成

“`
sudo mkdir /var/www
sudo mkdir /var/www/go
sudo chown -R jupyter /var/www/go
“`

パスを通す

“`
vim ~/.bash_profile

以下を追加
export PATH

元記事を表示

Golangで関数にメソッドを生やす

# ある日

関数の型をdefined typeで定義していたとき、ふと思いました。「Golangはdefined typeで型を定義して、その型にメソッドを定義できる。一方関数がファーストクラスオブジェクトな言語であり、関数の型もdefined typeで定義できる・・・、なら関数の型にもメソッドを定義できるのでは?」と :thinking:

# 試してみた

“`golang
package main

import “fmt”

type F func() int

func (r F) Add(i int) F {
return func() int {
return r() + i
}
}

func (r F) Inc() F {
return r.Add(1)
}

func (r F) Calc() int {
return r()
}

func main() {
var f F = func() int { return 1 }
fmt.Printf(“%d\n”, f.Add(2).Inc().Calc())
}
“`

できました :co

元記事を表示

【Go】Go言語入門①ーGo言語の第一歩

# はじめ

 **Mac** でgo言語を勉強しはじめました。
 自分の成長を記録したいので、記事をアップロードしました。

 macOS Big Sur : 11.6.1

# インストール
HowmebrewでGoをインストールする。
“`
$ brew install go
“`

### バージョン確認
インストールをしてから、バージョンを確認する
“`
$ go version
go version go1.19 darwin/amd64
“`

# goファイルを作成
テストファイル(hello.go)を作成する。
“`
$ touch hello.go
“`

hello.goファイルに下記のソースコードを記入する。

“` go
package main

import “fmt”

func main() {
fmt.Println(“hello world!”)
}
“`
 
編集してから、実行する。

# 実行

## 実行方法1
ビルドして実行する。
“`
$ go build hello.go
“`
同じディレクトリにバイナリデータ(h

元記事を表示

GOLangでフィボナッチ数を計算した

## はじめに
直近Go言語を勉強していますが、なんか数学問題を解けてみまたいため、[フィボナッチ数](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0)を計算できるロジックを作成しました。

## 環境
window 10
VSCode

## Target
以下の結果を出力する
“`
フィボナッチ数:(0,1,1,2,3,5…)
“`

簡単に回帰関数を利用して、作りました。

“`go:package.go
package main

import “fmt”

func fibonacci() func(x int) int {
return func(x int) int {
if x < 2 { return x } f := fibonacci() return f(x-2) + f(x-1) } } func main() { f := fibonacci() for i := 0; i

元記事を表示

go installしたバイナリをscratchイメージで動かす場合の注意点

# TL; DR

– webサーバー等netパッケージを使っているバイナリを `go install` する場合は `CGO_ENABLED=0` をつける
– 付けないと `no such file or directory` と出てしまう
– netパッケージをimportしたバイナリはダイナミックリンクでビルドされてしまうのが原因

# はじめに

[gRPC UI](https://github.com/fullstorydev/grpcui) [^1]のバイナリをマルチステージビルドしたら、`no such file or directory` と出て実行できませんでした。

“`bash
$ docker build .
Sending build context to Docker daemon 9.216kB

Successfully built 53b474247144
$ docker run -it –rm 53b474247144
exec ./grpcui: no such file or directory
“`

# 原因

元記事を表示

Go(gin)のAPIテストでテストが止まってしまい終了しない

# はじめに

GoのAPIテストを書いていて問題が発生したのでまとめます
ネットを調べたところ同じ現象が起きていなかったので、初心者の方の参考になればと思います

# 問題

ginで作成したAPIに対してリクエストが200返ってくるか確かめるコードを書いたのですテストが終わらず止まってしまいました

“`go:main.go
package main

var router *gin.Engin

func setupRouter() *gin.Engine {
r := gin.Default()
r.GET(“/ping”, func(c *gin.Context) {
c.String(200, “pong”)
})
r.Run(“:8080”)
router = r
}

func main() {
r := setupRouter()
}
“`

“`go:main_test.go
package main

import (
“net/http”
“net/http/httptest”
“testing”

“github.com/s

元記事を表示

Go(Gin)でfrom-dataをPOSTするテストを書く

# はじめに

最近GoのPOSTに関する記事を挙げていました。
やっと初めて作成したAPIがテスト段階に移り、POSTのテストを書いていたのですがテストでPOSTにどのようにデータを渡すのかに時間をとられたのでまとめます

# 問題

今回はフォームデータをPOSTするテストを書いていました
以下のようなコードを書いたのですが、ginで`c.params`で値を取得しても値がありませんでした
bodyで渡していたのでそれをform-dataで送る必要がありました

“`go:controller_test.go
jsonBody := []byte(`{“content”:”hoge”,”done”:false}`)
req, _ := http.NewRequest(“POST”, “/task”, bytes.NewBuffer(jsonBody))
“`

# 解決方法

以下のようにform-dataを作成してPOSTすることでうまくいきました

“`go:controller_test.go
(省略)
form := url.Values{}
form.Ad

元記事を表示

SQLBoilerで INSERT ON DUPLICATE KEY UPDATE したい

# モチベーション

多くのプロジェクトではレコードを一度で挿入または変更したいという要望があると思います。そんなときDBがMySQLであればBULK INSERTをしたいと思います。ですが、残念ながら今のプロジェクトで用いているSQLBoilerにはBULK INSERTの機能がありません(というか、多くのORMでないと思います)。しかし、SQLBoilerでは独自テンプレートを記述できるため、誰かがやっているだろうということで探すとこちらの記事が見つかりました。

https://qiita.com/touyu/items/4b25fbf12804f12778b7

今のプロジェクトではモデルでIDの生成を行っているため、何も問題なく利用させてもらいました。めでたしめでたし・・・のはずだったのですが、プロジェクトで開発を進めていくうちに、今度は `INSERT ON DUPLICATE KEY UPDATE` に相当する機能が必要となってきました。

せっかくテンプレートを作れて、元々SQLBoilerには`Upsert`があって、先程の記事を見つけたことでBULK INSERTの

元記事を表示

Tagliatelleで構造体のJSONタグのtypoを防ぐ

Go強化月間とのことなので、Go関連の記事を上げていこうと思います。

https://qiita.com/official-events/ae80b010f51f7018891a

# TL; DR

– `Tagliatelle` を [golangci-lint](https://golangci-lint.run/) に設定して、JSONタグをスペルチェックしよう

https://github.com/ldez/tagliatelle

# はじめに

Goで構造体をJSONにmarshal/unmarshalする際、フィールドのタグに対応するキーを指定することが可能です。Goのフィールドは慣習的に `PascalCase` ですが、JSONのキーは `snake_case` にしたいという場合は多いと思います。

“`go
type Person struct {
GivenName string `json:”given_name”`
FamilyName string `json:”family_namae”`
Age int `json:

元記事を表示

Go言語 – Slice / 配列 を for~range で展開してポインタを append すると全部同じ値になる

# 参考

>Goにおいてスライスおよびマップをforで回す際には「rangeで取ってきている値は常に同じメモリアドレスに格納される」ようになっています

https://zenn.dev/canalun/articles/go_for_loop_pointer_trap

後述するが、このせいで一部挙動に問題が出るようだ。

# TL; DR

あまり深く考えずGolangの仕様と割り切ったら良い気がした。

こちらも後述するがループ内で変数を再定義することで回避できる。

# 例

“`go
package main

import “fmt”

func main() {
numbers := []int{1, 2, 3}

for _, number := range numbers {
fmt.Println(number)
fmt.Println(&number)
}
}

// 結果
// 1
// 0xc0000b2000
// 2
// 0xc0000b2000
// 3
// 0xc0000b2000

“`

この例でいうと number

元記事を表示

Go + YouTube Data API v3 で特定のチャンネルの動画データ一覧を取得する

# 目的
YouTube Data API v3を使って、特定のチャンネルにアップロードされた動画に関するデータをすべて取得することが目的です。
APIの仕様上取得できる件数に制限があったり、動画のIDであるVideoIdの一覧を取得する際にちょっと苦労ので、それらを中心に解説していきますが、基本的には以下のリファレンスを見れば、時間はかかるかもしれませんが大体の操作は簡単に実装できるかと思います。
[YouTube API Reference](https://developers.google.com/youtube/v3/docs?hl=ja)

# 前提
* Go言語を使える環境が前提です
* 使っているバージョンは `1.18.3`
* 以下の記事を参考に、YouTube Data API v3を有効にし、APIキーが取得済み
[YouTube Data API v3 を使って YouTube 動画を検索する](https://qiita.com/koki_develop/items/4cd7de3898dae2c33f20)

# 流れ
私のGitHubページに以下の一

元記事を表示

小ネタ/Open API 3.0 ジェネレータ oapi-codegen v1.11.0 のコード自動生成の方法

社内で使う管理用のちょっとした API を OpenAPI & Go(golang) で作るべく **[oapi-codegen](https://github.com/deepmap/oapi-codegen)** を(過去の文献を参考に)使おうとして、

`configuration error: package name must be specified`

に阻まれ、回避方法を探したら **[リリース情報のページ](https://github.com/deepmap/oapi-codegen/releases/tag/v1.11.0)** にちゃんと書いてあった、というだけのメモ書きです。

(ついでにいうと、最初に探し当てていた文献にもちゃんと書いてありました…)

## 以前のバージョンでの使い方

こんな感じで紹介されている例が多かったと思います。

“`sh:
go get github.com/deepmap/oapi-codegen/cmd/oapi-codegen
oapi-codegen 【スキーマ定義の .yaml ファイル】 -package 【パッケ

元記事を表示

OTHERカテゴリの最新記事