寫在前面的話
18年的時候就想着要學golang, 結果一拖就是1年多, 這19年都已經快過了一半了,想想自己的惰性實在太強,還是得逼自己一把才行,不然20年了估計還是沒戲,所以找了一個切入點,最近在網上找到了一個教學視頻,叫 Google資深工程師深度講解Go語言 ,稍微看了一下, 覺得講的挺好, 是以一個在已經有了別的語言基礎上, 作爲項目轉型首選語言的角度來介紹golang的, 講到每個語法基本會和其他的語言進行比較, 這樣也比較容易記憶.
那麼這個系列的學習筆記就根據這個視頻的章節來走, 記錄一下每個章節裏介紹到的golang比較特殊的地方, 便於之後翻看複習和記憶.
希望自己堅持吧 加油加油!
PS:大多數總結的內容和代碼都來源於教學視頻的PPT和示例代碼,少部分來我自己的理解,之後的學習筆記的博客都是一樣
第一章 基礎語法
定義變量
- 變量類型寫在變量名之後
- 使用 var 關鍵字
var a int // 定義int型的變量a 默認值爲0
var a int = 10 // 定義int型變量a 賦初始值爲10
var s1, s2 string = "hello", "world" // 定義字符串類型s1,s2並賦初始值
- var 關鍵字可以放在函數內, 也可以在包內, 一般作用域爲包內的變量用var來定義
- 可以使用 var() 來集中定義變量
var (
aa = 3
ss = "kkk"
bb = true
)
- 讓編譯器自動決定類型
var a, b, i, s1, s2 = true, false, 3, "hello", "world"
- 使用 := 定義變量, 只能在函數內使用
a, b, i, s1, s2 := true, false, 3, "hello", "world"
- 簡短變量聲明左邊的變量可能並不是全部都是剛剛聲明的。如果有一些已經在相同的詞法域聲明過了,那麼簡短變量聲明語句對這些已經聲明過的變量就只有賦值行爲了。
in, err := os.Open(infile)
// ...
out, err := os.Create(outfile)
- 簡短變量聲明語句中必須至少要聲明一個新的變量,下面的代碼將不能編譯通過
f, err := os.Open(infile)
// ...
f, err := os.Create(outfile) // compile error: no new variables
內建變量類型
- bool, string
- (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr
- byte, rune(字符型 類似char, 但是長度爲4字節)
- float32, float64, complex64, complex128
強制類型轉換
- 只能強制轉換, 不能隱式轉換
var a, b int = 3, 4
var c int = math.Sqrt(a*a + b*b) // 錯誤
var c int = int(math.Sqrt(float64(a*a + b*b))) // 正確
常量的定義
const filename = "abc.txt"
const 數值可以作爲各種類型使用
const a, b = 3, 4
var c int = math.Sqrt(a*a + b*b) // 這裏編譯就不會像上面強制類型轉換的例子報錯
使用常量定義枚舉類型
- 普通枚舉類型
const (
cpp = 0
java = 1
pythod = 2
golang = 3
)
- 自增值枚舉類型
const (
cpp = iota
java
pythod
golang
)
// 這裏的枚舉的數值和上面一樣
條件語句 if
- if的條件裏不需要括號
- if的條件裏可以賦值
- if的條件裏賦值的變量的作用域就在這個if語句裏
const filename = "abc.txt"
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s\n", contents)
}
條件語句 switch
- switch會自動break,不用打break,除非使用 fallthough
- switch後可以沒有表達式,直接在case裏面加入條件,類似 if / elseif / elseif/ else
g := ""
switch {
case score < 60:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
}
循環語句 for(沒有while, 直接用for代替)
- for的條件裏不需要括號
- for的條件裏可以省略初始條件,結束條件,遞增表達式
// 省略初始條件
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
// 省略初始條件,結束條件
func printFileContents(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
// 省略初始條件,結束條件,遞增表達式
// 相當於while(true)
func forever() {
for {
fmt.Println("abc")
}
}
函數
- 返回值類型寫在最後面
- 可返回多個值
func test(a int, b string) ( success bool, errorInfo error, result int ) {
return true, fmt.Errorf(b), a
}
- 函數可以作爲參數
func apply(op func(int, int) int, a, b int) int {
...
}
- 沒有默認參數, 可選參數
- 只有可變參數列表
func sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
指針
- 指針不能運算(指針地址偏移運算)
參數傳遞
- 只有值傳遞一種方式
- 需要引用傳遞可以把參數類型定爲指針類型
一些小技巧
- Printf 格式化
- 附上一篇詳解 Printf格式化輸出、Scanf格式化輸入詳解
%d 十進制整數
%x, %o, %b 十六進制,八進制,二進制整數。
%f, %g, %e 浮點數: 3.141593 3.141592653589793 3.141593e+00
%t 布爾:true或false
%c 字符(rune) (Unicode碼點)
%s 字符串
%q 帶雙引號的字符串"abc"或帶單引號的字符'c'
%v 變量的自然形式(natural format)
%T 變量的類型
%% 字面上的百分號標誌(無操作數)
- 獲取函數名
func apply(op func(int, int) int, a, b int) int {
p := reflect.ValueOf(op).Pointer()
opName := runtime.FuncForPC(p).Name()
fmt.Printf("Calling function %s with args "+
"(%d, %d)\n", opName, a, b)
return op(a, b)
}
- 利用返回值做值交換
func swap(a, b int) (int, int) {
return b, a
}
- 可以通過 ‘_’ 來省略變量(因爲Golang申明瞭的變量必須要有引用,不然就會編譯報錯)
// 調用上面的swap方法
a, _ = swap( 1, 2 )