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

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

【A Tour of Go】基本編③ 〜構造体、配列、スライス、マップ〜

公式の A Tour of Go ではじめてGo言語を触ってみました。
以下、構造体、配列、スライス、マップについて学んだことのメモ。

前回の記事はこちら

https://qiita.com/BitterBamboo/items/58d80a1a1a85e18188ce

https://qiita.com/BitterBamboo/items/f72ce6f7ce20e6b5f6c7

## ポインタ

* ポインタは値のメモリアドレスを指す
* 変数`T`のポインタは`*T`型で、ゼロ値は`nil`

“` go
var p *int
“`

* `&`演算子は、そのオペランドへのポインタを引き出す

“` go
i := 42
p = &i
“`

* `*`演算子は、ポインタの指す先の変数を示す(*間接参照*)

“` go
fmt.Println(*p)
*p = 21 // ポインタ p を介して i へ値を代入する
“`

## 構造体

### 構造体とは

* 構造体(`struct`)は、フィールドの集まり

“` go
package main

元記事を表示

【A Tour of Go】基本編② 〜フロー制御〜

公式の [A Tour of Go](https://go-tour-jp.appspot.com/list) ではじめてGo言語を触ってみました。
以下、フロー制御(for, if, switch, defer)について学んだことのメモ。

前回の記事はこちら

https://qiita.com/BitterBamboo/items/58d80a1a1a85e18188ce

## `for`

* 初期化ステートメント: 最初のイテレーションの前に初期化が実行される
* 条件式: イテレーションごとに評価される
* 条件式の評価が false となった場合にイテレーションを停止
* 後処理ステートメント: イテレーションごとの最後に実行される

“` go
package main

import “fmt”

func main() {
sum := 0
for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) // 0 + 1 + ... + 9 = 45 } ``` * 初期化ステートメントと後処理ステート

元記事を表示

【A Tour of Go】基本編① 〜パッケージ、変数、関数〜

