Vim - 跳到某行的開始/最後

  • ^ 跳到句子開始,保持 command mode
  • I 跳到句子開始,切換到 insert mode
  • $ 跳到句子最後,保持 command mode
  • A 跳到句子最後,切換到 insert mode
  • 跳到某個想搜尋的字 :
      / [type the word you want to find]
    

    enter 後按 n可 以跳到下一個字 (用 :noh 可以取消 highlight)

Read, Write, Execute

Owner, Group, Other 對檔案/資料夾的 write, read, execute 三個動作分別具有不同的權限。

權限通常有兩種表示方法,第一種方式是用三個 octal number 作為權限的表示,第一個數字是 read 權限,第二個數字是 write 權限,第三個數字是 execute 權限;第二種方法是直接用 rwx 來表示。以下舉例:

  • 0 or —: No permissions
  • 1 or –x: Execute permission (execute a file or navigate to a directory)
  • 2 or -w-: Write permission (write a file or add new files in a directory)
  • 3 or -wx: Write and execute
  • 4 or r–: Read permission (read a file or list the contents of a directory)
  • 5 or r-x: Read and execute
  • 6 or rw-: Read and write
  • 7 or rwx: Read, write, and execute

Owner, Group, Other 對一個檔案的權限,就用三個 octal number 或三組 rwx 表示:

  • 777: Everyone can read, write, and execute.
  • 700: Owner can read, write, and execute.
  • 664: Owner and group can read and write.
  • 640: Owner can read and write and group can read.
  • 755: Owner can read, write, and execute, while group and others can read and execute.

可以用 ls -lll 來瀏覽目前目錄底下檔案/資料夾的權限設置。

會發現下面除了三組 rwx,有些檔案前面還有一個 d,這種 1333 的形式分別代表:檔案屬性/ owner 擁有者權限 / group 同群組使用者權限 / other 其他人權限。而 d 代表該檔案是個目錄。

有些檔案除了 1333,後面還有一個 @,這代表該檔案是 extended attributes。

Variadic Functions

Variadic Functions,可變參數函數,讓函數參數數量可是未定義,可能是一個或多個,也可能是零個。 fmt.Println 就是 Go 常見的 Variadic Functions。

以加總函數 sum 為例,可以有下面兩種寫法:

package main

import "fmt"

// Variadic Functions
func sum(nums ...int) {
	fmt.Println("nums: ", nums)
	total := 0

	for _, n := range nums {
		total += n
	}
	fmt.Println("sum: ", total)
}

// 傳入陣列
func sum2(nums []int) {
	fmt.Println("nums: ", nums)
	total := 0

	for _, n := range nums {
		total += n
	}
	fmt.Println("sum: ", total)
}

func main() {
	arr := []int{1, 3, 5, 7, 9}
	sum(arr...)
	sum2(arr)
}

玩一玩 Protocol Buffer

建立資料夾、進入資料夾、初始化

mkdir hello

cd hello

go mod init example

建立放 proto 檔案的資料夾、建立 .proto

mkdir person

cd person 

touch person.proto

person.proto 貼上以下程式碼

syntax = "proto3"; // 3 代表版本

option go_package = "example/person";
package person;

message Person {
    string name = 1; // 有型別,和JSON不同,所以編譯器才能自動產生很多不同語言的版本
}

執行:

protoc *.proto --go_out=plugins=grpc:. --go_opt=paths=source_relative

回到根目錄並建立 main.go

cd ..

touch main.go

main.go 貼上以下程式碼

package main

import (
	"fmt"
	"io/ioutil"
	"log"

	pb "example/person"

	proto "github.com/golang/protobuf/proto"
)

