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

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

SpannerマイグレーションツールRatchetを作りました

Spannerのマイグレーションツール [Ratchet](https://github.com/hiracchy/ratchet) を作りました。

## 背景
プロダクションで使えるSpannerのマイグレーションツールを調査していて、
wrenchが良さそうだったのですが、以下のような問題がありました。

– マイグレーションファイルの名前が連番で作られるため、複数人の開発で競合する
– DMLやパーティション化DMLへの対応がない(現在は、一部対応があるようです)

そこで、それらを解決したシンプルなマイグレーションツールを作りました。

## インストール
[リリースページ](https://github.com/hiracchy/ratchet/releases/latest)からダウンロードしてパスを通してください。

## 使い方
以下のステップで使えます。シンプルに使えるように心がけました。

### 1. マイグレーション用のテーブルを作成する(1回目のみ実行が必要)
“`console
$ ratchet init -p {プロジェクトID} -i {インスタ

元記事を表示

Quicとは何か?

# QUICとは
* QUICとは、Googleが高速化を目指し、UDPソケット上に用意したプロトコルです。
* なぜ、Googleはこのquicを作り出したのかというと、それは多分HTTP/2がTCPソケットの上に実装されたものであるからだと考えられます。
* どうしても、TCPは接続初期に何度か往復した通信をする必要があり、エラーや順序の整列をきちんとするために受信通知を返す必要があります。つまり高機能ではあるが、パフォーマンスへの影響が少なからず起こるということです。

**では、UDPはどうか?**
UDPは、TCPで行われている再送処理や輻輳制御などを取り払い通信回数を減らすことでパフォーマンスへの影響を減らしたプロトコルです。

**では、QUICはどうなのか?**
QUICでは、TCPが行っているようなパケットロス時の再送処理や、輻輳時の制御などを自前で実装しています。
また、TLSの機能を保持しており、シーケンス番号などのデータも隠蔽しています。

**じゃあ、HTTPSでのTCPと変わらないのでは?**
HTTPSでは、TCPのハンドシェイク後にTLSのハンドシェイク

元記事を表示

[Go] net/httpのややこしい関数名・型名を整理する

## 背景

– GoのHTTP通信に使う標準ライブラリnet/httpには、型名や関数名として似た単語がたくさん出てくる。Handler, HandleFunc, Handleなど。
– それらを整理しておきたい!

## net/http.Server

– Goでサーバを立てるにはServer構造体を初期化しなければならない。
– サーバを立てるのに、Server構造体を初期化するというのは、わかりやすい。

“`go
$ go doc net/http.Server

type Server struct {
// Addr optionallu specifies the TCP address for the server to listen on,
// in the form “host:port”. If empty, “:http” (port 80) is used.
Addr string

Handler Handler // handler to invoke, http.DefaultServeMux if nil

元記事を表示

reflectパッケージで構造体情報を取得

# reflectパッケージ
GO言語におけるreflectパッケージですが、
発生遅くありません?

思いついてから実装まで一体何フレかかってんだと。
特にしばらく実装から離れていると、さらに時間がかかりますよね。

そこで、そこらへんを少しずつTipsとしてまとめていければと思ってます。

# 構造体の変数名とタグを取得
“`
package main

import (
“fmt”
“reflect”
)

// 構造体
type Skill struct{
p int64 `tag:”弾拳”`
pp int64 `tag:”烈掌”`
ppk int64 `tag:”烈空脚”`
}

// 構造体情報を出力
func do(I interface{}) {
v := reflect.ValueOf(I)
t := v.Type()
for i := 0; i < t.NumField(); i++ { name := t.Field(i).Name tag := t.Field(i).Tag.Get("tag") fmt.Println("name=

元記事を表示

【Go】文字列を一部置換と全置換する方法

## 準備
文字列の置換には`strings`と言うpackageを使用する為、まずはimportを行います。
https://golang.org/pkg/strings/

“`go:import
import “strings”
// 以下でも良い
import (“strings”)
“`

## 特定の数のみ置換したい場合
1つだけ置換したい場合や2つなど複数置換したい場合は、`replace関数`を使います。
### 軽く説明
“`go
func Replace(s, old, new string, n int) string
“`
第1引数:置換したい文字列
第2引数:置換前の値
第3引数:置換後の値
第4引数:置換したい数(int型)
返り値:置換された結果の文字列
(stringsのReplace関数なので`strings.Replace()`と言う使い方)

### 具体例
“`go:一部置換
var title string = “SSSS.GRIDMAN”
fmt.Println(title) // => SSSS.GRIDMAN

// 1つのみ置

元記事を表示

【Go】文字列から数値への変換、数値から文字列への変換

## 準備
`strconv`と言うpackageを使用する為、まずはimportする。
(`strconv`に変換する為の色々な関数が存在。詳細は下記URL参照。)
https://golang.org/pkg/strconv/

“`go:import
import “strconv”
// 以下でも良い
import (“strconv”)
“`

## 文字列から数値への変換
文字列から数値への変換には`Atoi関数`を使用。

“`go
var str string = “100”
fmt.Printf(“型:%T”, str, str) // => 型:string

// string -> int
var num int
num, _ = strconv.Atoi(str)
fmt.Printf(“型:%T”, num) // => 型:int
“`

`Atoi関数`が変数を2つ(`num`と`_`)を取っている理由

ドキュメントに`func Atoi(s string) (int, error)`と書か

元記事を表示

anyenvでgoの開発環境を構築

## goenvのインストール
“`bash
$ anyenv install goenv

/var/folders/hk/_11v61jd5kn65bw_v55f9fjr0000gn/T/goenv.20210214134326.1521 ~
Cloning https://github.com/syndbg/goenv.git master to goenv…
Cloning into ‘goenv’…
remote: Enumerating objects: 69, done.
remote: Counting objects: 100% (69/69), done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 14402 (delta 15), reused 22 (delta 8), pack-reused 14333
Receiving objects: 100% (14402/14402), 2.61 MiB | 685.00 KiB/s, done.
Resolving d

元記事を表示

絵文字生成する slack コマンド作成

先日、絵文字生成を行なうコマンドとサーバを作成したため、それに合わせて slack のコマンドを作成してみました。軽いツールの説明と導入手順を書いていきます。

## ツール説明

### 絵文字作成ツール

まず、絵文字作成ツールです。
https://github.com/komem3/wordimg

入力したテキストから絵文字を作成してくれるコマンドラインツールが欲しいと思い作成しました。 Go で作ったのでコマンドとサーバのどちらも作成してみました。サーバの URL は https://wordimg-otho5yxlgq-an.a.run.app/wordimg です。[絵文字ジェネレーター](https://emoji-gen.ninja) のコマンドライン版みたいのを作りたいなというモチベーションで作成しましたが、あちらの完成度が高いのでまだまだ改良の余地があるなと感じております。

ちなみに、`https://wordimg-otho5yxlgq-an.a.run.app/wordimg?text=helloworld` というURLを見ると以下のようになります。更新

元記事を表示

AtCoder Regular Contest 112のメモ

# 前置き

Atcoderをやってみたので、自分用のメモです。
あとから加筆・修正する予定です。

# 問題

https://atcoder.jp/contests/arc112

# A

“`Q_A.go
package main

import (
“bufio”
“fmt”
“os”
“strconv”
)

var sc = bufio.NewScanner(os.Stdin)

func nextInt() int {
sc.Scan()
i, e := strconv.ParseInt(sc.Text(),10,32)
if e != nil {
panic(e)
}
return int(i)
}

func main() {
sc.Split(bufio.ScanWords)

var T int
fmt.Scanf(“%d”, &T)

var L, R int
var count int

counts := make(

元記事を表示

Paizaでも好きなエディタ使いたい!

Qiita初投稿です。
今回は自作のCLIツールを紹介します。

## TL;DR

– Paizaのスキルチェックを始めたが、Webページ上のエディタは使いづらいので、ローカルのエディタでコーディング&テストできるようなCLIツールを作ってみた

## 制作物

[![pz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565704/2ffbaef2-b79a-c51d-e554-85edc7a6654c.png)](https://youtu.be/FTqw5-lfkNE)
(↑クリックするとYouTubeへジャンプします。)

リポジトリはこちら → [reeve0930/pz](https://github.com/reeve0930/pz)

## なぜ作ったか

ものすごく個人的な話なので、興味のない人は読み飛ばして下さい…

最近、[AtCoder](https://atcoder.jp/)で競技プログラミングを始めました。
AtCoderで過去問を解いて色々と勉強していたのですが、
[P

元記事を表示

15rep – 独自Errorの作成 ~ 備忘録

# 書いた理由
– API作成しているときにエラーって返すと思います。その際に独自でErrorを定義し返すというよくある内容をメモ化(作り込まず簡易)

# 独自エラーの定義
– 独自のエラー型を定義するやり方
– Goの組み込みのエラー型(error)は以下のような型です。
(errorインタフェース)

“` go
type error interface {
Error() string
}
“`
– func Error() string を実装した型は全てerrorインターフェースが実装されているものとみなす。(便利)

# 実際に書いてみた
“` go
package main

import (
“fmt”
“net/http”
“encoding/json”
)

type ErrorMessage struct {
Code int
Message string
}

// Errorメソッドさえ定義されていれば良い
func (e *ErrorMessage) Error() string {
return e.Message
}

元記事を表示

【Go】一体いつからappendの引数に与えた変数が不変だと錯覚していた?

# 結論

“`go
slice = append(slice[:idx], slice[idx+1:]…)
“`

上記のようにできない場合で、どうしても元のスライスを保持したいときはmake&copyしましょう

“`go
slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
newSlice := make([]int, len(slice))
copy(newSlice, slice)
“`

https://play.golang.org/p/T9su3lB5xi5

# はじめに
スライスを使うときに無意識でappendを使うかと思います。
単純に追加するだけであれば、至って普通の挙動を示しますが、とある条件の時に
想定しない挙動になることがあります。

# 実験内容
配列の中から特定のインデックスにある値を削除する処理です。
例えば以下のようなコードがあった場合はどうでしょうか?

“`go:main.go
package main

import “fmt”

func main() {
slice := []in

元記事を表示

Hugo を導入する過程で go の環境とか作る

github の hugo を clone して docker build すれば docker の環境は出来るので、書くまでもないと言えば書くまでもない。

# TL;DR
正式版と Draft 版の二つの Hugo サーバを立ち上げ、Draft でうまくいったら git をつかって、正式版から pull して反映するという環境を作りたい。

そのために hugo + git の docker 環境 + ホスト側に同じバージョンの hugo が必要になった。go の環境はあまり関係なかった、、、

# まずは出来た Docker のイメージを使う
sinby/hugo-git:0.80.0 で公開しているので

“`
% sudo docker run –rm -v =0/site:/site sinby/hugo-git:0.80.0 new site .
“`

こんな感じでまずは site を構築する。=0 は tcsh の機能なので、bash 使っている人とかは $(pwd) とかに置き換えることになるでしょう。

ところで、いったいこれはなにをしているのか?

##

元記事を表示

【Go Lang】WebFrameWork使ってみた1 Gin

# はじめに

筆者について。
– SIer界隈の人
– 東京以外の地方都市在住
– 30代後半

GoLang案件がなんだか増えてきた。
ということで導入のテンプレートになるWebFWを作りたい。
そのベースとなるWebFrameWorkについて、実際に使ってみて導入の検討をしていくことにする。
観点は以下!

– 人気
– 学習しやすさ
– 特徴

# 使ってみるWebFrameWork
[GitHubリポジトリのスター数でOSSランキングを作成する](https://qiita.com/loftkun/items/5ea5b9577347505729f6)
を参考にGitHubリポジトリのスター数をカウントしてみた。
※jqはダウンロードしてきてpathを通す必要あり

“`
$ set LANGUAGE=go
$ set KEYWORD=web+framework
$ set STAR=10000
$ set USER=yusuke-nomura-cosmoroot
$ set PASS=20130401_cosmo
$ set page=1
$ curl –anyauth

元記事を表示

faker ダミーデータ生成ライブラリ Go

人名や住所などのダミーデータをランダムに生成するGoライブラリ。英語ですが。

[faker](https://github.com/jaswdr/faker)

“`golang
package main

import (
“fmt”

“github.com/jaswdr/faker”
)

func main() {
faker := faker.New()

fmt.Println(faker.Person().Name())

fmt.Println(faker.Address().Address())

fmt.Println(faker.Lorem().Text(100))
}
“`

ループで使用する場合。

“`
p := faker.Person()

for i := 0; i < 10; i++ { fmt.Println(p.Name()) } ``` 実行結果 ``` Ms. Kaitlin Johnston II 7 Balistreri Crossing Apt. 728 Loychester, DE 29058 ali

元記事を表示

strings.Replace と strings.Replacer はどっちが早い

# 概要
複数の文字を置換するときは `strings.Replacer` でまとめて置換した方が早そうな印象がありました。
しかし `strings.Replace` のコードの方が `-bench` の結果がよい状況に出会したので改めて確認しました。

# 用語

## やりたいこと
`ABCDE` の `A` を `1` に `BC` を `23` に置き換えたいとき

## 用語

(用語に自信がないので以下の使い方で書きます)

* 「文字」
* 上記やりたいことでいうところの、`A`
* 「文字列」
* 上記やりたいことでいうところの、`BC`
* 「置き換えたい文字(列)」
* 上記やりたいことでいうところの、`A` や `BC`
* 「置換対象文字列」
* 上記やりたいことでいうところの、`ABCDE`

# さっそくまとめ

以下の場合は `strings.Replace` を複数回実行した方が早そうです。

* 「置き換えたい文字(列)」が少ないとき
* 「文字列」を置き換えたいとき
* 「置換対象文字列」に、「置き換えたい文字(列)

元記事を表示

Apache/Nginx 自動再起動付き監視デーモンを golang で作ろう

## はじめに
モダンな監視ツールを導入できない環境向けに簡単な監視デーモンを golang で簡単に実装してみます。
クロスコンパイルでほとんどの環境で動作するデーモンを作れるのでこういう時に golang は本当に頼りになります。

## やってみよう

#### 必用なもの
* golang

#### 仕様
監視対象URLにポーリング → エラー回数が上限を超え → 任意のコマンドを発行
上記のデーモンを golang で実装する
監視対象URLやエラー時に発行するコマンドなどを環境変数にから読み込む

#### 実装

まずは必要な変数を定義します。

“`go:main.go
var (
CheckUrl string // 監視対象URL
CheckTimeout int64 // 監視のタイムアウト
CheckInterval int64 // 監視間隔(秒)
RetryCount int64 // リトライ最大回数
StopCmd string // エラー検知時のApache/Nginx停

元記事を表示

【Go】標準入力 / bufio.Scanner

競プロとかをやっていると標準入力を受け取って処理をすることが多いと思います。
記事も多いので、あまり理解せず書いていたコードをドキュメントを参照しながらまとめようと思います。

Go勉強し始めて日が浅いので色々ご容赦ください…mm

## 標準入力を受け取るよくある書き方。
“`go
package main

import (
“bufio”
“fmt”
“log”
“os”
)

func main() {
sc := bufio.NewScanner(os.Stdin)
sc.Scan()

if err := sc.Err(); err != nil {
log.Fatal(err)
}

fmt.Println(sc.Text())
}
“`

## 一つずつみていく
まず、`bufio.Scanner`を[みてみる](https://golang.org/pkg/bufio/#Scanner)。今回使ってるメソッドが大体載ってますね。

“`go
// ファクトリ関数
func NewScanner(r io.Reade

元記事を表示

GoプロジェクトにSonarScannerをかけてみる

# What’s?

SonarQubeでは、Goも解析対象となっているようなので試してみようかなと。

# SonarQubeでGoを使う

SonarQubeのGoに関するドキュメントは、こちら。

[Go](https://docs.sonarqube.org/8.6/analysis/languages/go/)

SonarScannerを使うようです。

SonarScannerは64ビットのWindows、macOS、Linuxで動作し、Go自体のインストールはカバレッジを取得しなければ不要のようです。

> * SonarQube Scanner should run on a x86-64 Windows, macOS or Linux 64bits machine
> * You need the Go installation on the scan machine only if you want to import coverage data

Goに対する解析ルールは、こちら。

[Go static code analysis](https://rule

元記事を表示

Go – error handlingにおけるnilでハマった

## 前提
この記事は以下環境で調査した結果を元に記載しております。
– OS : MacOS BigSur11.2
– Go : ver 1.15.6
– IDE : Visual Studio Code
*プログラミング初学者が書いた記事なので、もしご指摘などございましたらコメント頂けると嬉しいです!

## ハマった問題
“`
err := (*gorm.DB).GetErrors()
if err != nil{
return A
} else {
 return B
}
“`
でエラーハンドリングをした際に、errには何もエラーが発生しておらず、綺麗に動作しているつもりでもAが返り値として戻ってきてしまっていた。
“`log.Println(err)“`ログを出力してみると、出力は“`[]“`
“`log.Printf(“%T\n”, err)“`で出力すると、出力は“`[]error“`

ここで私はerrがnilではなく、型がついているものらしく、どうやら型が一致していないとイコールで判定されない?と気づく。
詳細は[quoll00](https:

元記事を表示

OTHERカテゴリの最新記事