都說 Go 的語法簡單,學習之後發現,其中的坑真不少,論語法簡單,只服 Python ...
自動添加分號
在很多其他的編程語言中,每一行代碼的結尾都必須有分號(假設一行中只有一句代碼),Golang 的開發者認為,既然每行都要加,不如編譯器自動來加。當然,你加了分號也不會報錯。
Golang 中,在以下兩種情況下會自動加入分號:
-
當輸入被斷開為標記時,如果行末標記為
-
一個標識符
-
一個整數、浮點數、虛數、字元或字元串文字
-
關鍵字
break、continue、fallthrough、return
中的一個 -
運算符和分隔符
++、--、)、]、}
中的一個
-
-
如果讓複合語句占用單獨一行,則在
)
或}
後面的分號可以被省略。
Golang 的這個特性,產生了很多寫法上的強制性規定。
(1)函數的左括弧 { 必須和函數定義寫在同一行
這種寫法在其他語言中是絕對沒有問題的,但是在 Golang 中會報找不到方法體,因為根據上面的規則,編譯器會在 func main()
後面自動加上分號。
(2)一條語句只能寫在一行中
如果你一定要把兩條語句寫在一行中,那麼也是可以的,但是必須要在第一條語句後面手動加上分號。但是強烈不建議這麼做。
(3)用 + 拼接字元串時,如果要換行,+ 必須留在行末
var str string = "hello world " +
"hello world"
這是可以的,但如果寫成以下形式就不可以了,會報 invalid operation: + untyped string,因為編譯器會在第一行末尾添加分號。
其他例子還有很多,這裡就不一一例舉了,當你用了一個在其他語言中非常合理的寫法而 Golang 編譯報錯時,首先想想看,如果每一句後面都加個分號,代碼還是你預期中的樣子嗎。
回車和換行
\r
是回車符(return),作用是使游標移動到本行的開始位置;\n
是換行符(newline),作用是使游標垂直向下移動一格;
所以我們一般用 \r\n
來新起一行。
至於為什麼回車和換行要分開,這是一個歷史遺留問題。而現今在很多語言中,\r
、\n
、\r\n
都能起到新起一行的作用。但是在 Golang 中,\r
依然只保留了其原始的回車作用。\n
、\r\n
都能起到換行的作用。
示例 1:
fmt.Println("hello\nworld!")
運行結果:
hello
world!
示例 2:
fmt.Println("hello\rworld!")
運行結果:
world!
這雖然有點坑,但其實還好,一般人換行符都會用
\r\n
或\n
,很少有人會用\r
吧。
定義的變數或導入的包如果沒有使用到,代碼編譯不能通過
這是強迫症患者的福音,例如我
變數的定義
(1)一般定義
一般語言中,定義變數時是類型在前,變數名在後:
int i = 10
在 Golang 中,是反過來的:
var i int = 10
包括函數傳參時亦是如此:
func test(str string){
fmt.Println(str)
}
(2)類型推導
定義時若不聲明類型直接賦值,會根據值自行判定變數類型
var i = 10 // i 就是 int 類型
(3)省略 var
name := "Tom"
註意:是 :=
,冒號不可省略,省略後就變成賦值了。並且變數名不能是已經聲明過的,因為這是聲明並賦值。
上面的語句等價於:
var name string
name = "Tom"
(4)一次性聲明多個變數
// 方法一
var n1, n2, n3 int
//方法二
var name, age = "Tom", 20
//方法三:類型推導
name, age := "Tom", 20
(5)聲明全局變數
//方法一
var name string = "Tom"
var age int = 20
//方法二
var (
name = "Tom"
age = 20
)
基本數據類型
(1) 整數
整數的類型有很多,int、int8、int16、int32、int64,還有 uint 系列。這裡要說明一下的是 int 這個類型,它在 32 位系統中占 4 個位元組,64 位系統中占 8 個位元組。定義變數時,整數的預設推導類型就是 int 型。
這裡有個吐槽點,我在下麵的隱式轉換中再來吐槽。
(2) 浮點數
沒有 float
和 double
,而是用 float32
和 float64
表示。
浮點類型預設聲明為 64 位。
var f = 3.14
fmt.Printf("%T", f)
// 輸出 float64
也可以用科學計數法來表示( E 和 e 都可以)
var f = 3.14E2
(3) 字元類型(char)
Golang 中沒有專門的字元類型,如果要存儲單個的字元,一般用 byte
來保存。
字元串是一串固定長度的字元連接起來的字元序列。在其他語言中,字元串是由字元組成的,而 Golang 的字元串不同,它是由位元組組成的。(此處有坑,稍後詳解)
var c byte = 'a'
fmt.Println("C =", c)
// 輸出 97
當直接輸出字元的值時,實際輸出的是字元對應的碼值。如果需要輸出字元,則需要用格式化輸出。
fmt.Printf("c = %c", c)
Golang 中,中文也可以是一個字元,這在其他一些語言中是不可以的。但是中文的碼值顯然超出了 byte
的範圍,可以用 int
或 rune
來定義。Golang 中統一使用 UTF-8 編碼。
var c rune = '中'
fmt.Printf("%v %c", c, c)
(4) 字元串
多行字元串,用 ` (ESC下麵那個鍵)引起來
var str string = `hello
world`
字元串的預設值是 ""
隱式轉換
Golang 沒有隱式轉換,所有不同類型變數之間必須顯示轉換。類型轉換的基本語法類似 python。
var i int = 100
var f float32 = float32(i)
將一個大的數據類型轉換為一個小的數據類型時(例如 int64 轉 int32),可能導致溢出,溢出不會報錯。
var num1 int64 = 999999
var num2 int8 = int8(num1) // 轉換結果是63
吐槽開始,也許你覺得,隱式轉換沒有就沒有吧,最多用的時候強轉一下。看下麵的代碼,你還會覺得如此嗎?
不同類型無法比較。想說 fuck 嗎?
之前說道 int 類型的時候,有個要吐槽的,來看下麵的代碼!
不管你是啥系統,int 和 int32、int64 都是不同的類型,想直接比較?沒門!