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

Go関連のことを調べてみた2021年09月22日
目次

Go.spec.goからOpenAPI specの出力実験v2

## infoを出したい!

const OpenAPISpecに埋め込んでもらう→const OpenAPISpecの文字列をyamlにして読み込む。

“`go
const OpenAPISpec = `
info:
version: 1.0.0
title: Swagger Petstore
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
`
“`

## 制約を書きたい!

大方針として、StructTagを使う。

1. 普通のタグと一応混在できる。
1. 解析が簡単。
1. 短くかける。

ということを考えて、yamlがjsonも行けるってことなので、「`{a:”b”} `」が解析に失敗するので断念。
「`{a: “b”} `」と空白を書かないとダメなのね……
ということで、素直にjson5でやることにした。
が、ライブラリが更新されてない。けど、大丈夫だろう。

元記事を表示

Go 言語で日付を JSON に変換するとき構造体を使わずに任意のフォーマットにする

## はじめに

Go 言語で構造体を JSON に変換すると `time.Time` 型の要素は RFC3339 フォーマットに変換されます。
これを他のフォーマットにしたくて

> golang time json marshal

といったキーワードでググると `time.Time` 型を要素に持つ構造体 (`jsonTime`) を定義して `MarshalJSON()` メソッドを実装する、以下のような方法がヒットします。

“`go
type jsonTime struct {
time.Time
}

func (j jsonTime) MarshalJSON() ([]byte, error) {
return json.Marshal(j.Format(“2006/01/02”))
}
“`

これで解決なのですが、私にとっては `jsonTime` が構造体だと都合が悪かったため、それを使わない方法を調べました。

## 環境

“`zsh
% go version
go version go1.17.1 darwin/amd64
“`

#

元記事を表示

Go.spec.goからOpenAPI specの出力実験

# はじめに

OpenAPI spec書くのきついよね。
ソースで書きたいじゃん。
ということで、実際にやってみた。

## input

“`go
package api

type Error struct {
Code int32
Message string
}

type NewPet struct {
Name string
Tag string
}

type Pet struct {
NewPet
Id int64
}

type FindPetsParams struct {
Tags []string
Limit int32
}

type Interface interface {
// (GET /pets)
FindPets(params FindPetsParams) []Pet

// (POST /pets)
AddPet(body Pet) Pet

// (DELETE /pets/{id})
DeletePet(id int64)

// (GET /pets/{id})
FindPetById(id

元記事を表示

REST APIを実装して遊ぶ

# はじめに

最近Goしている。
RESTで遊んでいる。
OpenAPIで自動生成でやる。
書いてられない……
さて、どうしよう……

# 解決案

ざっくり案だけど、JavaのSpringdocみたいに自動で仕様書書くのはどうだろう。
Goだと割と楽にコード解析ができる。
そこで、go自体でIDLっぽく、インタフェースを書いて、自動生成する。

“`go
package idl

// 適当に構造体を宣言→componentsに入れる。
type NewPet struct {
Name string
Tag string `idl:”制約条件”`
}

type Pet interface {
// (GET /pets)→pathとmethodに使う。
Find(params FindPetsParams) Pet
// -> paramsクエリの情報。Pet 200の応答。
}
“`

こんな感じで、定義書いておいて、go:generateでキックして、OpenAPI spec&コード生成できるといいんかなと。

元記事を表示

値レシーバとポインタレシーバの違いについての備忘録(new UserとUser{}を使った場合について)

Go初心者で躓いたのでメモとして残します。
`type User struct { Name string }` があるとする。
`u := new(User)`と、`u := User{}`では、値レシーバとポインタレシーバを使う際どう異なるのかを、暗黙の変換に着目してまとめてみた。

“`go
package main

import “fmt”

type User struct {
Name string
}

// メソッド(値レシーバ)
func (u User) setValueName() {
u.Name = “gopher”
}

// メソッド(ポインターレシーバ)
func (u *User) setPointerName() {
u.Name = “gopher”
}