func main() {
  person := &pb.Person{Name: "XXX"}
	fmt.Printf("Person's name is %s\n", person.GetName())

	//把 person object 寫到檔案 person.bin(人類不可讀)
	out, err := proto.Marshal(person)
	if err != nil {
		log.Fatalf("Serialization error: %s", err.Error())
	}
	if err := ioutil.WriteFile("person.bin", out, 0644); err != nil {
		log.Fatalf("Write File Error: %s ", err.Error())
	}
	fmt.Println("Write Success")

	//讀檔然後印出來
	in, err := ioutil.ReadFile("person.bin")
	if err != nil {
		log.Fatalf("Read File Error: %s ", err.Error())
	}
	person2 := &pb.Person{}
	err2 := proto.Unmarshal(in, person2)
	if err2 != nil {
		log.Fatalf("DeSerialization error: %s", err.Error())
	}

	fmt.Println("Read Success")
	fmt.Printf("Person2's name is %s\n", person2.GetName())
}

下載需要的 package


go get -u github.com/golang/protobuf/proto

執行程式

go run main.go

參考資料

Protocol Buffers and Go: Getting started

gRPC v.s. WebSocket

gRPC

特色

  • 使用 Google 的 Protocol Buffers(Protobuf) 作為 interface description language.
  • protoc compiler 支援多語言,例如:python、go,所以客戶端和伺服器可以使用不同語言撰寫
  • 基於 HTTP/2
  • 讓調用遠程的程式也像調用本地函式庫一樣,此外,許多網路相關的程式碼被不需要工程師自己寫,protoc compiler 會幫忙產生

缺點

  • Protobuf 非人類可讀語言,debug 不方便
  • 雖然很多語言都有 gRPC 的套件,瀏覽器仍然沒辦法直接支持,需要使用例如 gRPC Web 這種 proxy

WebSocket

特色

  • WebSocket 是 W3C 網路協定標準,與一般 http、https不同之處在於,他只需要一次接觸便能一直保持連線,直到其中一方斷掉
  • 可以傳輸文本、binary data
  • HTTP/1.1 握手期間可以指定在 WebSocket 之上使用的子協議(例如,MQTT),也可以自訂協議或自訂額外功能(例如發布/訂閱消息傳遞)
  • 因為是持續的連接而不是每次都 request/response,所以只需要極小的傳輸開銷
  • 瀏覽器原生支持 WebSocket API
  • 事件驅動(event-driven)

缺點

  • stateful
  • 連線終止後不會自動恢復
  • 某些環境(例如帶有代理服務器的公司網絡)會阻止 WebSocket 連接。

比較

  • data format
    • GRPC : .proto file
    • WebSocket : no “official” format specification
  • request processing performance
    • gRPC : 使用 HTTP2 連線延遲比較大,但因為 HTTP2 支持 multiplexing 與 高效的 binary format,gRPC 有較大的吞吐量(throughput)
    • WebSocket : 使用持續的 TCP 連線,通信完成才關閉,也可以做 multiplexing ,但必須要使用第三方函式庫或自己寫代碼,比較麻煩
  • scalability
    • gRPC : 使用的 HTTP 是 stateless,維持通信所需的任何信息都會在每次請求/響應交換時重新傳輸。雖然這造成標頭中數據的低效重複,但它也確保了服務器在過程中是可互換的,因為它們都不需要記住與它們通信的客戶端的任何信息。擴展比較簡單
    • WebSocket : stateful protocol,依賴於雙方(尤其是服務器)存儲有關連接狀態和先前消息歷史記錄的信息。 您需要更複雜的代碼來跟踪狀態。此外,客戶端只能與有權訪問當前狀態的服務器進程通信。 這會使擴展大量 WebSocket 之間的連接變得困難 但總而言之,WebSocket 佔用資源較少,差不多規模的系統,使用 gRPC 會需要比較大的計算能力和頻寬

使用時機

gRPC

  • Connecting polyglot services in a microservices-style architecture.
  • Connecting client devices (e.g., mobile devices) to backend services. (理想情況不涉及高頻數據更新)
  • Connecting point-to-point realtime services that need to handle streaming requests or responses.

WebSocket

  • Realtime updates, where the communication is unidirectional, and the server is streaming low-latency (and often frequent) updates to the client. (例如:實時比分更新、新聞源、警報和通知 等)
  • Bidirectional communication, where both the client and the server send and receive messages. (例如:聊天室、虛擬活動、虛擬教室)
  • 多用戶協作(例如:同時編輯一文檔)
  • Fanning out (broadcasting) the same message to multiple users at once.(pub/sub messaging)

參考資料