Neovim + DAP + Go

TL;DR DAP(Debug Adapter Protocol)の力を借りれば、Neovim上でも視覚的にGoのデバッグが出来ました。 ここでは下記については話しません。 DAPの詳細 packer.nvimでのインストール方法 vscode-goのdebugAdapter.jsの使用方法 Neovimでデバッグするモチベーション v0.2.2から色々変わったNeovimを久々に触ってみようかと思いinit.luaへ以降して遊んでいました。 起動が早いだけでなく、LSP系の動作もサクサク動いてここ2ヶ月程快適に過ごしています。 ただ、VSCodeでのデバッグ機能がとても便利なため、デバッガ使用時のみこの快適な環境を離れていました。 どうにかNeovim上で完結させられないか…。 DAP DAPの説明はリンク先や他HPをご参照ください。 イメージを持ってもらうためLSPを引き合いに出すと、LSPがテキスト編集時に定義や変更内容や補完候補等を返すのに対して、DAPはデバッガとやりとりしてデバッグ情報を返す位のイメージを持ってもらえれば大丈夫だと思います。 Neovim + DAP + Go 使うプラグインは下記になります。 mfussenegger/nvim-dap : NeovimのDAPクライアント。VSCodeのlaunch.jsonも使用可 rcarriga/nvim-dap-ui : nvim-dapを視覚的に操作しやすいUI leoluz/nvim-dap-go : DAPのGo用設定(delve dap起動) nvim-treesitter/nvim-treesitter nvim-dap-goでテストをデバッグする際、近くのテストを見つけるのに必要 packer.nvimの設定 VSCodeのlaunch.jsonを使用しない場合、require('dap.ext.vscode').load_launchjs()は不要です。 launch.jsonを読み込めた場合、デバッグ方法の選択時にlaunch.jsonの内容が追加表示されて選択可能になります。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 -- dap plugin installation with packer.nvim ... -- dap use { "rcarriga/nvim-dap-ui", requires = { "mfussenegger/nvim-dap", "leoluz/nvim-dap-go", "nvim-treesitter/nvim-treesitter" }, config = function () vim....

<span title='2021-11-24 00:00:00 +0000 UTC'>11月 24, 2021</span>&nbsp;·&nbsp;3 分

gin + gorm v2でのセッションやトランザクション

TL;DR ginでの各リクエストを1セッションで管理しつつ、トランザクションも管理したい。 ginのmiddlewareで、gin.Contextにgorm.WithContextを用いてGormのセッションを持たせる。 ginの各HandlerFuncの中では、gin.Context内のGormセッションからDBへアクセスする。 モチベーション Gormはv2になり色々と変わった。 Gorm 2.0 Release Note 色々な記事が書かれているがTransactoinに関してあまり書かれていない。 下記疑問を払拭して正しい使い方を自分なりに確かめたかったので試した。 なんとなく動くがこれで正しいのか? ドキュメントを読んでいてSkipDefaultTransaction:trueだと30%もパフォーマンスが上がるというがその設定はtrueにしていいいのか? っていうか、DefaultTransactionって何?ロールバックの単位とかどうやって指定するの? 確認&検証 検証時に作成したソースはgithub.com/lunarxlark/gorm2-tx Context Gorm 2.0 #Context GormはContextサポートを提供し、それを使いたかったらWithContext使ってくれ。 また、Sessionには単セッションモードと継続セッションモードがある。 普通は、継続セッションモードを使って、複数オペレーションをまとめるよ。 …GormのSessionってどんなことできるの? Session Gorm 2.0 #Session Gormは`Session`メソッドをを通して、新しいセッションを提供するよ。 新しいセッションを作る場合、設定がたくさんあるよ。DryRunやLoggerとかね。 …新しいセッションを一々作るのは望んでない。 Contextサポートしてくれるってことなのでgin.Contextへ埋め込む時にセッションを作成してそれを使い回したい。 gorm.WithContextのreturnはdb.Sessionとなっている(下記はgormのソースから抜粋)ので、gin.Contextへ埋め込むだけで新たにセッションを作る必要はない。 1 2 3 4 // WithContext change current instance db's context to ctx func (db *DB) WithContext(ctx context.Context) *DB { return db.Session(&Session{Context: ctx}) } ここまでで下記みたいな感じになる。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 func main() { //....

<span title='2021-09-12 00:00:00 +0000 UTC'>9月 12, 2021</span>&nbsp;·&nbsp;2 分

2021年版 vim + goplsの設定

goplsが出てから, vimでも定義ジャンプやシンボル検索、ドキュメント参照等が行えるようになった。 たまにVSCodeを触りvimでの作業を改善できないか考える中で、自身の設定が古いことに気付いた。また、ググってもなかなか出てこなかったのでメモとして記述する。 cf. GitHub dotfiles いきなりだが、vimrcとvim-lsp-settings/settings.jsonを抜粋して貼り付ける。 以前、GoではLspCodeAction, LspCodeLens等をサポートしていなかったが、今では使えるようになっている。 キーマップに設定している関数は全てGoで使用出来る。 ただし、カーソルがどこにいても実行出来るわけではないので注意が必要。 LspCodeActionはカーソルの位置によって実行内容が変わるのでそこも注意。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ... Plug 'prabirshrestha/vim-lsp' Plug 'mattn/vim-lsp-settings' Plug 'prabirshrestha/asyncomplete-lsp.vim' Plug 'mattn/vim-gomod' ... " ------------------------------------------------------------------------------ " vim-lsp " ------------------------------------------------------------------------------ function! s:on_lsp_buffer_enabled() abort setlocal omnifunc=lsp#complete setlocal signcolumn=yes if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif nmap <buffer> <leader>ac <plug>(lsp-code-action) nmap <buffer> <leader>cl <plug>(lsp-code-lens) nmap <buffer> <leader>df <plug>(lsp-definition) nmap <buffer> <leader>dd <plug>(lsp-document-diagnostics) nmap <buffer> <leader>im <plug>(lsp-implementation) nmap <buffer> <leader>pdf <plug>(lsp-peek-definition) nmap <buffer> <leader>sm <plug>(lsp-document-symbol-search) nmap <buffer> <leader>Sm <plug>(lsp-workspace-symbol-search) nmap <buffer> <leader>rf <plug>(lsp-references) nmap <buffer> <leader>td <plug>(lsp-type-definition) nmap <buffer> <leader>rn <plug>(lsp-rename) nmap <buffer> <leader>en <plug>(lsp-next-error) nmap <buffer> <leader>ep <plug>(lsp-previous-error) nmap <buffer> <leader>ho <plug>(lsp-hover) let g:lsp_format_sync_timeout = 500 autocmd!...

<span title='2021-06-16 00:00:00 +0000 UTC'>6月 16, 2021</span>&nbsp;·&nbsp;2 分

load test with dynamic payload by tsenart/vegeta

負荷テストツールvegetaのコマンドでの使い方ぐはググるとたくさん出てくるが、ライブラリとして仕様している記事が少なく手こずったのでメモ代わりに記事にする。 やりたいこと リクエスト毎にRequestの内容を動的に変えて、負荷をかけたかった。 Headerに持つタイムスタンプがリクエスト時のタイムスタンプになるように。 userIdはuniqueになるように。(同じユーザだと重複リクエストを弾く処理があったため。) 具体的には下記のような感じでリクエストを送りたい。 1 2 3 4 5 {"header": {"timestamp":"1234"}, "body": {"userId": "lunar-1"}} {"header": {"timestamp":"1234"}, "body": {"userId": "lunar-2"}} {"header": {"timestamp":"1235"}, "body": {"userId": "lunar-3"}} ... {"header": {"timestamp":"1240"}, "body": {"userId": "lunar-n"}} vegeta.Targeterは func(*vegeta.Target) error である。 また、vegeta.Attackは、vegeta.Targeterをgoroutineで都度呼び出して、Targeter内からTargetに基づきリクエストしていることから、都度Targetが変わるようなTargeterを返す関数を作成し、それをAttack時に呼び出せば良さそう。 ってことが、 [QUESTION] Sending requests with dynamic body #330に書いてあって何度も行き来した結果やっと理解できた…。 上記を拝借して以下のようにすることで目的を達成できた。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 type yourRequestBody struct { UserID string } targeter := func(id uint64) vegeta....

<span title='2021-03-11 00:00:00 +0000 UTC'>3月 11, 2021</span>&nbsp;·&nbsp;1 分

Custome Logger using LoggerWithConfig in Echo

WebFramework EchoのLoggerを弄っていて気付いた点があったのでメモ。 sample code 箇条書き responseログにHeader X-Any-Headerを出力したい場合、ログフォーマットに"any_header":${header:x-any-header}を指定すればいいよ responseログにQueryParamerter ?anyparam=xxxを出力したい場合、ログフォーマットに"any_query":${query:anyparam}を指定すればいいよ デフォルトで出力されるカラム’id’はHeader X-Request-Id を指定すると出力されるよ Skipperを設定することで、path毎にログ出力する/しない等を設定出来るよ 1, 2, 3はEchoのそういう機能だってことで特にありません。 4は結構便利だなと思いました。以下のサンプルコードでは、/healthcheckに来た場合とCI/CD等での自動テスト時にはresponseログを出力しないようにする設定例です。 sample 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 // Middleware e....

<span title='2020-11-10 02:51:09 +0900 +0900'>11月 10, 2020</span>&nbsp;·&nbsp;2 分

My Favorite Usage urfave/cli

参加しているプロジェクトでurfave/cliを使っている。使い方はExampleにあるのと同じ書き方で使っている。 大半のバッチ処理をコマンドとして記述しているので、Exampleの書き方だとだいぶ見辛くなってきた。縦長のコマンド定義とオプション説明で目的の処理を探すのにもページ送りを何度もする。なんとかしたい。 ...

<span title='2020-02-06 00:00:00 +0000 UTC'>2月 6, 2020</span>&nbsp;·&nbsp;1 分

Error 'undefined' when go run

x…motemen/ghqを写経している時、 go run main.go 出来ないことに気付いた。 下記が実行時のエラーになる。ちなみに、 go build は出来る。 1 2 3 4 ~/d/s/g/x/ghq >>> go run main.go # command-line-arguments ./main.go:38:17: undefined: commands ~/d/s/g/x/ghq >>> commands が見つからない?同じ階層の commands.go には下記記述がちゃんとあるのに、どうして見つからない…。 1 2 3 4 5 6 var commands = []*cli.Command{ commandGet, commandList, commandRoot, commandCreate, } 理由は、go runの引数に指定したファイル(+ importされるパッケージ)しか読み込まないから。 実際、go run main.go commands.goに変更すると上記エラーは解消される…が、別のエラーとなる。 今度は違うのが見つからないって言われる。 1 2 3 4 5 6 ~/d/s/g/x/ghq master >>> go run main.go commands.go # command-line-arguments ./commands.go:25:10: undefined: doGet ....

<span title='2020-02-04 00:00:00 +0000 UTC'>2月 4, 2020</span>&nbsp;·&nbsp;1 分