公式の [A Tour of Go](https://go-tour-jp.appspot.com/list) ではじめてGo言語を触ってみました。
以下、パッケージ・変数・関数について学んだことのメモ。

## パッケージ

### package

* Goのプログラムはパッケージで構成される

“` go
// プログラムは main パッケージから開始される
package main

// “fmt” と “math/rand” パッケージを import
import (
“fmt”
“math/rand” // `package rand` ステートメントで始まるファイル群
)

func main() {
fmt.Println(“My favorite number is”, rand.Intn(18))
}
“`

### import

* `import`ステートメントの書き方
* 括弧で複数の`import`を整理する(*better*)
* 複数の`import`ステートメントを書く

“` go
// factored import st

元記事を表示

grpcurlを用いてgRPCサービスの動作確認を行う

# はじめに
gRPCサーバーの開発を進めている際に、gRPCサーバーに対しての動作確認をローカル環境で行いたい場合があると思います。
そこで、動作確認の際に、便利なツールが公開されているので紹介します。

# grpcurl

https://github.com/fullstorydev/grpcurl

# install
今回はMacにて使用するので、以下のコマンドでinstallを行います。
“`
brew install grpcurl
“`

# 事前準備
gRPCサーバーの`main.go`に以下の処理を追記しておきます。

下記のソースを追加
“`
s := services.NewServer(client)

reflection.Register(s) ⇦追記
log.Printf(“server listening at %v”, lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
“`
上記の設定を追加しておかないと、grpcurlコマンド使用時に以下のよ

元記事を表示

Goを小さく実行するための簡易シェルスクリプト

# はじめに
昨日初めてGoを書きました。

筆者は新しい言語を書くときは`haskell-playground`や`javascript-playground`みたいなディレクトリを作り、「ネットで見つけた便利なコード」や「試しに動かしたいちょっとしたコード」などをそこで動かしながら、少しずつ新しい言語を学びます。

なので今回も同様に`go-playground`というディレクトリを作って、そこでgoのコードをあれやこれやと動かして遊んでいました。

# なぜシェルスクリプトを書いたのか
そこまでは良かったのですが、書いているうちに**試しにコードを動かすたびにmain関数を毎回書き換えること**がちょっと面倒だなぁと思いました。

具体的に説明しますと、例えば`gob`というgoでバイナリデータを扱うプログラムをちょっと動かしてみたいと思い、以下のようなコードを書いたとしましょう

“`gob.go
package main

// importは省略
func store(data interface{}, filename string) {
//バイナリデータ

元記事を表示

【AtCoder】C++のmultisetを使う問題をGo言語で解く

# 概要
2022-05-28(土)に開催されました[NOMURA プログラミングコンテスト2022(AtCoder Beginner Contest 253)](https://atcoder.jp/contests/abc253)の[C – Max – Min Query](https://atcoder.jp/contests/abc253/tasks/abc253_c)をGo言語で解く方法を紹介します。

# 問題と解答のアプローチ
Go言語で、問題文に沿って実装してみます。
$x$について下記のような制約がありますので、
問題文の多重集合$S$を、mapで書くことでメモリ制限を超えないようにします。
“`math
0 \leq x \leq 10^9
“`
下記の書いてみますと、クエリ3で$S$の最大値と最小値を求めるところを
工夫をしないと、実行時間制限をオーバーしてしまいます。

“`go
package main

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

var sc = bufio.NewScanner(os.S

元記事を表示

Go を公式パッケージからインストール ( Ubuntu / RaspberryPi OS / WSL2 )

インストール方法は、こちらを基にしています。
「ラズパイに Go をインストールする」
https://zenn.dev/ysmtegsr/articles/20d6e0c7159be2

# 環境

– Go Version 1.18.2
– Raspberry Pi OS Lite
– Release date: April 4th 2022
– System: 32-bit
– Kernel version: 5.15
– Debian version: 11 (bullseye)

また、同様にして Ubuntu20.04 , WSL2 にもインストールできました。

# ダウンロード
https://go.dev/dl/
こちらから、該当のアーキテクチャを選択し、リンク先をコピーして使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5539aac0-c8eb-090c-9b80-ef477b9ca406.png)

– Raspberr

元記事を表示

Cloud Functions (Go言語) & PubSub & Cloud Scheduler を利用してcronを実現する

方法を3ステップで解説します

# STEP1 トピックを作成する

GCP の PubSub のコンソールからトピックを作成する

名前は、「hello-functions」にしました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38174/7100bd83-21bd-a557-33b3-bd517563cb27.png)

# STEP2 メッセージを受信して起動するアプリケーションを Cloud Functions にデプロイする

## コード

GCP の Cloud Functions のコンソールから「関数の作成」を選択して出てくるテンプレートと同じ内容です

“`go:hello_functions.go
package p

import (
“context”
“log”
)

type PubSubMessage struct {
Data []byte `json:”data”`
}

func HelloPubSub(ctx context.Cont

元記事を表示

【gin】goでAPIサーバー

# golangでAPIサーバー
[gin](https://github.com/gin-gonic/gin)というフレームワークを使ってAPIサーバーを建て、CRUD処理を実装します。
プログラム全体は[こちら](https://github.com/shuyaeer/go_api_server)においてあります。

## 環境
MacBook Pro (14-inch, 2021)
Go 1.18.2
gin 1.77

## APIの設計
焼き鳥屋の商品情報を扱うものを想定します。
– 商品一覧の取得
– 単一商品の取得
– 新商品の登録
– 在庫情報の変更
– 商品の削除

これらを実装します。

## ディレクトリとファイル類を作成
“`bash
$ mkdir go_api_server
$ cd go_api_sever
$ touch main.go # プログラムを書くファイルを作成
$ go mod init go_api_server # モジュールを管理するファイルを作成
$ go mod tidy
“`

使用する外部モジュールであるginもこ

元記事を表示

「STEP UP GO」第1回イベントレポート

# 導入

2022年5月28日開催の __「STEP UP GO」__ というメルカリさん主催の学生・第二新卒向けのイベントに参加させていただきました。

5月から7月にかけて行われる全3回の勉強会の第1回では、
前半でGolangの基本情報をメルカリのtenntennさんに紹介していただきつつ、
後半ではメルカリUSに所属されているNSEGAさんとのパネルディスカッションを拝聴しました。

Qiitaの記事にするほど綺麗にまとめられているわけではないですが、
自分が知って勉強になったことなどをメモ書き程度に書き留めておこうと思います!

# 学び
インプットは良質なアウトプットするために行う。
勉強をやみくもにするのではなく、アウトプットが前提にあるべきということを再確認した

# Goについて

* 使っていないimport宣言を許していないのは、ビルドが遅くなる要因を排除する目的があるから
* なんで許さないのか → 開発のスケールしやすくなることをGo自体が目指しているから。
* 言語ごとの開発の背景を学ぶべきである
* 「Goに入ってはGoに従え」

*

元記事を表示

VSCodeを開いたときのgoplsのmoduleに関するエラー

# 環境
Go1.18.2

# 経緯
VSCodeで複数のモジュールを含むworkspaceを開いたときに下記のエラーが表示される

# エラー

“`err
gopls requires a module at the root of your workspace. You can work with multiple modules by opening each one as a workspace folder. Improvements to this workflow will be coming soon, and you can learn more here: https://github.com/golang/tools/blob/master/gopls/doc/workspace.md.
“`

# 解決策
https://github.com/golang/tools/blob/master/gopls/doc/workspace.md#go-workspaces-go-118

エラーメッセージの通り上記のリンク先を確認すると
workspaceの

元記事を表示

moqを触ってみる

# はじめに

Goのテスト用モック生成ライブラリ `moq` を触ってみたので紹介したいと思います。

https://github.com/matryer/moq

モック生成は今まで `gomock` しか使ったことが無かったので、gomockとの違いについても見ていきます。

https://github.com/golang/mock

# バージョン

– moq: `v0.2.7`

# 使ってみる

紹介したコードは以下のリポジトリにまとめています。

https://github.com/Syuparn/moqexample

`go generate` でインターフェースからモックが生成されます。

“`go
//go:generate moq -fmt goimports -out employee_moq_test.go . EmployeeRepository

type EmployeeRepository interface {
Get(ctx context.Context, id EmployeeID) (*Employee, error)
}
`

元記事を表示

VRChatでOSCを使ってケモ耳をアナログ時計にした

# はじめに
アバターの耳をアナログ時計にしてみたかったのでしてみました。簡単に手順を紹介します。各種用語の説明についてはリンク先をご覧ください。
# できたもの
アホ毛を引っ張ると両耳で時刻を教えてくれます。アホ毛を固定するとそのまま時刻を表示しつつけ、元の位置に戻すと解除されます。

# 誰向け
– このアホ毛耳時計がどうやって実現されているのかなんとなく知りたい人
– [Avatars 3.0](https://docs.vrchat.com/docs/avatars-30)と[PhysBones](https://docs.vrchat.com/docs/physbones)がちょっとわかる人
– Animatorを組むときにWriteDefaultsの挙動がちょっとわかってる人向け
– [Write Defaults on States](https://docs.vrchat.com/doc

元記事を表示

APIGateway+Lambdaでミドルウェアを使う

# 背景

Go言語でlambdaを使ってサービス提供するときに、複数エンドポイント共通の処理を入れたくなった。
各エンドポイントに共通の処理を書き込むと、可読性が下がるためミドルウェアとして実装してみた。

参考:
https://github.com/mefellows/vesper
https://github.com/aws/aws-lambda-go/blob/main/lambda/handler.go

# 前提

`APIGatewayProxyRequest`と`APIGatewayProxyResponse`を利用している。

# 実装

いろいろと既存実装の制約あって`reflect`を利用してごちゃごちゃしているけど、実行速度考えたらできる限り`reflect`使わないで、エンドポイントのハンドラーの引数を`APIGatewayProxyRequest`、戻り値を`APIGatewayProxyResponse`に限定してあげた方がいいかも。

“` go
type LambdaFunc func(context.Context, events.APIGate

元記事を表示

【Go】OpenAPI Generatorでコード生成時modelにCustom Struct Tagを出力する

## 概要
Goには、OpenAPIで定義したyamlをコード出力するツールがあります。概要については[OpenAPI GeneratorでGoのAPIサーバー/クライアントコードを自動生成する](https://qiita.com/saki-engineering/items/b20d8b6074c4da9664a5)の記事で、解説されています。
出力するコードにはmodelのstructも含まれるのですが、例えば[Ginでバリデーションを使ってみる](https://k01ken.hatenablog.com/entry/2021/07/14/234834)で紹介されているような、Custom Struct Tag(ginだと`binding`)を、出力したいという場合もあると思います。
今回は、OpenAPIでCustom Struct Tagを出力したい場合どうするかというのをメモ書きします。

## 対応方法
[goswaggerのCustom extensions](https://goswagger.io/use/models/schemas.html#custom-ex

元記事を表示

Go の sort.Slice でソートできない

# 現象

sort.Slice の第二引数の結果を、第一引数のスライス以外から算出すると、ソートが期待通りに動かない。

“`go
sort.Slice(dates, func(i, j int) bool {
return times[i].Before(times[j])
})
“`

### 具体例

文字列の日付のスライスをソートを行いたいとします。
ソート処理には sort.Slice を使用します。

“`go
dates := []string{
“2022-05-02”,
“2022-05-03”,
“2022-05-01”,
}

times := make([]time.Time, len(dates))
for i, date := range dates {
d, err := time.Parse(“2006-01-02”, date)
if err != nil {
retur

元記事を表示

GoのゲームエンジンEbiten向けのステートマシンライブラリを作った

# はじめに
Go言語のゲームエンジン[Ebiten](https://ebiten.org/)という薄いライブラリがあります。
しかし、Unity等と違いシンプル・コンパクトにまとまっている思想のため最低限の機能しかなく、シーン管理や状態管理等は自分で実装しなければなりません。
そのため今回、Ebiten向けのステートマシンライブラリを作りました。

# 成果物
[PenguinCabinet/pgfsm](https://github.com/PenguinCabinet/pgfsm)

[awesome-ebiten](https://github.com/sedyh/awesome-ebiten#frameworks)にも載っています。
[issueで丁寧にレビューしてくださった sedyhさん、ありがとうございます](https://github.com/sedyh/awesome-ebiten/issues/2)

# 使い方
チュートリアルをもとに、少し使い方を紹介させていただきます。

詳しくは公式[チュートリアル](https://github.com/Penguin

元記事を表示

【Go】Ginの.IndentedJSONと.JSONの違い

# 概要

GinでAPIを開発するチュートリアルをWeb上で探すと色々出てくるが、JSON形式の文字列をレスポンスとして返す際IndentedJSONメソッドで返している場合とJSONメソッドで返している場合があったため違い何なのか調べた。

# 調査結果

Ginのドキュメントから引用(Google翻訳かけてます)

https://github.com/gin-gonic/gin/blob/master/context.go

JSONメソッド
> JSONは、指定された構造体をJSONとして応答本文にシリアル化します。
また、Content-Typeを「application/json」として設定します。

IndentedJSONメソッド
> IndentedJSONは、指定された構造体をきれいなJSON(インデント+エンドライン)として応答本文にシリアル化します。
また、Content-Typeを「application/json」として設定します。
警告:きれいなJSONを印刷すると、CPUと帯域幅がより多く消費されるため、これは開発目的でのみ使用することをお勧めします

元記事を表示

gRPCのstream方式でファイルアップロード処理を実装する

# はじめに
マイクロサービス方式の開発で選定されることが多いgRPCを用いてクライアントからのファイルアップロード処理を実装してみました。

# gRPCの通信方式

* Unary RPCs
シンプルな通信方式。1つのrequestに対して1つのresponseが返ってくる方式になります。gRPCの通信方式の中で一番REST方式に近いものになると思います。
* Server streaming RPCs
クライアントからの1つのrequestに対して、サーバーから複数のresponseを返すことができる通信方式になります。サーバーからクライアントに向けてサイズの大きいファイルなどを送信したい場合に使うことが多いと思います。
* Client streaming RPCs
クライアントからの複数のrequestに対して、サーバーから1つのresponseを返す通信方式になります。クライアントからサーバーに向けてサイズの大きいファイルなどをアップロードする際に使うことが多いと思います。
* Bidirectional streaming RPCs
クライアントからの複数のreques

元記事を表示

【Go】GinでURLからパラメーターを受け取る2つの方法

# 概要

Ginを使用したAPI開発などでURLからパラメーターを受け取る際、
パラメーターの種類によって受け取り方が異なるのでまとめました。

クエリパラメータ
`http://example.com/user?id=123`

パスパラメータ
`http://example.com/user/123`

# 受け取り方

“`go:クエリパラメータの場合
router.GET(“/user”, func(ctx *gin.Context) {
id := ctx.Query(“id”)
})
“`

“`go:パスパラメータの場合
router.GET(“/user/:id”, func(ctx *gin.Context) {
ctx.Param(“id”)
})
“`

以上です。

元記事を表示

OTHERカテゴリの最新記事