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

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

Go言語で外部コマンド実行するときの、標準出力取得するorしない、panicするorしない、の実装まとめ

Go言語で外部コマンド実行するときに、標準出力取得するorしない、panicするorしない、という以下の4パターンを使うので、それぞれの実装をまとめました

1. 外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はpanicする
2. 外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はerrorを返す
3. 外部コマンドを実行し、標準出力を返す。エラーの場合はpanicする
4. 外部コマンドを実行し、標準出力とエラーを返す

## ソース

“`golang
package main

import (
“fmt”
“os”
“os/exec”
“strings”
)

func runCommandGetOutputWithoutPanicByArray(command string, args …string) (string, error) {
stdout, err := exec.Command(command, args…).CombinedOutput()
return string(stdout), err
}

元記事を表示

Go のような日時フォーマットを Ruby で使えるようにする gem「GoTime」

 Rubyist の皆さま、日々 `Time#strftime` 使ってますか?

 Rails プログラマの場合 直接 `Time#strftime` を使う機会は少ないと思いますが、設定ファイル上などで `strftime` 用のフォーマット文字列[^timewithzone] を書いたことがあるのではないかと思います。

[^timewithzone]: Rails の場合、正確には `TimeWithZone#strftime` だと思いますが。

– 参考:[【初心者向け・動画付き】Railsで日時をフォーマットするときはstrftimeよりも、lメソッドを使おう](https://qiita.com/jnchito/items/831654253fb8a958ec25)

 ですので当然 strftime 用のフォーマット文字列など、何も見なくてもスラスラ書ける方が多いのではないでしょうか。

 **私は見ないと書けませんけどね!**

 だって何?この[フォーマット文字列](https://docs.ruby-lang.org/ja/latest/method/Time/

元記事を表示

goでbuffer writeする処理のメモ

bufferにwriteする際、io.Writerのインターフェースを使う場合は以下のように書けます。

“`
buffer.Write([]byte(“bytes.Buffer example1”))
“`

ただ、毎回バイト列にキャストしないといけないのは面倒です。なのでWriteStringというメソッドがbufferに用意されています。

“`
buffer.WriteString(“bytes.Buffer example2”)
“`

ただ、WriteStringはbuffer専用のメソッドのため、他の構造体では使えません。すべてのio.Writerインターフェースを満たす構造体に対してstringを書き込むような処理はio.WriteStringで実装できます。

“`
io.WriteString(&buffer, “bytes.Buffer example”)
io.WriteString(os.Stdout, “bytes.Buffer example”)
“`

まとめると以下のような感じです。

“`main.go
package main

im

元記事を表示

Go言語における.envファイルの使い方(viper使用)

# はじめに

Go言語でサーバーアプリケーションを作成しています。

このアプリでは、暗号化に使うシークレットキーやら、データベースのユーザー、パスワードといった設定値を簡単に扱えるライブラリとして、viperを使っています。

viperを使ってconfig.yamlといった外部ファイルを読み込む方法については、下記の参考資料等々よく見ますが、config.yamlの他に.envファイルも扱いたいと思いました。

viperにおける、.envの扱いについては、調べてもあまり出てこなかったので備忘録としてまとめました。

# 前提

## Versionについて

Goのバージョン、viperのバージョンは以下のとおりです。

– Go 1.17.6
– [github.com/spf13/viper](http://github.com/spf13/viper) v1.10.1

## フォルダ構成

今回説明するフォルダ構成は以下の通りです。

“`:フォルダ構成
.
├── config
│ ├── config.yaml
│ └── config.go
├── .e

元記事を表示

Golangはじめて物語(第10話: RDS Proxy+Aurora(PostgreSQL互換)とうまく付き合う方法)

# はじめに
[以前の記事](https://qiita.com/neruneruo/items/6346c655045a153ba458)では、GolangでAurora(MySQL互換)のエンドポイントに直接接続する方法を書いたが、今回はRDS Proxyを経由する方法を考察する。

GolangでRDS Proxy+Aurora(PostgreSQL)互換を使う場合、以下を考慮する必要がある。

なお、本考察においては、[この記事](https://qiita.com/neruneruo/items/15d6c5c50cf225bcd1fc)の構成を元にして実験をしている。
Aurora(PostgreSQL互換)のエンジンバージョンは12.7だ。

# 何を気を付けなければいけないのか
色々動作を検証していると、RDS Proxyの仕様とGolangの言語仕様の合わせ技でかなりややこしいことになった。
詳細は↓このような感じだ。

– RDS Proxyは特性上、Prepared Statementのように接続時に設定を行うようなことをするとピン留めが発生する(参考:[公式ドキ

元記事を表示

JupyterにPython以外のカーネルを導入する

## この記事の前提条件

誰でも無料で利用できる、カスタマイズ可能な[Jupyter](https://jupyter.org/)であれば、自分が推している言語でカーネルを導入しない手は無いと思い、色々チャレンジしてみました。
ここでは以前投稿した下記の環境で話を進めていきます。

https://qiita.com/Q-Lazy/items/bd7dacf1d8e865d57a94

## すでに利用可能な処理系のカーネルを導入

まずは、言語本体はすでに利用可能な状態で、カーネルさえインストールすればよいパターンから着手してみたいと思います。

####【Bashカーネル編】

手始めに容易に導入出来るBashから行います。こちらカーネルはPython3で実装されているので、pipコマンドでモジュールをインストール出来ます。
Jupyterへのカーネルのインストールも、Pythonモジュールの関数を実行するだけです。

“`bash
$ pip3 install –user bash_kernel

$ python3 -m bash_kernel.install
“`

元記事を表示

初めてOSS(Hasura)にコントリビュートしたのでまとめた

## はじめに

最近、OSS([hasura/graphql-engine](https://github.com/hasura/graphql-engine))にコントリビュートしました。
本記事は、業務で遭遇したOSSのバグに遭遇してから、IssueとPull requestでのバグ報告・修正するまでの経緯を簡単にまとめています。

今まで自分は、OSSへのコントリビュートは難易度が高いと思っていました。しかし、いざやってみると思ったより敷居が低く、経験値も多く得ることができました。

> OSSコントリビュートしてみたいけど、今一歩踏み出すことができない

といった方の参考になればという考えのもと、記事にしました。拙い文章ではありますが、参考になれば幸いです。

### 対象読者
:::note
・OSS活動をしてみたいが、どうやってやればいいかわからない方
・Hasuraにコントリビュートしてみたい方
:::

### コントリビュート内容

立てたIssue・Pull Requestは以下です。

https://github.com/hasura/graphql-engi

元記事を表示

Go言語でのエラーハンドリング方法

Go言語でコードを書く際によく使うエラーハンドリング方法をまとめます。

エラーハンドリングといったら大げさに聞こえますが、シンプルに普通のエラー処理です。
普段Go言語をいじっている方からすればです。

## Goの処理は基本エラーがつきもの
初めてGoを触った時の感想ですが、例外処理はなく常にエラーを持ち回る印象を受けています。
関数はメソッドは正常値とエラーをセットで返していて、コール元はその戻り値からエラーチェックをしてから、正常処理か異常処理のいずれかを実施する流れがスタンダードになっています。
https://go.dev/play/p/RI6w5doxZZh

“`go
package main

import (
“errors”
“log”
)

func main() {
s, err := doSomething()
if err != nil {
doErrorProcess(err)
return
}
doSuccessProcess(s)
}

func doSomething() (string, error) {
// retur

元記事を表示

【gRPC】GoでUnaryなAPIを実装する

#はじめに
前の記事で紹介したgRPCのAPIタイプの内、1リクエストに対して1レスポンスを返すUnaryを実装してみました。

https://qiita.com/suzuki0430/items/2be2d532cedd200937ca#%E6%A7%98%E3%80%85%E3%81%AAapi%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%97

#実装
細かい手順に分けて実装していきます。

##準備
GoでgRPCやProtocol Bufferを実装するにあたり、以下のライブラリを導入します。

“`
$ go get -u google.golang.org/grpc
$ go get -u github.com/golang/protobuf/protoc-gen-go
“`
また、シェルにパスを通します(今回は`.bash_profile`)。

“`bash
export GO_PATH=~/go
export PATH=$PATH:/$GO_PATH/bin
“`

https://github.com/grpc/grpc-go

h

元記事を表示

[Go] ハロー ワールド

# install
https://go.dev/doc/install

# code
“`go
package main

import “fmt”

func main() {
fmt.Println(“Hello, World!”)
}
“`

## package
コードの先頭では、このファイルに記述するコードがどのパッケージに所属するかを宣言する

## import
fmt というパッケージを import する

## func
func を使い、 `main` という function を宣言する

# command
“`zsh
go run main.go
“`

# Reference
https://go.dev/doc/tutorial/getting-started

元記事を表示

M1 MacBook AirでGoを動かそうとしたらプチハマった

# 使用環境
* MacBook Air M1
* VSCode 1.63.2

# 導入目的
BEをGoで構築する案件にアサインされたので、お勉強をしようと思い環境導入です。

# Go環境構築
* ”Go Install”とか適当にググって出てきたサイトをポチポチクリックしてインストール。
* VSCodeも勝手に”Goで書かれたコードやん!拡張機能入れたげるわ〜!”とサジェスト。

* 続いてF5でデバッグ開始すると”Debuggerおらんやない〜? GoにおすすめのDelvインストールしとこか〜?”とマザーテレサ並みの献身。

あゝ、VSCode、君はなんてよくできたエディタなんだっ!
というふうに、最も簡単に環境構築はできたと思ったのでした。

#ハマった
何も考えないで適当にHello World!
こんにちはGo!
はい、動きませんでした。

2fe9ba50-c15c-1f22-793c-42eb1a6b2445.pngMakefileで必要なファイルだけgo generateするレシピ

http://makiuchi-d.github.io/2022/01/27/make-go-generate.ja.html

元記事を表示

Goのスライスの中身がすべて同じ値になる

# 結論

range の左辺はただの変数である。
繰り返しのたびに再代入しているだけなので、気をつける。

# 現象

上手い例がかけないが、例えば以下の状況

“`go

type Foo struct {
Item string
}

foo1 := Foo{“1”}
foo2 := Foo{“2”}
foo3 := Foo{“3”}
slice := []Foo{foo1, foo2, foo3}

var foos []*Foo
for _, foo := range slice {
foos = append(foos, &foo)
}

for _, foo := range foos {
fmt.Println(foo.Item)
}

// => 3
// => 3
// => 3

// 中身が同じ、なぜ?
“`

なぜか中身がすべておなじになる。

# 原因

range の第二引数のポインタを格納してしまっているため。

詳しくは `foos` の中身をプリントしてみるとわかる

“`go

type Foo struct {
Item s

元記事を表示

SQLBoilerでエラー:Error: unable to initialize tables: unable to fetch table data

# はじめに
SQLBoilerで`sqlboiler mysql`コマンドをうったときにエラーが出ました。

– Go: v1.16
– SQLBoiler: v4.8.3

# エラー内容
“`
Error: unable to initialize tables: unable to fetch table data: something totally unexpected happened when running the binary driver /app/go/base/sqlboiler-mysql: fork/exec /app/go/base/sqlboiler-mysql: no such file or directory
“`

# 解決方法
ドライバーが入ってなかったので、

“`
$ go get github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-mysql
“`

でドライバーを追加したらOKでした。

元記事を表示

Golangのreflectパッケージを用いた汎用メソッドの作り方

## 背景

Goではマルチタイプの自作汎用メソッドを実装したい時に、ジェネリクスが使えない代わりにinterface型や`reflect`パッケージを用いたり、個別型ごとにメソッドを定義したりして対応する方法がよく使われます。
単に基本型をinterface型として扱うだけであれば、実装はさほど難しくないと思われますが、配列やスライスが含まれる場合にはちょっと工夫が必要になるかと思います。
そこで本記事ではinteface{}や`reflect`パッケージを用いて、**型ごとのswitch分岐を記述することなく**、配列を含む様々な基本型を引数や返り値に扱う汎用メソッドを実装する方法について紹介します。また、`reflect`パッケージの利用が最小限に抑えられそうな汎用メソッドのサンプルとして`Choice`,`Sample`,`Intersection`メソッドの作り方を後半に載せてあります。

“`go:本記事では取らないアプローチ例
for _, v := range values {
if v == nil {
fmt.Println(“it is

元記事を表示

Go: 接種状況ダッシュボードのデータを使ってワクチン接種済者をカウントする

こちらで行ったのと同じ計算を Go で行いました。
[Python3: 接種状況ダッシュボードのデータを使ってワクチン接種済者をカウントする](https://qiita.com/ekzemplaro/items/e892ab821eef343d4860)

“`go:count_vaccination.go
// —————————————————————-
//
// count_vaccination.go
//
// Jan/26/2022
//
// —————————————————————-
package main

import (
“fmt”
“os”
“log”
“encoding/csv”
// “reflect”
“strconv”
“time”
)

// ——————————————————–

元記事を表示

Go Flow Levee で機密データのロギングを検出する

## はじめに
セキュリティ上問題となるプログラミングエラーの一つに、誤って機密データをログに記録してしまうというものがあります [^cwe-532]。データ構造やロジックが複雑になるほど、レビューでもこの種のエラーは見落としやすくなります。[Kubernetes](https://github.com/kubernetes/kubernetes) でも何度かこの問題が起きており、[Go Flow Levee](https://github.com/google/go-flow-levee) というツールを使った[静的解析による対策](https://github.com/kubernetes/enhancements/tree/master/keps/sig-security/1933-secret-logging-static-analysis)が導入されています。

[^cwe-532]: [共通脆弱性タイプ一覧 CWE](https://www.ipa.go.jp/security/vuln/CWE.html) では、この問題を [CWE-532: Insertion of S

元記事を表示

【GoでMockを差し込めるようにリファクタリングした】

現在Goで作っているアプリケーションを先輩からアドバイスをもらって、より疎結合に実装できるようになったのでまとめる。(MVCの概念の中で行うことを前提にしています)

## 何をMock化したいのか?

今回のリファクタリングを通じて思ったのは、「どこの関数をmock化したいのか」をまず考えるべきと言うこと。

今回の例だとcontrollerの`user.setvalue()`をmock化できればCreateUserの単体テストが楽になりそうだ。

userController.go

“`go
package controllers

import (
“app/~/models”
“github.com/gin-gonic/gin”
)

func CreateUser(c *gin.Context) {
user := &models.User{}
c.BindJSON(user)

user.SetValue(*user) /* <--------- ここをMock化できたらよさそう*/ c.JSON(200, gin.H{ "result": true

元記事を表示

entでUpsertを実装する(for PostgreSQL, SQLite3)

# はじめに

– 仕事でORMに[ent](https://github.com/ent/ent)を使いAPIを作成しているんですが、Upsertを実装する際にPostgresだとつまずいた部分があったため、Tipsになればと良いなと思いやったことを書き残していきます

# 発生した問題
– Upsertを実装したものの
– SQLiteでは正常に動作する
– PostgreSQLでは下の様なエラーが発生する
– CreatedAtは更新したくないのに更新されてしまう

“`sh
ERROR: ON CONFLICT DO UPDATE requires inference specification or constraint name (SQLSTATE 42601)
“`

今、こんな問題が起きてる方は 5. から見ると良いと思います:+1:
5. [Upsertを実装する場合](#upsertを実装する場合)

# 目次
1. [ent v0.9.0からUpsertが利用できる様になりました](#ent-v090からups

元記事を表示

Go1.18+のジェネリクスで補償トランザクションをシンプルに書く

# TL; DR

– 補償トランザクションを簡単に書けるライブラリを作ったよ
– 入れ子の `if err != nil` とおさらば!
– サービスを遅延評価することでエラーハンドリングを隠蔽

https://github.com/Syuparn/saga

# はじめに

マイクロサービスで処理が失敗した場合、ロールバック処理としてよく補償トランザクションが用いられます。
一方、Goには大域脱出する例外処理が無い(`panic`除く)ので、補償トランザクションが `if err != nil` の入れ子まみれになってつらみを感じがちです。[^1]

今まで「そういうものか」と割り切っていましたが、ジェネリクス(とコード自動生成)を使うと意外とシンプルに書けたので紹介します。

## おことわり

モジュールは `saga` という名前ですが、非同期でイベントをやりとりする仕組みは備わっていません。
あくまで、補償トランザクションをシンプルに書けるライブラリとして作成しています。

# 実装例

[補正トランザクション パターン – Cloud Design Patterns

元記事を表示

OTHERカテゴリの最新記事