老是失憶……

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
# 跑起一個 ubuntu container 並且用 foreground 模式進入 bash
$ sudo docker run -it ubuntu bash

$ sudo docker run -d -p [HOST_PORT]:[CONTAINER_PORT] --name [CONTAINER_NAME] [IMAGE_NAME]:[version]

# 停止並移除 container
$ sudo docker rm --force [CONTAINER]

# 列出 local 有的 image
$ sudo docker images

# 在 Docker Hub 搜尋 image
$ sudo docker search [KEYWORD]

# 在有 Dockerfile 的資料夾 build Docker image
$ sudo docker build --tag [NAME]:[TAG] .

# Remove Docker image
$ sudo docker rmi [IMAGE]

# Login to a Docker registry
# 如果是 private registry 就要 login 才能 push
$ sudo docker login

# Push Docker image
$ sudo docker push [IMAGE_NAME]:[TAG]

用 Go 寫了個可以讀 Readmoo 的閱讀記錄跟劃線的 package。

可以從閱讀記錄拿到基本的書籍資料跟劃線。

細節見 Github

應該要把拿 token 弄得簡單點,現在很手動…

我的 keymap 是 Sublime + Jetbrains 部份按鍵 + 自己設再配 vim 的大雜燴

  • ctrl + shift + p:執行動作(action)
  • ctrl + p:找檔案
  • ctrl + r:檔案中找 symbol
  • ctrl + alt + shift + t:refactor 選單
  • alt + enter:各種神奇功能(?)
  • alt + insert:加入各種 code
  • shift + f6:rename
  • alt + 1:project browse window
  • alt + 3:find window
  • alt + 4:run window
  • alt + 9:git window

TBC…

Go 從 1.13 開始支援 Go Module,可以在 GOPATH 以外的地方建立 go project 並進行套件管理。一直覺得 source code 只能放在 GOPATH 裡超阿雜…

建立 project

GOPATH 以外的地方建立一個 directory,並且在其中執行 go mod init

1
2
3
$ mkdir project
$ cd project
$ go mod init github.com/cjwind/project

會產生 go.mod 檔案,它會記錄 Go module 與使用的 Go 版本:

1
2
3
module github.com/cjwind/project

go 1.15

接下來在這個 directory 裡進行開發跟 build 就都一樣,重點是現在 source code 不用非得放在 GOPATH 裡啦~

套件管理

go get 安裝 package 後,會發現在 go.mod 多了一行 require [package] [version],就表示目前使用的 package 及其 version。

另外可能會出現 require [package] [version] // indirect,這表示是我們使用的 package 所需要的 package。

也可以用 go get [package]@[version] 來指定特定的 package version。

Ref

COPY

COPY 如果 source 是 directory,會 copy directory 的內容,但是 directory 本身不會 copy。

假設有個資料夾叫 css/,底下有兩個 file foo.cssbar.css

1
COPY ./css /workspace/

這樣在 container 裡會變成 /workspace/ 底下有 foo.cssbar.css,而不是 /workspace/css/ 底下有 foo.cssbar.css。想要是 /workspace/css/ 底下有兩個 file 得這樣寫:

1
COPY ./css /workspace/css

Ref:https://docs.docker.com/engine/reference/builder/#copy

使用 embedded struct 做 json 的 marshal 跟 unmarshal 時,json 欄位會省略 struct embedded 欄位的中間名,以比較簡潔的形式呈現。如果 struct 有寫出欄位名稱,json 欄位就會多那一層。

使用 embedded struct

1
2
3
4
5
6
7
8
9
10
11
type Serving struct {
Amount float64
Unit string
}

type Food struct {
Name string
Serving // embedded struct
NutritionInfo
Comment string
}

marshal 結果:

1
2
3
4
5
6
7
8
9
10
{
"Name":"Banana",
"Amount":100,
"Unit":"g",
"Calorie":0,
"Carb":0,
"Fat":0,
"Protein":0,
"Comment":""
}

不使用 embedded struct

1
2
3
4
5
6
type Food struct {
Name string
Serving Serving // not embedded struct
NutritionInfo
Comment string
}

marshal 結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"Name":"Banana",
"Serving":
{
"Amount":100,
"Unit":"g"
},
"Calorie":0,
"Carb":0,
"Fat":0,
"Protein":0,
"Comment":""
}

不用 embeded struct 就會有一層 Serving,用 embedded struct 就會省略 Serving 這層。

submodule 是在 git repos 中使用別的 repos 的方式之一。

git 的 submodule 是記錄一個指到別人 repo 某個 commit 的指標。對主 repo 來說,記錄的只是一個 submodule commit hash。

切到 submodule 的目錄時做 git 操作會是在操作另一個 repo。

加入 submodule

1
$ git submodule add <repo path>

clone 含有 submodule 的 repos

clone 含有 submodule 的 repos 後,submodule 的目錄會是空的,要做以下動作來初始化:

1
2
$ git submodule init
$ git submodule update

git submodule update 會讓 submodule 的內容回到記錄的 commit。

更新 submodule

submodule 的 repo 更新或者想用不同版本(commit)的 submodule 時,要做以下操作:

1
2
3
4
5
$ cd submodule_dir
$ git pull
$ cd ..
$ git a submodule_dir # 更新主 repo 記錄的 submodule commit hash
$ git ci

概念是把 submodule 的 repo 更新或者 checkout 到想要的 commit,再在主 repo 更新記錄的 submodule commit hash。

移除 submodule

1
2
$ git rm -rf submodule_dir
$ vim .git/config # 移掉 submodule 相關設定

.gitmodules

檔案 .gitmodules 會記錄有哪些 submodule。

任何檔案可以擁有任意數量的 init() function:

1
2
3
func init() {
// ...
}

init() 會在程式啟動時自動以宣告的順序執行,但不能被 call 或參考。

假設有以下兩個 go 檔案:

foo.go
1
2
3
4
5
6
7
package main

import "fmt"

func init() {
fmt.Println("foo.go first init")
}
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func init() {
fmt.Println("main.go first init")
}

func init() {
fmt.Println("main.go second init")
}

func main() {

}

go run 以不同的順序指定 source file 會有不同結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ go run foo.go main.go
foo.go first init
main.go first init
main.go second init

$ go run main.go foo.go
main.go first init
main.go second init
foo.go first init

# 不指定 file
$ go run .
foo.go first init
main.go first init
main.go second init

不指定 file 的話 go 會將 file 以其名稱排序。

如果嘗試直接 call init() 則會 compile error:

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func init() {
fmt.Println("main.go first init")
}

func main() {
init() // compile error: undefined: init
}