2023/2024

2023

  • 開発したもの振り返るとずっとGoの1年だった。
  • go routine、goでの自動テストのパターンは結構勉強した
  • 設計書(design doc) をmermaid使ってmarkdownで全部書き始めた

1-4月

常駐プロセス作成

  • Redisからデータ取得、整形、ファイルに書き出し
  • go routine(worker起動してずっとグルグルするだけだが)

5-7月

goでcliで運用ツール

9-11月

goで日時バッチ

  • RDSからデータ取得、CSV形式でS3にアップ

12-1月

  • API
  • RabbitMQでのメッセージング

2024

設計力、DB周り強化

自分のソフトウェアの作り方の方針は基本的にこの方と同じつもり

https://ymmt.hatenablog.com/entry/2024/01/05/165100

品質は一切妥協しない。ドキュメントに書かれている挙動はすべて自動テストでカバーする

その他としては、設計や仕様について各種のドキュメントをしっかり作っておくと、他の人にあとをお任せしやすいです。

1. 設計

エンタープライズ)ソフトウェア設計力をつける

アウトプット

Goでサンプルコードつけてまとめる

https://www.gitbook.com/

Introduction - mdBook Documentation

2. DB

postgressを題材にして勉強する。別にMySQLじゃなくてもいいかと思ったので。

https://soudai.hatenablog.com/entry/2024/01/18/150718

アウトプット

OSS-DB Silver/Gold取る?(可能であれば日本帰った際に取れるといい)

3. テスト

テストコード書きまくるマンとして、テスト技法ももう少し極めたいと思った。

https://dev.classmethod.jp/articles/book-software-test-techniques/

https://www.veriserve.co.jp/helloqualityworld/media/search/?tag=テスト技法解説

アウトプット

JSTQBの資格取る?別に英語ならカナダでも取れる?

https://jstqb.jp/attribute.html

4. Docker

パターン集を作る。あると便利

アウトプット

  • Nginx+go(app)
  • RabbitMQ+go(app Producer)+go(app Consumer)
  • Redis+go
  • DynamoDB+go
  • MySQL+go

https://zenn.dev/robes/articles/cf728a5d161727

習慣

サーバー、DB周りで手ぐせをつける the-art-of-command-line/README-ja.md at master · jlevy/the-art-of-command-line · GitHub

Linuxサーバー

MySQL

  • disable autocommit SET AUTOCOMMIT=0

Linuxサーバにログインしたらいつもやっているオペレーション - ゆううきブログ

go pointerチートシート

Topic

goのpointerのチートシート。教える時に自分もよく頭がこんがらがるので

自分が覚えやすいようにまとめた(ちょっと強引に)

