目錄
前言:
Go語言的設計初衷
- 針對其他語言的痛點進行設計
- 並加入併發編程
- 爲大數據、微服務、併發而生的通用編程語言
Go語言很特別
- 沒有“對象”,沒有繼承多態、類等,沒有泛型,沒有try/catch
- 有接口,函數式編程,CSP併發模型(goroutine+channel)
- 自帶gc
- 靜態編譯,編譯好後,扔服務器直接運行
- 學習Go語言很簡單,因爲語法簡單
- 用好Go語言不容易,因爲要調整三觀
Go語言的主要特徵
- 1.自動立即回收
- 2.更豐富的內置類型
- 3.函數多返回值
- 4.錯誤處理
- 5.匿名函數和閉包
- 6.類型和接口
- 7.併發編程
- 8.反射
- 9.語言交互性
GO概覽
- 基本語法:變量,選擇、循環,指針,數組,容器
- 面向接口:接口體,duck typing的概念,組合的思想
- 函數式編程:閉包的概念
- 工程化:資源管理、錯誤管理、測試和文檔、性能調優
- 併發編程:理解調度器
Go基礎
Go語言聲明
- var(聲明變量)
- const(聲明常量)
- type(聲明類型)
- func(聲明函數)
1)聲明在函數內部,是函數的本地值,類似private
2)聲明在函數外部,是對當前包可見(包內所有.go文件都可見)的全局值,類似protect
3)聲明在函數外部且首字母大寫是所有包可見的全局值,類似public
下劃線(很特殊)
“_”是特殊標識符,用來忽略結果。
- 下劃線在import中:用【import _ 包路徑】只是引用該包,僅僅是爲了調用init()函數,所以無法通過包名來調用包中的其他函數
下劃線在代碼中:忽略這個變量,意思是那個位置本應賦給某個值,但是咱們不需要這個值。所以就把該值賦給下劃線,意思是丟掉不要。
變量聲明
- Go語言中的變量需要聲明後才能使用,同一作用域內(可以放在函數內,也可以放在包內)不支持重複聲明。並且Go語言的變量聲明後必須使用。
- 使用var()集中定義常量
- 在函數內部,可以使用更簡略的 := 方式聲明並初始化變量。:=不能使用在函數外
- 沒有char,只有rune: rune類型用來表示utf8字符,一個rune字符由一個或多個byte組成。
- 原生支持複數:complex64 complex128 (實部、虛部)
常量聲明
- 常量的聲明和變量聲明非常類似,只是把
var
換成了const
,常量在定義的時候必須賦值- Go語言的常量不用大寫,在go中大小寫是有區別的
iota(自增值)
是go
語言的常量計數器,只能在常量的表達式中使用。
數組
Golang Array和以往認知的數組有很大不同。
1. 數組:是同一種數據類型的固定長度的序列。
2. 數組定義:var a [len]int,比如:var a [5]int,數組長度必須是常量,且是類型的組成部分。一旦定義,長度不能變。數量寫在類型前
3. 長度是數組類型的一部分,因此,var a[5] int和var a[10]int是不同的類型。
4. 數組可以通過下標進行訪問,下標是從0開始,最後一個元素下標是:len-1
for i := 0; i < len(a); i++ { } for index, v := range a { }
5. 訪問越界,如果下標在數組合法範圍之外,則觸發訪問越界,會panic
6. 調用func f(arr[10] int)會拷貝數組。數組是值類型,賦值和傳參會複製整個數組,而不是指針。因此改變副本的值,不會改變本身的值。
7.支持 "=="、"!=" 操作符,因爲內存總是被初始化過的。
8.指針數組 [n]*T,數組指針 *[n]T。
切片Slice
slice 並不是數組或數組指針。它通過內部指針和相關屬性引用數組片段,以實現變長方案。
Slice本身沒有數據,是對底層array的一個view
- 1. 切片:切片是數組的一個引用,因此切片是引用類型。但自身是結構體,值拷貝傳遞。
- 2. 切片的長度可以改變,因此,切片是一個可變的數組。
- 3. 切片遍歷方式和數組一樣,可以用len()求長度。表示可用元素數量,讀寫操作不能超過該限制。
- 4. cap可以求出slice最大擴張容量,不能超出數組限制。0 <= len(slice) <= len(array),其中array是slice引用的數組。
- 5. 切片的定義:var 變量名 []類型,比如 var str []string var arr []int。
- 6. 如果 slice == nil,那麼 len、cap 結果都等於 0。
append超出原 slice.cap 限制,就會重新分配底層數組,即便原數組並未填滿
package main
import (
"fmt"
)
func main() {
data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]
fmt.Println(s)
s = append(s, 100, 200) // 一次 append 兩個值,超出 s.cap 限制。
fmt.Println(s, data) // 重新分配底層數組,與原數組無關。
fmt.Println(&s[0], &data[0]) // 比對底層數組起始指針。
}
輸出結果:
[0 1]
[0 1 100 200] [0 1 2 3 4 0 0 0 0 0 0]
0xc000086060 0xc000056060