func main() {
// 値レシーバ
u1 := new(User) // uは*User型
(*u1).setValueName()
fmt.Println(“u1.Name:”, u1.Name, “*u1:”, *u1, “&u1”, &u1)
// u1

元記事を表示

Raspberrypi Pi4にgo言語のインストール

# はじめに

RaspberryPi4にGo言語のインストールをする必要が出たので最新版をインストールして動作テストしてみる

なお、OSは[64biのRaspberryPi OS](http://downloads.raspberrypi.org/raspios_arm64/images/)を使用している

# インストール

以下のコマンドで、Go言語をインストールする

“`bash
wget https://golang.org/dl/go1.17.1.linux-arm64.tar.gz
tar -xzf go1.17.1.linux-arm64.tar.gz
sudo mv go /usr/local
rm -rf go1.17.1.linux-arm64.tar.gz
echo “export PATH=\$PATH:/usr/local/go/bin” >> ~/.bashrc
sourc ~/.bashrc
“`

# 動作テスト

goのパスが通っていることを確認

“`bash
$ go version
go version go1.17.1 linux/

元記事を表示

Vectyを使ってGoでフロントエンドを作ってみた話

# 注意
本記事はとりあえず動く形にしたくらいの理解度で書いた記事です。内容に誤りが含まれる可能性があります。

# 概要
Goでフロントエンドを作るフレームワークである[Vecty](https://github.com/hexops/vecty)を使ってみた際の備忘録です。また、状態管理のために[Redux](https://github.com/dannypsnl/redux)を使用しています。

作成したリポジトリは[こちら](https://github.com/suger-131997/todos-vecty)です。Webページは[こちら](https://suger-131997.github.io/todos-vecty/)。

[Redux Todos Example](https://github.com/reduxjs/redux/tree/master/examples/todos)を参考にしています。

# 使用したバージョンなど
– Go 1.17
– github.com/hexops/vecty

元記事を表示

Go httpサーバー&リソースをワンバイナリにする

Go言語で 標準package のみを使用して、
httpサーバーを作成するのをやってみたいと思います。

ただ httpサーバー を立てるだけだと
すぐできてしまいそうなので、今回は `go:embed` を使ってみたいと思います。

## go:embed とは

httpサーバーを立てて何かページを返すようなものを作ろうと思っています。
あとリソースは、外部アクセスさせずにローカルで完結するようにします。

そのためには、リソースをローカルで持たなければいけません。

例えば、画像・CSS・JavaScript などのファイルとか。。。

実行体(exe)と同じところにファイルを置いて、
exeから読み込んで返してもらってもよいのですが
ファイルを入れ忘れるとかがあると面倒なので・・・ワンバイナリにしたい!

そんな時に使えるのが `go:embed` です。
リソースも実行体に含めてワンバイナリにしてくれます。

Go 1.16 からリリースされたので、それ以上で使えます!

使い方もそんなに難しくないので、さっそくやってみます。

## httpサーバーを立てる

まずは、h

元記事を表示

Go (Golang) コマンドラインツールの作り方

Golang バージョン 1.16 以上をを想定しています
環境の構築方法については次の記事を参照してください:
[Docker とVisual Studio Code を使った Go (Golang) 開発環境構築 – Qiita](https://qiita.com/y_shinoda/items/e6e2fef46408c0bae83b)

## 基本

まずは Golang プロジェクトを初期化します

プロジェクト用フォルダーを作成し、そのフォルダーの直下で次のコマンドを実行します:

“`console
go mod init <リポジトリーのパス>
“`

例:

“`console
go mod init github.com/yukihiko-shinoda/go-commandline-tool
“`

※ リポジトリーのパスは後から変えることもできます

すると、ファイル: `go.mod` が作成されます

“`text
project/
+—go.mod
“`

次に `.go` ファイルを作成します
例:

“`text
project/

元記事を表示

Go言語でAWS上、マスターデータ管理システムを実装した話

# 概要

元々、各プロダクトでマスターデータをJSON、DB、コードなどで管理していました。
PaymentMDM (Master Data Management)というプロダクトをGo言語で実装して、決済システムの共通マスタ情報の取得と運用をRestful APIを目指しています。

開発しやすく、拡張しやすく、低コストでメンテできるプロダクトを作りたいと思いました。まあ、それは普通ですよね! 我々の簡単とは、後で定義します。
最初から完璧にすることを目指していませんですた。気がつく問題や開発の非効率を改善するように、継続的にベストプラクティス、またはライブラリを導入しました。そして、コードのリファクタリングを行いまいした。なんのプロダクトでも適切であるテックスタックなんて存在していないです。おそらく、テックスタックがまた変わっていくと思いますので、現状のテックスタックです。

しかし、Go言語開発の他のプロダクトのニーズに一部のテックスタックが適切であることの確認ができるのではないかと思いました。例えば、PaymentMDMのテックスタックがすでに、別のプロジェクトで完全に再利用

元記事を表示

Goでカタカナバリデーションを実装しようとしたが、unicodeパッケージのKatakanaテーブルには記号なども含まれていた。

## 現象

Goでカタカナチェックを実装する際に、
[unicodeパッケージ](https://pkg.go.dev/unicode)のKatakanaテーブルを利用していたのだが、

“`Go
if !unicode.In(r, unicode.Katakana) {
return false
}
“`

なんか想定外の`㋐`などの記号も通してしまうので、
Katakanaのテーブルにはどのような文字が入っているのか確認した。

## 解析

unicodeパッケージのソースを見る限り、下記コードポイントの範囲で指定されている。

https://cs.opensource.google/go/go/+/master:src/unicode/tables.go;l=4709-4723

“`Go
var _Katakana = &RangeTable{
R16: []Range16{
{0x30a1, 0x30fa, 1},
{0x30fd, 0x30ff, 1},
{0x31f0, 0x31ff, 1},
{0x32d0, 0x32fe,

元記事を表示

Goでプリミティブなアトミック操作をするならuber-go/atomicを使ってほしい話と、比較不能かつコスト0な型の話

atomicを直接使う人はそう多くないと思われるが、仮に使うようなことがあった場合は全人類標準ライブラリのsync/atomicではなく[uber-go/atomic][uber-go-atomic]を使うべきである。

## なぜsync/atomicはよくないのか

以下のようなコードにおいて、`sync/atomic`は型による保護機構が欠如しているために誤った操作に気がつくことができない。

“`go
package main

import (
“fmt”
“sync/atomic”
)

type Money struct {
price int32
}

func main() {
ended := make(chan int)

mine := &Money{price: 1}
go func() {
// atomic.AddInt32(&mine.price, 1) とすべきところで間違いに気が付かない
mine.price += 1
ended <- 0 }() // atomic.AddInt32(&mine.price, 1) と

元記事を表示

Javaで飯食ってるエンジニアがGolangを学んでみる~序章~

とりあえずJavaとの差を意識してメモ書きのように書いてみる。Go→Javaの順
序章と書いたが続くかは不明。。。

社会人になり、弊社に入社してからJavaを学んだのだが、
その時は学生時代に研究で利用していたFortranとの対比で基本的な文法は学んで言った記憶があった。
(やり方がいいかは別)

今回もJavaとGoがいずれも静的型付け言語であることを利用し、
同じことをそれぞれの文法で書いたらどうなるかを実際にメモ書きしてみた感じ。

※Editorじゃないのでミスっていたらすみませんコメントで教えてください
※全部はやってません

#コンソール出力

“`Go

import “fmt”

func main(){

var human string = “TOM”

fmt.Printf(“%sは人間です”,human)
}

“`

“`java

public static void main(String[] args){

String human = “TOM”;

System.out.printf(“%sは人間です”,h

元記事を表示

Goで Chokudai SpeedRun 001 を解く

[Chokudai SpeedRun 001](https://atcoder.jp/contests/chokudai001/) を一通り解いたので、解き方やコードを載せます。
このコンテストは、私がAtCoderで過去に行われたコンテストを色々漁っているうちに見つけました。開かれた経緯が不明(有識者求む)の謎のコンテストですが、問題セットが典型問題で構成されています。そのため、私のような競プロ初心者には、典型解法の確認やライブラリの整理に使えました。問題を解く際の注意点ですが、他のコンテストと違い、共通の制約がコンテストのトップページに書かれていて、問題文に書かれていないので、合わせて読まないと罠にはまる可能性があります。最後ですが、もっといい解法があれば連絡いただけると助かります。

# [A 最大値](https://atcoder.jp/contests/chokudai_S001/tasks/chokudai_S001_a)
for文を使い、入力を受け取るたびに、最大値を更新するだけ。for文を使うのが面倒でなら、$n$の上界が100しかないので、入力を全て受け取って、ソー

元記事を表示

初心者による初心者のためのGo|製作途中だからどんどん書き加えていくよ

#Goの基礎を備忘録ってことで、綴っていきます。
初心者なので、間違ってたりしたら教えてください。

##変数を宣言する
明示的に変数を定義する場合

“`go
var [NAME] [TYPE]
“`

暗黙的に変数を定義する場合

“`go
[NAME] := [VALUE]
“`

後者に関しては、型を意識する必要がない。

#条件分岐 IF
単純にこう。

“`go
if <条件式> {
<処理>
} else if <条件式> {
<処理>
} else {
<処理>
}
“`

ちなみに、複数の条件式があり、ANDを使いたい場合は“`&&“`とすれば良し。
ORであれば、“`||“`でOK。

##配列の長さを取得する

“`go
<長さを格納する変数> := len(<サイズを取得したい変数>)
“`

##コマンドライン引数を受け取る FLAG編
まずは基本から

“`go
package main

import “flag”
import “fmt”

func main() {
flag.Parse()

元記事を表示

Go言語のechoフレームワークを使用してAPIサーバーを立てる方法(入門)

Go言語にて、echoを使用してAPIサーバーを立てる方法を解説します

## インストール
以下のコマンドでインストール

“`
go get github.com/labstack/echo/v4
“`

## GetのAPIを実装する
GetのAPIを実装したmain.goを作成

“`main.go
package main

import (
“net/http”

“github.com/labstack/echo/v4”
“github.com/labstack/echo/v4/middleware”
)

func main() {
// echoインスタンスを生成
e := echo.New()

// Middleware
// httpリクエストの情報をログに表示
e.Use(middleware.Logger())
// パニックを回復し、スタックトレースを表示
e.Use(middleware.Recover())

// ルーティング
e.GET(“/”, getSample)

// サーバーをスタートさせる
// ポート

元記事を表示

OpenAPI等のジェネレータツールによる更新作業の自動化、失敗時の自動ロールバックの実現

# OpenAPI等のジェネレータツールによる更新作業の自動化、失敗時の自動ロールバックの実現

こんにちは、
最近はOpenAPIやgRPCであったり、それにまつわるジェネレータツールがとても熱いですね。

新規にジェネレータを走らせるのは何の憂いもなく素晴らしいのですが、
開発が進むにつれて、ディレクトリ構造が追加、変更されたり、中間処理を挟んだりと、素のジェネレータでは対応できない場合があります。
また、複数のジェネレータを使う場合、それぞれのジェネレータのご機嫌を伺わなければならない状況が発生し、そもそも更新作業にはジェネレータを使わないようになる場合も多いと思います。

ジェネレートした結果が意図した結果にならなかった場合、その問題を解決するために、いちいちGit操作を行ったり、例えば、ある段階のcommitを取り消したりrebaseしたりする操作を行うとそれだけで丸1日が潰れてしまう経験をお持ちの方もいるのではないでしょうか。

今回は、ジェネレータをもっと効率的に使うために、ジェネレート作業の自動化と適切なロールバックを行うことができるスクリプトを作ってみました。

今回

元記事を表示

Docker とVisual Studio Code を使った Go (Golang) 開発環境構築

Golang の開発環境を Docker と Visual Studio Code で約 3 分で構築する手順を解説します

Docker と Visual Studio Code を組み合わせて開発環境を準備する利点については
次の記事を参照してください:

– [【Docker】【Visual Studio Code】 PC に言語をインストールせずにプログラム開発しよう | ultra code](https://futureys.tokyo/lets-develop-program-without-installing-language-by-docker-and-vscode/)

開発のためのエディターとして Visual Studio Code を利用する利点については
次の記事を参照してください:

– [ファイルやプログラムの編集には Visual Studio Code を使おう | ultra code](https://futureys.tokyo/lets-use-visual-studio-code-for-editing-file-or-program/)

元記事を表示

deferの即時評価

Go言語の勉強を始めたのですが、deferで引っかかってしまった部分があったのでまとめまてみました。

>defer ステートメントは、 defer へ渡した関数の実行を、呼び出し元の関数の終わり(returnする)まで遅延させるものです。

>defer へ渡した関数の引数は、すぐに評価されますが、その関数自体は呼び出し元の関数がreturnするまで実行されません。

引用元:[A Tour of Go](https://go-tour-jp.appspot.com/flowcontrol/12)

上記の通りdeferを使うことで、呼び出している関数がreturnするまで処理の実行を遅らせることができます。
例えばファイルを閉じたりチャネルをクローズするのに使われます。

“`go:サンプルコード
func main() {
file, _ := os.Open(“./example.txt”)
defer file.Close()
data := make([]byte, 100)
file.Read(data)
fmt.Println(string(da

元記事を表示

【Golang】mapに複数のキーを設定する

個人的に感動的に便利だったので、書いておきます。

## コード

mapのキーにstructを設定すると出来ます。
複数のキーで一つの値を持っておきたい時に便利です

“`go
package main

import (
“fmt”
)

type key struct {
key1 string
key2 string
}

func main() {
m := map[key]string{
key{
key1: “hoge_key1”,
key2: “hoge_key2”,
}: “hoge”,
}

fmt.Println(m)
}
// 結果:map[{hoge_key1 hoge_key2}:hoge]
“`

元記事を表示

OTHERカテゴリの最新記事