20190830のGoに関する記事は5件です。

goleakでgoroutine leakのリスクを減らす

このページについて

uberが手掛けているgoleakを使ってgoroutine leakを検出できるか試してみました。簡単なデモコードではしっかりエラーにしてくれたので、使ってみてもよいのかなと思います。

現在(2019-08)α版 なのでもう少し待ってみてもいいかもしれませんが、、

内容

goroutine leakの起こる関数を書き、goleakを使って検出できるか試してみます。

関数

package helper

import (
    "fmt"
    "time"
)

func Leak(sleep int) {
    fmt.Println("leak test")
    go func() {
        fmt.Println("start goroutine")
        for {
            // leak しないパターンも試す
            if sleep == 0 {
                return
            }
            time.Sleep(time.Duration(sleep) * time.Second)
        }
    }()
}

テスト

leak_test.go
package helper

import "testing"

func TestLeak(t *testing.T) {
    type args struct {
        sleep int
    }
    tests := []struct {
        name string
        args args
    }{
        {
            name: "leak",
            args: args{
                sleep: 1,
            },
        },
        {
            name: "not leak",
            args: args{
                sleep: 0,
            },
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            Leak(tt.args.sleep)
        })
    }
}

goleakはパッケージ全体に適用したい場合はTestMainから動かすと良いみたいです

main_test.go
package helper

import (
    "testing"

    "go.uber.org/goleak"
)

func TestMain(m *testing.M) {
    goleak.VerifyTestMain(m)
}

これで準備は整いました。
テストを実行します

$ go test -v ./...
=== RUN   TestLeak
=== RUN   TestLeak/leak
leak test
start goroutine
=== RUN   TestLeak/not_leak
leak test
start goroutine
--- PASS: TestLeak (0.00s)
    --- PASS: TestLeak/leak (0.00s)
    --- PASS: TestLeak/not_leak (0.00s)
PASS
coverage: 100.0% of statements
goleak: Errors on successful test run: found unexpected goroutines:
[Goroutine 33 in state sleep, with runtime.goparkunlock on top of the stack:
goroutine 33 [sleep]:
runtime.goparkunlock(...)
    /usr/local/Cellar/go/1.12.1/libexec/src/runtime/proc.go:307
time.Sleep(0x3b9aca00)
    /usr/local/Cellar/go/1.12.1/libexec/src/runtime/time.go:105 +0x159
github.com/smith-30/ootd/helper.Leak.func1(0x1)
    /go/src/github.com/smith-30/ootd/helper/leak.go:16 +0xa0
created by github.com/smith-30/ootd/helper.Leak
    /go/src/github.com/smith-30/ootd/helper/leak.go:10 +0xa6
]
FAIL    github.com/smith-30/ootd/helper 0.457s
Error: Tests failed.

goroutineリークを検出してテストを落としてくれていますね!
もちろん、テストケースが not leak のみの場合はエラーで落ちません
goroutineをバリバリ使うデーモンや並列処理を使うAPIのメインロジックのe2eテストの際には使っていきたいと思っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

golangを触った初日メモ

概要

知ったことをメモする。
golang幼稚園生?

ライブラリ

Left align Right align
realize ホットリロード
goose DBマイグレーション
siris Webアプリケーションフレームワーク
go-cmp 値比較
pprof プロファイリング
guregu/null 変数にnullが入ってきたときに型のデフォルト値にするのではなくnullとして扱えるようにする
hashicorp/golang-lru LRUキャッシュ
gorm ORM
julienschmidt/httprouter ルーティング
kr/pty unix操作するやつ
labstack/echo Webサーバー
go-urn URNパーサー

Log出力

import "log"

func main() {
    log.Print("hoge")
}

実行結果

# go run main.go
2019/08/30 09:20:52 hoge

echoのサーバー起動

import "github.com/labstack/echo/v4"

func main() {
    e := echo.New()
}
# go run main.go
   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.1.5
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8081
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GORM エラーハンドリング

user, err := module.Configure.Repositories.UserRepository.FindByID(id)
// データがない時のエラー
if err == gorm.ErrRecordNotFound {
    c.JSON(http.StatusNotFound, gin.H{"error": fmt.Sprintf("reservation number not found")})
        return
}
// その他のエラー
if err != nil {
   c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
   return
}

err == gorm.ErrRecordNotFound の時は http.StatusNotFound
http.StatusInternalServerError
http.StatusBadRequest

http.StatusNotFound  404 
// 欲しいデータが見つからない。
http.StatusBadRequest 400
// リクエストがおかしい
type reqParams struct {
    user_id  uint64
}
なのにstring でパラメーターを送ってしまったとか

http.StatusInternalServerError  500
// サーバーと接続ができない
//サーバーがダウンしているなど。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go言語+VSCodeで"run test"を押したときにも.envの環境変数を適用

はじめに

VSCodeでGoのコードを書いている場合、任意の関数・メソッド内で右クリックメニューから
Go: Generate Unit Tests For Function を押すだけでテーブルテスト形式のテストが
編集中ファイル名_test.go に自動生成され、さらにテスト関数の上に出るコードレンズのリンク
run test をポチるだけでテスト実行できます。
ドチャクソ便利ですね。
スクリーンショット 2019-08-30 2.47.48.png
↑これ

でも上記テストを実行する環境はVSCodeを開いた環境なので、
.env 等で環境変数を管理していると適用されません。

.envを使用するように設定を変更

Goのextentionには標準で設定項目が用意されているので、
そこに.envファイルのパスを指定するだけでOKです。

(開いているワークスペース直下に.envファイルが有ると仮定します。)
VSCodeの設定画面を開き、Go configurationの Test Env File
テキストフィールドに ${workspaceFolder}/.env と指定しましょう。

スクリーンショット 2019-08-30 2.38.10.png

これだけでOKです。

あ、これはユーザー設定というよりPJに依存した設定であることが多いと思うので
User SettingsではなくWorkspase Settingsの方に書いたほうがいいかもしれません。

おまけ

スクショに見えているTest Env Varsを編集でもテスト開始前に環境変数をセットできます。
また、Test Flagssettings.json上で編集("go.testFlags": ["-v"],を追加)して
-vをつけておけば、テスト中に標準出力に吐かれたログを見ることができるので
テストがサイレント落ちして理由わかんねーよって時には威力を発揮します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Win10にてパッケージ管理(chocolatey)を使ってGo言語をインストール

目的

  • WindowsでもLinuxのようにパッケージ管理を使ってソフトを管理したい

Chocolatey(パッケージ管理)のインストール

(以下、公式サイトの手順)

管理者権限でコマンドプロンプトを起動

image.png

インストール実行

コマンドプロンプトで以下を実行
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

ちなみに管理者権限でコマンドプロンプト起動しないと実行時に以下のエラーになります。
image.png

コマンドプロンプトでバージョン確認

コマンドプロンプトで以下を実行
C:\Windows\system32>choco
Chocolatey v0.10.15
Please run 'choco -?' or 'choco <command> -?' for help menu.

パッケージ管理からGo言語(Golang)のインストール

コマンドプロンプトで以下を実行
C:\Windows\system32>choco install golang

image.png

チョコってコマンドが個人的に好きです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む