名前 作用素 作用 対象 作用素の例
address operator & 値 → ポインター 値の変数 pointerToX := &x
indirection operator * ポインター → 値 (dereferencing) ポインターの変数 *pointerToX
pointer type * ポインター型の変数の定義 (nil pointer) 型名 var pointerToX *int
new function new() ポインター型の変数の作成(Zero value 型名(をパラメーターで渡す) var x = new(int)

Summary

少しすっきりした

How's day been?

Good 😉

compile: version "go1.19.5" does not match go tool version "go1.20.5”のメモ

久々に個人PCのGoのソースを実行しようと思ったら、タイトルのエラーが出た。1.20に上げてそのままんだったぽい

原因

パスが通っているgoのパスとGOROOTのパスが一致していなかった

❯ go env GOROOT
/usr/local/go

❯ echo $GOROOT
/usr/local/go

#GOROOTは1.19.5
❯ ll /usr/local | grep go
drwxr-xr-x 10 root root      4096 Jan 10  2023 go
-rw-r--r--  1 sho  sho  148949578 Jan 23  2023 go1.19.5.linux-amd64.tar.gz

-------------

❯ which go
/usr/bin/go

#こっちは1.20.5
❯ go version
go version go1.20.5 linux/amd64

対応

.zshrcで設定していてた環境変数GOROOTを削除。これでコンパイルエラーは出なくなった。

export GOROOT=/usr/local/go

変更後

❯ go env GOROOT
/usr/lib/go-1.20

❯ echo $GOROOT

❯ which go
/usr/bin/go

❯ go version
go version go1.20.5 linux/amd64

GOROOTとGOPATHの違い

GOROOTはgoのインストールパスを指定する。基本的には変える必要なかった。1.19と1.20を共存させたかったらここいじって切り替えるのがいいのか?

GOROOT is a variable that defines where your Go SDK is located. You do not need to change this variable, unless you plan to use different Go versions.

GOPATHはワークスペースのパス。デフォルトは~/go

GOPATH is a variable that defines the root of your workspace. By default, the workspace directory is a directory that is named go within your user home directory (~/go for Linux and MacOS%USERPROFILE%/go for Windows).

golang mapチートシート

パターン 定義 len Read Write
nil map var nilMap map[string]int 0 できる panic
empty map literal emptyMapLiteral := map[string]int{} 0 できる できる
nonempty map literal teams := map[string][]string{"Orcas": {"Fred", "Ralph", "Bijou"},"Lions": {"Fred", "Ralph", "Bijou"},"Kittens": {"Fred", "Ralph", "Bijou"},} n できる できる

1. nil map

定義

var nilMap map[string]int

len

fmt.Printf("[nilMap] len: %v\n", len(nilMap))
//[nilMap] len: 0

読み取り

できる。値のzero valueを返す。この例だとintのzero value

fmt.Printf("[nilMap] read : %v\n", nilMap["apple"])
//[nilMap] read: 0

書き込み

panic起きる

nilMap["apple"] = 10
//panic: assignment to entry in nil map

2. empty map literal — non nil

定義

emptyMapLiteral := map[string]int{}

len

fmt.Printf("[emptyMapLiteral] len: %v\n", len(emptyMapLiteral))
//[emptyMapLiteral] len: 0

読み取り

できる。値のzero valueを返す。この例だとintのzero value

fmt.Printf("[emptyMapLiteral] read: %v\n", emptyMapLiteral["apple"])
//[emptyMapLiteral] read: 0

書き込み

emptyMapLiteral["apple"] = 10
fmt.Printf("[emptyMapLiteral] read: %v\n", emptyMapLiteral["apple"])
//[emptyMapLiteral] read: 10

3. nonempty map literal — non nil

定義

teams := map[string][]string{
        "Orcas":   {"Fred", "Ralph", "Bijou"},
        "Lions":   {"Fred", "Ralph", "Bijou"},
        "Kittens": {"Fred", "Ralph", "Bijou"},
    }

len

fmt.Printf("[teams] len: %v\n", len(teams))
//[teams] len: 3

読み取り

fmt.Printf("[teams] read: %v\n", teams["Orcas"])
//[teams] read: [Fred Ralph Bijou]

書き込み

teams["Lakers"] = []string{"A", "B", "C"}
//[teams] read: [A B C]

2022/2023

2022振返


  • 英語は春~夏過ぎまで集中的に勉強できた
    • R, Wスコアアップ
  • 金融の業務知識がついたと思われる一年だった(これが一番伸びたかもしれない)
  • Golangでの機能開発
  • React + Reduxでの画面開発
    • これが秋以降一番大変だった
  • 秋後半からSQLの本を読み始めた。データベース関連は個人的に性に合うのでおもろい

    Learning SQL: Generate, Manipulate, and Retrieve Data

  • 2022年の目標は英語以外はほぼ積み残しという感じ笑

    • プライベートで取れる時間を英語に割いたので、当然といえば当然の結果

Golang 😃

  • Learning Go読んでいたおかげだいぶ業務で活かせた気はする
  • Go routineはもう少し練習必要かなと

Java/Spring 😰

  • 結局ほとんど手つかずでFinish

Blockchain関連 😰

  • これは当分いいかな。冬の時代だし…

インフラ(AWS/Docker)🥺

  • インフラ関係にも手を付ける余裕はなかった。2023年はDockerでローカル環境を1から用意することありそう。そのタイミングで久々にドキュメント見るかな

アルゴリズムデータ構造 🙂

  • Leetcodeのweekly contestに毎週参加を1ヶ月くらいがんばった笑
  • 課題はわかったので、今年の具体的な目標に落とし込む
  • 問題は継続的に続けていく習慣形成

英語 😃

  • 毎日英語の勉強をする習慣作れたのが一番の収穫
  • 毎日ライティングは本当に効果があったので、継続したい
  • リスニング弱点は弱点だけど、実生活ではだいぶ聞き返すこと減っている

2023目標


  • 1番の目標はここ数年、仕事・勉強 > 私生活 だったので、今年は私生活比重多に戻していく
    • 料理、運動(ヨガ、筋トレ、ランニング)、ポケモンランクマ
  • 剣盾はマスボ行って満足したけど、SVは継続的にランクマ潜る
  • たくさん本読みたいというわけではないが、本読む時間は増やしたいかな。寝る前とか読書時間でいい

英語

  • 今年はスピーキング重視。瞬間英作文的なのが有効だと思っているので、継続してみる
  • 地味だけど英単語、英作文は継続(英語力には1番効く)

アルゴリズムデータ構造

  • Leetcode weekly contest
    • 1,2問目を40分
    • 3問目も時間内に解ける回数増やしたい
    • 30min/day → 過去のLeetcode weekly contest #1,2
    • 週末は知らない系統の問題の解説記事など読む

SQL

  • これも100本ノック的な問題解いていくのいい気がしたので、問題解いていきたい
  • あとは、トランザクション、インデックスまわりをもっと理解深める

Go or Java

React

  • 去年の夏過ぎにだいぶ勉強しちゃったので、もう少し続けたい気持ちはある

Docker

  • Learn and adopt Docker Multi-stage builds into your new Dockerfiles.

Multi-stage builds

とりあえず、丸3年閉じ込められたカナダから来月出国できるのうれしい。日本で一旦リフレッシュ

プライベートリポジトリをgo getして「terminal prompts disabled」とか「Confirm the import path was entered correctly.」とか言われたときのメモ

プライベートリポジトリのモジュールをgo getするための設定(https

社内のプライベートリポジトリをgo getする際にしばしば混乱するのでメモ。httpsでのアクセスが必要な環境なので、https前提の話となっている。

何も設定していない場合に発生するエラー

前提:

  • go version go1.15.6 linux/amd64 (ちょっと古い…)
  • GOPRIVATEを設定していない
  • httpsの認証情報を設定してない
  • キャッシュクリア
  • go.modがあるディレクトリで実行

go get, go get ${モジュール名}

  • go.modに記載のモジュールをインストールする。
  • ①プライベートリポジトリの認証を突破できない
❯ go get
①go: github.com/Sho372/mysecret@v0.0.0-20221015173609-50bc2589408e: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /home/sho/goworkspace/pkg/mod/cache/vcs/f7c95e78ccfc05412466703c9dfe4d96cfb78fa98dc272d0d7347bff3f468e2d: exit status 128:
        fatal: could not read Username for 'https://github.com': terminal prompts disabled

ちなみに、go.modがない環境で実行すると…

  • ①に加えて②も起きる
❯ go get github.com/Sho372/go-const
①go get github.com/Sho372/go-const: module github.com/Sho372/go-const: git ls-remote -q origin in /home/sho/goworkspace/pkg/mod/cache/vcs/1213af4aff3f33e0fc4e0690d9630417ffc2fcdd363e78fe9cf3cf41f1e5a64c: exit status 128:
        fatal: could not read Username for 'https://github.com': terminal prompts disabled
②Confirm the import path was entered correctly.
If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.

1. GOPRIVAETを設定

今回はモジュール名を直接指定する。モジュール名はモジュール側のgo.modに書いてある。

❯ export GOPRIVATE=github.com/Sho372/mysecret
❯ env | grep GOPRIVATE
GOPRIVATE=github.com/Sho372/mysecret

指定するもジュルー名がわからない時はモジュール側のgo.modを確認する

❯ cat go.mod
module github.com/Sho372/mysecret

go 1.15

上記のexportで設定してもいいが、goの設定なので、go env -wで設定するようにしている。

go env -w GOPRIVATE=github.com/Sho372/mysecret

2. httpsの認証情報を設定に追加して、認証情報入力をスキップする

.netrc

Frequently Asked Questions (FAQ) - The Go Programming Language

git confg

プライベートリポジトリをgo getする方法 - 尋常でないもふもふ

bitbucket, gitlab

Today I Learned - Fix: go get private repository return error terminal prompts disabled

こちらも.netrcで設定してもいいが、.gitconfigで設定がまとまっている方がいいので、gitの設定で解決するようにしている。

git config --global url."https://${githubのaccess token}:x-oauth-basic@github.com/".insteadOf "https://github.com/"
❯ cat ~/.gitconfig
[user]
        email = 32non23ca@gmail.com
        name = Sho372
[url "https://${githubのaccess token}:x-oauth-basic@github.com/"]
        insteadOf = https://github.com/

3. go get

設定が完了したら、欲しいプライベートモジュールをgo getする

❯ go get [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret)
go: downloading [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret) v0.0.0-20221015173609-50bc2589408e
go: [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret) upgrade => v0.0.0-20221015173609-50bc2589408e
❯ cat go.mod
module go-import-package
go 1.15

require github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e // indirect

go getが成功すると、GOMODCACHE配下にread onlyで格納される

❯ go env | grep GOMODCACHE
GOMODCACHE="/home/sho/goworkspace/pkg/mod"
❯ pwd
/home/sho/goworkspace/pkg/mod/github.com/!sho372
❯ ll
total 16
drwxr-xr-x  4 sho sho 4096 Oct 16 02:41 .
drwxr-xr-x 40 sho sho 4096 Oct 16 04:43 ..
dr-x------  2 sho sho 4096 Oct 16 02:41 mysecret@v0.0.0-20221015173609-50bc2589408e
❯ go env | grep GOCACHE
GOCACHE="/home/sho/.cache/go-build"

4. ソース上で取得したモジュールをimportして使う

最後にソース上でimportする

import (
        "fmt"
        "log"

        "github.com/Sho372/mysecret" ★
        "github.com/shopspring/decimal"
)

go mod vendor (vendoring)

go mod vendorを実行すると、vendorディレクトリが生成され、ソースコードが格納される。

  • vendorディレクトリが生成され、この配下に依存モジュールのソースがダウンロードされる
  • vendorがある場合は、そこにあるモジュールで依存が解決されるらしい
  • GOMODCACHE配下とは異なり、修正可能なのでデバッグコードを差し込むことができる
❯ ll
total 2368
drwxrwxrwx 1 sho sho     512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho     512 Oct 16 03:31 ..
-rwxrwxrwx 1 sho sho     148 Oct 16 05:41 go.mod
-rwxrwxrwx 1 sho sho     404 Oct 16 04:54 go.sum
-rwxrwxrwx 1 sho sho 2421984 Oct 16 05:33 main
-rwxrwxrwx 1 sho sho     261 Oct 16 04:57 main.go

❯ go mod vendor

❯ ll
total 2368
drwxrwxrwx 1 sho sho     512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho     512 Oct 16 03:31 ..
-rwxrwxrwx 1 sho sho     148 Oct 16 05:41 go.mod
-rwxrwxrwx 1 sho sho     404 Oct 16 04:54 go.sum
-rwxrwxrwx 1 sho sho 2421984 Oct 16 05:33 main
-rwxrwxrwx 1 sho sho     261 Oct 16 04:57 main.go
drwxrwxrwx 1 sho sho     512 Oct 17 04:49 vendor ★

❯ ll vendor/github.com/Sho372
total 0
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 ..
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 mysecret ★

キャッシュクリア実験

上記の手順でプライベートパッケージからパッケージを取得したあとに、以下を実施してキャッシュクリアの挙動を確かめた

1 go clean -modcache

  • GOMODCACHE="/home/sho/goworkspace/pkg/mod" ディレクトリが削除される
  • このあとにgo buildを実行してもまだ通る

2 go clean --cache

  • GOCACHE="/home/sho/.cache/go-build"配下のキャッシュが削除される
  • このあとにgo buildを実行してもまだ通る

3 rm -rf vendor,go clean -modcache,go clean --cache

  • vendorディレクトリを削除
  • go buildするとGOCACHEにキャッシュが残るので再度これもクリア
  • 念のためGOMODCACHEもクリア
  • これで完全にローカルからパッケージが消え去ったはず

4 go build

  • パッケージのダウンロードが開始した。(ただし、Go 16ではgo build時の自動ダウンロードはなくなったらしいので、go get or go mod tidyを実行)
❯ go build
go: downloading github.com/shopspring/decimal v1.3.1
go: downloading github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e

キャッシュクリアまとめ

つまり、ローカルのパッケージを完全に削除して、再ダウンロードしたい場合は以下ぽい

  1. もしvendorディレクトリがあるなら、rm -rf vendor
  2. go clean --cache
  3. go clean -modcache
  4. go get or go mod tidy
  5. もしvendorディレクトリが必要なら、go mod vendor

プライベートモジュールの改修

  • プライベートパッケージ側でブランチを切って改修
  • そのブランチ版をインポートして使ってみる

1. プライベートモジュールで改修

  • feature ブランチを作成して改修し、push
  • 新たに pokemons パッケージを作成

2. featureブランチ版をgo get

  • @${ブランチ名}で指定できる
  • go get -uだとさらにモジュールが依存するモジュールの最新も取得してくれるらしい。こっちが適切?
❯ go get github.com/Sho372/mysecret@feature
go: github.com/Sho372/mysecret feature => v0.0.0-20221016202503-eb4c4bc6b253
go: downloading github.com/Sho372/mysecret v0.0.0-20221016202503-eb4c4bc6b253
❯ cat go.mod
module go-import-package

go 1.15

require (
        github.com/Sho372/mysecret v0.0.0-20221016202503-eb4c4bc6b253
        github.com/shopspring/decimal v1.3.1
)

3. 使ってみる

  • 今回は、「モジュール名」と「パッケージ名」が異なるから?、${モジュール名}/${パッケージ名}で指定するとimportできた
import (
    "fmt"
    "log"

    "github.com/Sho372/mysecret"
    "github.com/Sho372/mysecret/pokemons""github.com/shopspring/decimal"
)

func main() {

    mysecret.SecretProcess()
    fmt.Println(pokemons.PIKACHU) ★

    amount, err := decimal.NewFromString("1.23")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(amount.String())
}

4. 元のmainブランチ版に戻す

  • go get ${モジュール名}@latestでも、元のmasterブランチの最新に戻った
  • go get ${モジュール名}@latestはgo get ${モジュール名}と同じ意味らしい
go get github.com/Sho372/mysecret@latest
go: github.com/Sho372/mysecret latest => v0.0.0-20221015173609-50bc2589408e
❯ cat go.mod
module go-import-package

go 1.15

require (
        github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e
        github.com/shopspring/decimal v1.3.1
)
❯ go build
go: finding module for package github.com/Sho372/mysecret/pokemons
main.go:8:2: module github.com/Sho372/mysecret@latest found (v0.0.0-20221015173609-50bc2589408e), but does not contain package github.com/Sho372/mysecret/pokemons

masterブランチ指定でもいける

go get github.com/Sho372/mysecret@master
go: github.com/Sho372/mysecret master => v0.0.0-20221015173609-50bc2589408e

Modules · golang/go Wiki

goコマンド

公式ドキュメント

Go Modules Reference - The Go Programming Language

go.modで定義された、プロジェクトの依存モジュールを取得したい時

  • go get or go mod tidy
    • 格納先:GOMODCACHE="/home/sho/goworkspace/pkg/mod"
cd ${go.modがあるディレクトリ}
go get or go mod tidy

プロジェクトに新しいモジュールを追加したい時(go.modへの追記)

  • go get ${モジュール名}
    • 格納先:GOMODCACHE="/home/sho/goworkspace/pkg/mod"
cd ${go.modがあるディレクトリ}
go get ${モジュール名}
cat go.mod  //取得したモジュール名が追記されている

vim-goimportsが効かない時

vim-importsなんか効かないなぁ~とか思ってたら、そもそもgoimportsインストール前提のプラグインでしたよという話。

vimのgoの環境はググってでてきた記事の設定をほとんどそのままコピペしていたので…調べるまで全く気づかなったでござる。

goimports

https://github.com/mattn/vim-goimports

  1. Requirementsにgoimports書いてあったので、goimportsをインストール
  2. .vimrcに Plug 'mattn/vim-goimports 追記して、vim-goimportsプラグインインストール(vim-plugでインストール)
  3. :w でフォーマットされて、import文追記されたらOK