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

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

golangci-lintでジェネリクスが使えるようになった

golangci-lintが、 `v1.45.0` (投稿時点の最新版)でGo1.18の新構文(ジェネリクスやany等)に対応しました :tada:
これで心おきなくジェネリクスが使えます!

https://github.com/golangci/golangci-lint/releases/tag/v1.45.0

早速 [issueでの紹介手順](https://github.com/golangci/golangci-lint/pull/2438) に従ってリンターをかけてみました。
(現在進行形で対応が進んでいるので、最新の状況については ~~この記事より~~ issueでの確認をおすすめします)

# 準備

`.golangci.yml` に以下の2行を足すだけです。

“`yaml:.golangci.yml
run:
go: 1.18
“`

(ちなみに指定しない場合Go1.17までのモードで起動しクラッシュしました)

“`bash
$ golangci-lint run
ERRO [runner] Panic: unused: package “ma

元記事を表示

[ビデオエコーのデモあり]GoでもWebTransportがしたい!

# WebTransportのビデオエコーデモの公開がしたい!

早い、確かに早い。
ブラウザからエンコードしたchunkデータにタイムスタンプを埋め込み、サーバーにエコーさせてchunkデータが戻ってくるまでわずか17ms
これなら確かによりリアルタイムな何かができるだろう。
しかしこれを実用化するには別の問題があった。安定性だ。

781, 772, 763 …
694, 682, 678 …
黒い画面に映し出される数字は数秒毎にじりじりと減っていく。
121, 110, 103, 99
メモリ残量を表す `vmstat` の `free` の値はとうとう残り100MBを切ってしまったことを示していた。

92, 106, 102, 98, 112, 108 …
お? ちゃんとGCが仕事をしてる?? メモリを食い尽くさずに安定稼働できるのか??

そう一抹の期待を抱きながら、ふと視線をずらすと、そこには固まって動きのないウェブカメラの画像が表示されていた。
ああ、やはり10分は持たないか。。
ブラウザでエンコードしたウェブカメラの動画・音声データをサーバーに送信し、Py

元記事を表示

Go1.18で追加された型セットを静的解析する

## 概要
先日[メルカリの短期インターン](https://mercan.mercari.com/articles/31914/)に参加した際にGo1.18の機能に焦点を当てたOSS開発をする機会があったので、そこで得られた知見をまとめようと思います。

3/16にGo1.18がリリースされ、様々な機能が追加されました。その中の一つである型パラメタ(ジェネリクス)について、機能追加に伴い新たに型セット([Type Set](https://github.com/golang/go/issues/45346))という概念も追加されました。

– [Type Parameters Proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md)
– [Type setに関するIssue](https://github.com/golang/go/issues/45346)

本記事では、型セットがGoの中でどのようになっているのかを、Goの標準パッケージ

元記事を表示

Go1.18からtext/templateのand, orが短絡評価されるようになった

表題の通りです。

`and`, `or` の右辺値で副作用を起こすテンプレートを書いていた場合、Go1.17と1.18で挙動が変わります。Go本体と同じ仕様になったので分かりやすいですね。

“`:テンプレート
{{$d := dict}}
{{or 1 (set $d “msg” “right value is evaluated!”)}}
{{$d}}
“`

go1.17: `or` の右辺値も評価されるので、 `$d` にキーが追加されている

“`:go1.17

1
map[msg:right value is evaluated!]
“`

go1.18: `or` の左辺値がtruthyなので短絡評価され、 `$d` にキーが追加されない

“`:go1.18

1
map[]
“`

# 挙動は何によって変わる?

Go本体のバージョンで決まります。 `go.mod` ファイルのGoディレクティブは関係ありませんでした[^1]。

そのため、`go install` で同じバージョンのバイナリを落としてきても、Go本体のバージョンによって挙動が変わります

元記事を表示

Go言語でWebAssemblyを実装

## 簡単なWebAssemblyを実装

モジュールディレクトリの作成と**go.mod**を生成します。

“`sh
mkdir wasm
cd wasm
go mod init example.com/wasm
“`

**main.go**を作成します。

“`go
package main

import “fmt”

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

Go言語のビルドコマンドに環境変数**GOOS = js**、**GOARCH = wasm**を設定して、**main.go**をWebAssembly用にコンパイルして**main.wasm**を生成します。

“`sh
GOOS = js GOARCH = wasm go build -o main.wasm
“`

**main.wasm**だけでは動かないので、**wasm_exec.js**(JavaScriptサポートファイル)をコピーします。

“`sh
cp “$(go env GOROOT)/misc/wasm/wa

元記事を表示

[GORM]複合主キーによるDeleteのSQL文

[GORM](https://gorm.io/ja_JP/)の[Delete()](https://gorm.io/ja_JP/docs/delete.html)のSQL文が、複合主キーの場合に、少しイレギュラーであったため、書き留めました。

+ 環境
“`
go 1.17
mysql 5.7

gorm.io/gorm v1.22.0 ( GORM自体のv2に当たる。v1は、jinzhu/gormの方 )
gorm.io/driver/mysql v1.1.2
“`

以下のような複合主キーのテーブルの場合に、
“`golang
type Item struct {
Pk1 string `gorm:”primaryKey;autoIncrement:false;”`
Pk2 string `gorm:”primaryKey;autoIncrement:false;”`
Name string
}
“`

GORMの[Delete()](https://gorm.io/ja_JP/docs/delete.html)を使うと、
“`golang
item :=

元記事を表示

wailsにEchoを導入したら「blocked by CORS policy」が発生したのでCORS対応する

![go-1.17](https://img.shields.io/badge/go-1.17-brightgreen) ![wails-v2 beta](https://img.shields.io/badge/wails-v2.0.0(beta)-brightgreen) ![echo-v4.7.2](https://img.shields.io/badge/echo-v4.7.2-brightgreen)

## 前提
– wailsに別のweb frameworkを用いたい
– wailsにReactとEcho( https://echo.labstack.com/ )を用いてアプリケーションを作ってみた
– CORSのエラーが発生した

## 結論
– EchoにCORSの設定を行う
– 勉強目的でWebフレームワークを入れたがwailsでいろいろやってくれているので煩わしい気がする

## 事象
wailsにEchoを導入してfetchして見たところ下記エラーが発生しました。

![image.png](https://qiita-image-store.s3.ap-nor

元記事を表示

GORMでデータベースのレコードが削除されない時の対処法

# はじめに
Gormを使用してデータベースを操作していましたが、レコードを削除した際にアプリ上で見ると消えているもののデータベース上には残っていることに気が付きました。
筆者の場合は、ユーザーのメールアドレスを一意な値にしたことで、「新規登録」→「ユーザー削除」→「同じアドレスで再登録」した際にデータベースでエラーが起きていました。

# 対処法
対処前に書いていたユーザー削除のコードは以下になります。

“`go
func DbDeleteUser(id int) {
d := db.GormConnect()
d.Delete(&User{}, id)
defer d.Close()
}
“`

この書き方だと、論理削除といってレコードがデータベースから物理的に削除されるわけではなく、通常のクエリ系のメソッドで検索できなくなるだけのようです。

https://gorm.io/ja_JP/docs/delete.html

対処後のコードは以下になります。

“`golang
func DbDeleteUser(id int) {
d := db.GormConn

元記事を表示

compile: version “go *.**” does not match go tool version “go *.**”エラーの解決

# compile: version “go *.**” does not match go tool version “go *.**”エラー

goの環境構築していてhello worldさせるために、
はりきって` go run hello.go `をしたら上記のエラーがでた。

## エラー内容
“`
# unicode/utf8
compile: version “go1.16.2” does not match go tool version “go1.17.8”
# runtime/internal/sys
compile: version “go1.16.2” does not match go tool version “go1.17.8”
# internal/unsafeheader
compile: version “go1.16.2” does not match go tool version “go1.17.8”
# internal/race
compile: version “go1.16.2” does not mat
“`

goenvを使って

元記事を表示

【GO環境構築】環境構築をしてVSCodeで少し動かすまで

### ゴール
Go言語の基礎が始められる状態にする

Go言語の基礎

https://astaxie.gitbooks.io/build-web-application-with-golang/content/ja/02.1.html

a tour of Go

https://go-tour-jp.appspot.com/list

### 環境
– mac

### 環境構築に必要なこと
– インストール
– コマンド実行 `brew install go`
– 環境変数の設定
– パス追加とGOPATHの設定
– `export GOPATH=$HOME/go`
– `export PATH=$PATH:$GOPATH/bin`

– ディレクトリの作成
– 環境変数GOPATH配下「bin」「pkg」「src」のフォルダを作成
– `mkdir -p go/bin`
– `mkdir -p go/pkg`
– `mkdir -p go/src`

– VSCodeの設定

元記事を表示

初めてGo(Gin)でアプリケーションを作る時に直面した壁とその解決法

初めてGoを使用し、文法もよくわからない状態でWebアプリケーションを開発しようとしたとき、他言語と勝手が違ったり、動的な言語(Perl,PHP,Python,Rubyなど)と違って型があったりして「いつもやっていることができない」となった際の事象や解決法を残しておきたいと思いこの記事を書くに至りました。

## 前提
– 使用したフレームワーク
– Gin
– 動作環境
– Docker20.10.8
– アプリの詳細
– 求人サイト
– 一般的なWebアプリケーションにあるDBからデータを取得して表示する/データを登録するといったことができる

## Ginの恩恵を受けた箇所
Goのフレームワークは基本的にフルスタックではないので、なにからなにまでGinのお世話になったわけではなく、通信周り(ルーティング)やセキュリティ周り(セッションなど)が主なGinの出番でした。そのため今回紹介するのはこうした部分がメインとなります。

Ginによって楽に実装できたものの、Ginについての情報が少なく、これらの手法を見つけるのに苦労したため、残しておきたいと思

元記事を表示

go mod vendorとは何ぞや

## そもそもvendorとは?
vendorは `go get`でダウンロードするモジュールを`GOPATH/pkg/mod`ではなく、プロジェクトのルートディレクトリに置くことができる仕組みのこと。
import時の挙動としては、`GOPATH`よりも優先して`vendor`ディレクトリのモジュールを探しにいく。

### なぜvendorが必要?
1つのPCで複数のGoプロジェクトがあるとする。複数のプロジェクトでそれぞれ違うバージョンのモジュールが必要になったとき、昔のGoはvendorを使うしかなかった。つまり、今は不要!(ただ、あると便利)
## go mod vendorとは?
`go mod vendor`は `go get`の後に実行するコマンドで、`GOPATH`にあるモジュールをプロジェクトルートディレクトリにある `vendor`ディレクトリにコピーするコマンドである。

## vendorはgitの管理下に置く
こうすることで、`git clone`したらすぐ動作確認ができたり、docker buildやCIで楽をすることができる。
`node_module

元記事を表示

プロセスとスレッドについて調べた

# 0. はじめに

Goでgoroutineやchannelの実装に出くわしたときに、雰囲気で見過ごしていたので基礎から整理する。

# 1. プロセスとスレッド

## プロセス

– 独立のメモリ空間を保有している処理の単位。
– プロセス間では基本的にメモリは共有されない。
– 1つ以上のスレッドから構成される。

## スレッド

– 1つのプロセスに割り当てられたメモリ内で動作する処理の単位。
– スレッド間ではメモリが共有される。
– スレッド間では同じデータに簡単にアクセスできる。

### シングルスレッドとマルチスレッド

– シングルスレッドとは、処理を上から順番に実行していくこと。
– マルチスレッドとは、処理効率を上げるなどの目的で、複数の処理を並行して行うこと。
– 例えば、時間のかかる操作を別スレッドで実行することで、ユーザー操作の受付を中断することなくプログラムを動かすことが可能になる。

# 2. マルチプロセスとマルチスレッドの違い

– どちらも処理を並行して行う技術。
– マルチプロセスの場合、プロセス間では基本的にメモ

元記事を表示

[Go] os.Stdin・os.Stdoutを用いた関数・メソッドのテスト

# テストケースの失敗例と解決策
Go言語でサポートされているテスト自動化ツール`go test`において,標準入出力を用いた関数・メソッドのテストを行う際にはひと工夫必要になる.

例として以下の関数をテストする場合を考える.
“`golang:sample.go
/* パッケージ,インポート文は省略 */

// isFooは標準入力から文字列を受け取り,
// それが”Foo”と等しければtrueを,異なればfalseを返す.
// 比較の結果に加え,エラーが発生した場合はそれを,そうでなければnilを返す.
func isFoo() (bool, error) {

// 標準入力を読み取るScannerを取得.
scanner := bufio.NewScanner(os.Stdin)

// スキャンを行い,エラーが有ればそれを返す.
scanner.Scan()
if err := scanner.Err(); err != nil {
return false, err
}

// スキャンした文字列と”Foo”を比較した結果を返す

元記事を表示

Go言語でCUIベースのテキスト型アドベンチャーゲームを作りました

Go言語はモダーンなプログラミング文法を持ち、マルチスレッド処理が得意な
「ハイ・エンド」なコンピュータ言語なのに、CUIベースのテキスト型
アドベンチャーゲームを作りました。

下記のURLからZIPファイルをダウンロードできます
(実行には Goコンパイラが必要です。verは多分、1.13以上であれば大丈夫)

https://github.com/new-doumeishi/travel_to_search_X.git

このゲームは主人公の「たかし」が東京の街を移動して「たい焼き器」を探す
というゲームです。
各街で「探す」コマンドで探せますが、誤って爆弾を引いてしまうことが
あります。
「たかし」は無事に「たい焼き器」を探すことができるでしょうか。

元記事を表示

[Go] RuneCountInStringで文字列の文字数を取得

`Go` にて文字列の文字数を取得したい時に

`len` の場合

`byte`で数えるまたは一つの `Unicode character`は`1~4`bytesが使われるため

英語以外の文字列はうまく文字数を取れないことがあります。

`unicode/utf-8` パッケージの `RuneCountInString` 関数を使えば

文字列の文字数を取得できるようになります。

“`go
package main

import (
“fmt”
“unicode/utf8”
)

func main() {
name := “テスト太郎”
fmt.Println(“len:”, len(name))
fmt.Println(“RuneCountInString:”, utf8.RuneCountInString(name))
}
“`

“`zsh:output
len: 15
RuneCountInString: 5
“`

元記事を表示

Go1.18がリリースされたので、早速Goのバージョンアップ

2022年3月16日、Go1.18がリリースされました。
https://go.dev/blog/go1.18
待望のジェネリックス機能が使えるようになったので、早速Goのバージョンアップです。

## ダウンロード
Go1.18が公開されたばかりなので、公式サイトからダウンロード・インストールします。
https://go.dev/dl/

デフォルト設定では、`/usr/local/go`配下にインストールされるので、パスを通しておきましょう。
“`
~ $ which go
/usr/local/go/bin/go
~ $ go version
go version go1.18 darwin/amd64
“`

## アプリケーションでのGoのバージョンアップ
Goの標準モジュール管理`go.mod`で管理されているアプリです。
次のコマンドで`go.mod`に記載されているGoのバージョンが上がったことを確認しています。
“`
go mod tidy -go=1.18
“`

これでアプリケーションが正常に動作することも確認しています。

元記事を表示

SQLの呼び出しでプレースホルダを使う理由

# はじめに
本記事ではGo言語とMySQLを使用しています。

Go言語のdatabase/sqlパッケージのチュートリアルを読んでて、プレースホルダを使う意味について分からなかったのですが、42Tokyoで一緒に勉強している学生から教えてもらえました。

http://go-database-sql.org/retrieving.html

> You should, in general, always prepare queries to be used multiple times. The result of preparing the query is a prepared statement, which can have placeholders (a.k.a. bind values) for parameters that you’ll provide when you execute the statement. This is much better than concatenating strings, for all the usual reasons (

元記事を表示

(競プロ)Goで挑戦するAtcoder Beginner Contest 243の復習(A~E)

# 初めに
 なんとなく競技プログラミングを再開することにしたのでその復習をここに残しておきます。ちなみに私は茶色コーダーなのでE以降は解けていないです。
 今回はバーチャル参加しましたが、今後も余裕があれば時間を測って昔のコンテストでも解いてみようと思います。

# A – Shampoo
[A – Shampoo](https://atcoder.jp/contests/abc243/tasks/abc243_a)
これは最初そのままvをaやbと比較したものを提出しましたが、普通にWAで(a+b+c)との剰余をとるのを忘れていました。
以下ACだった実装です。

“`
package main

import (
“fmt”
)

func main() {
var v, a, b, c int
fmt.Scan(&v, &a, &b, &c)
v = v % (a + b + c)
if v < a { fmt.Println("F") } else if v < a+b { fmt.Println("M") } else { fmt.Println(

元記事を表示

Go1.18がでたのでコレクション操作とかいくつか触った記録

## [github.com/samber/lo](https://github.com/samber/lo) をつかったコレクション操作

“`go
package _go

import (
“github.com/samber/lo”
“github.com/stretchr/testify/assert”
“testing”
)

func TestLodash(t *testing.T) {

type ArtistID int

type Artist struct {
ID ArtistID
Name string
Age int
}

type ArtistMap = map[ArtistID]Artist

artists := []Artist{
{
ID: 1,
Name: “A”,
Age: 25,
},
{
ID: 2,
Name: “B”,
Age: 45,
},
{
ID: 3,
Name: “C”,
Age: 30,
}

元記事を表示

OTHERカテゴリの最新記事