月曜からストレスフリーでTypeScriptのコーディングするためのメモ
TypeScriptコンパイラー TSCのインストール
https://code.visualstudio.com/docs/languages/typescript#_installing-the-typescript-compiler
グローバルインストール
npm install -g typescript
プロジェクトごとのインストール
npm install --save-dev typescript
確認
tsc --version
プロジェクトディレクトリを作成
https://code.visualstudio.com/docs/languages/typescript#_hello-world
mkdir HelloWorld cd HelloWorld code .
.tsのソースを用意して、コンパイル&実行(tscコマンド)
- テストソースを用意
tscコマンドで.tsを.jsにトランスパイル (
helloworld.jsが生成される)tsc helloworld.ts- コンパイルがソース -> バイナリに対して、トランスパイルはA言語 -> B言語への変換を指すらしい
実行 ※ただのJS実行
node helloworld.js
Hover information
https://code.visualstudio.com/docs/languages/typescript#_hover-information
⌘K⌘Iでも出せる
Signature help
https://code.visualstudio.com/docs/languages/typescript#_signature-help
⇧⌘Spaceでも出せる
Errors and warnings
https://code.visualstudio.com/docs/languages/typescript#_errors-and-warnings
⇧⌘Mでサマリー出せるF8でインラインで詳細出せる
Formatting
- VSCodeにはTypeScriptのフォーマッターが組み込まれている
typescript.format.enableでフォーマッターの有効・無効を切替える (defaultでtrue)- フォーマットの細かい設定は
typescript.format.* - 設定値については↓で確認
- フォーマットの細かい設定は
VSCode設定デフォルト値一覧
https://code.visualstudio.com/docs/getstarted/settings#_default-settings
Refactoring
処理を抽出
- 関数にしたい部分をハイライト
- 電球マークをクリック or
⌘. - Extract function and Extract constant
処理をループブロックで囲む
- 関数にしたい部分をハイライト
- 電球マークをクリック or
⌘. - ブロックの挿入から選択
リネーム
F2
Linters
https://code.visualstudio.com/docs/languages/typescript#_linters
- ESLintを設定
- typescript-eslint
ESLint
以前はTSLintが推奨されていたが、TSLintはdeprecatedになって、現在はESLintを使ったほうがいいとのこと Migrate from TSLint to ESLint
コマンドでインストールと設定ファイルを作成
eslint.config.jsがプロジェクトルートに生成される (最近設定ファイル名が変わったみたい)
npm init @eslint/configpackage.jsonを編集
- このままでESLintを実行すると以下のエラーが出た
shell SyntaxError: Cannot use import statement outside a module - メッセージに出ている通り、
"type": "module"を設定する(node:46256) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
- このままでESLintを実行すると以下のエラーが出た
{
"name": "ts-practice",
"version": "1.0.0",
"description": "",
"type": "module",
...
}
- 実行
shell npx eslint .
VSCodeのESLint拡張
- ESLintの拡張をインストール
- 最近ESLintの設定ファイル名が
eslint.config.jsになったせいで、公式リリース版では動かなった。プレリリース版をインストールしたら正常に動作した - 正常に動作していればソース上で指摘される。「問題」からも確認可能
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. 設計
(エンタープライズ)ソフトウェア設計力をつける
- 「Patterns of Enterprise Application Architecture(通称:PofEAA)」読む
- 設計書(design doc)のテンプレと書き方を確立する
アウトプット
Goでサンプルコードつけてまとめる
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サーバー
- disable autocommit
SET AUTOCOMMIT=0
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
gowithin 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の本を読み始めた。データベース関連は個人的に性に合うのでおもろい
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
- 今年最初の開発タスクをどっちで実装するかで決める
- Goの場合 → Go routineとバックエンドを趣味で作ってみる
Javaの場合 → Spring本を読む
React
- 去年の夏過ぎにだいぶ勉強しちゃったので、もう少し続けたい気持ちはある
Docker
- Learn and adopt Docker Multi-stage builds into your new Dockerfiles.
とりあえず、丸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
キャッシュクリアまとめ
つまり、ローカルのパッケージを完全に削除して、再ダウンロードしたい場合は以下ぽい
- もしvendorディレクトリがあるなら、
rm -rf vendor go clean --cachego clean -modcachego getorgo mod tidy- もし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
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 //取得したモジュール名が追記されている