- Go通過
來建立web伺服器,底層是初始化一個ListenAndServe
對象,然後調用server
來監聽端口。net.Listen("tcp",addr)
- 調用
函數來處理接收用戶端請求。函數裡面為一個srv.serve(net.Listener)
,首先通過for{}
接受請求,接着建立一個Conn,最後單獨開一個goroutine取執行:accept
。go c.server()
- 使用者的每一次請求都是一個新的goroutine去執行。
- conn通過解析request
擷取相應的c.readRequest()
,它本質是一個路由器,通過它來比對url跳到對應的handle函數。handler := c.server.Handler
- 可通過`http.HandleFunc("/",sayhelloName)來注冊請求的路由規則。
OS擷取環境變量
os.getenv()擷取環境變量擷取不到最新設定的環境變量,最新設定的需要重新啟動電腦擷取
基本類型
這兩天在搞反射,看到Go的基礎資料類型那麼多,int,int32,int64都有,而且運算過程中還需要轉換,是以抽空看了些部落格以及官方文檔。
- int跟uint
- 有符号:int8,int16,int32,int64
- 無符号:unit8,unit16,unit32,uint64
- int和unit取決于作業系統,在32位系統就是32位元組,在64位系統就是64位元組
- int跟int32不是相同的類型,雖然在特定的場景下它們大小相同,但是在運算過程中需要轉換
- byte是unit8的别名,rune是int32的别名
- 浮點類型為float32和float64
- 浮點類型在運算過程中可能存在精度丢失的情況
- string
- 字元串是不可變的,一旦建立,就不能改變字元串的内容
- 可以使用内置函數len來發現s的長度,如果字元串為常量,則length是編譯時常量。
- 字元串的位元組可以通過索引來擷取,但是取元素的位址是非法的,即&s[i]是無效的。
反射
反射在計算機中是程式檢查自己結構的一種能力,尤其是通過類型,它是中繼資料程式設計的一種方式,也是混亂的重要來源
每個語言的反射模型都不同(很多語言根本不支援它)
Type And interface
因為反射是建立在類型系統上,讓我們先回顧一下Go中的類型。
Go是靜态類型語言,每個變量都有一個靜态類型,即在編譯時就已知被固定上一種類型:
int, float32, &MyType, []byte
type MyInt int
var i int
var j MyInt
變量i和j具有不同的靜态類型,雖然他們具有相同的底層類型,但如果沒有轉換,則無法将他們配置設定給彼此。
interface可以存儲任何具體的值,interface包括:
- 變量包括(type,value)兩部分,這也是為什麼nil != nil的原因
- type包括static type和concrete type,static type是編輯時就看到的類型,而concrete type是runtime看到的類型
反射就是建立在類型之上的,Golang的指定類型的變量的類型是靜态的(也就是指定int、string這些變量,它的type是static type),在建立變量的時候就已經确定,反射主要于Golang的interface有關(它的類型是concrete type),隻有interface類型才有反射之說。
API
以下是一些API
reflect:
TypeOf(interface{}) Type : 傳回接口中儲存值的類型,i為nil值傳回nil
ValueOf(interface{}) Value : 傳回一個初始化為i接口保管的具體值的Value,但i為nil時傳回Value零值
New(Type) Value:傳回一個指向類型為Type的新申請的零值的指針。
Type:
Kind():傳回該接口的具體類型
Name():傳回類型名
Elem():傳回該類型的元素類型,如果Kind不是Array,Chan,Map,Slice,Ptr會panic
Value:
Append(s Value,x ...Value) Value: s需為切片類型的Value值,x需為s的元素類型的Value值,将x複制給s并且傳回s
Type():傳回v持有的類型的Type表示
Elem() Value:傳回v持有的接口或者指針保管值的Value封裝,如果v的Kind不是interface或者Ptr将會panic
Kind():同上一緻
CanSet():判斷v持有的值是否能更改,隻有當Value持有值為Ptr并且為共有類型時,它才可以被修改。
Set(x Value):将v的持有值修改為x的持有值
SetInt(x Int64)
SetString(s string)
....
更多API的可參考官方文檔:https://go-zh.org/pkg/reflect/#Value.Convert
反射講得比較好的一篇文章:https://juejin.im/post/5a75a4fb5188257a82110544
Go運作時
盡管Go編譯器産生的是本地可執行代碼,這些代碼仍舊運作在Go的runtime(這部分的代碼可以在runtime包中找到)當中,這個runtime類似虛拟機,它負責管理包括記憶體配置設定、垃圾回收、棧處理、goroutine、channel、slice、map和reflection等等。
Interface
Go中的interface并不是顯示實作的,這就導緻,一個方法接收的類型為IPerson,但是雖然我的Student對象已經實作了IPerson,但是還是不要在通過方法去new實作傳回IPerson對象
type IPerson interface{
}
type Student struct{
name string
age int
}
func newIPerson(name string,age int) IPerson{
return Student{
name : name,
age : age,
}
}
切片
-
,make([]int,l,c)
為長度,l
為容量,不傳c
則容量等于長度c
- 底層還是數組,通過
擷取長度,len()
擷取容量cap()
-
之後傳回的是一個新的切片append
- 擴容:
-
小于1000時,兩倍擴容capacity
-
大于1000時,增長因子為capacity
,1.25
擴容25%
-
- nil切片的數組指針為nil,而空切片的數組指針指向一個沒有配置設定任何記憶體空間的位址,即底層元素包含0個元素。不管nil切片還是空切片,對其調用append,len和cap的效果都是一樣的。
- 指派:将一個切片指派給另一個切片可指定索引
- 第一個索引:指定切片的頭部
- 第二個索引:指定切片長度的尾部
- 第三個索引:限制切片的容量
參考下面代碼:
a := []int{1, 2, 3, 4, 5}
b := a[1:]
c := a[:4]
d := a[1:4]
e := a[2:3:4]
fmt.Println("a", len(a), cap(a))
fmt.Println("b", len(b), cap(b))
fmt.Println("c", len(c), cap(c))
fmt.Println("d", len(d), cap(d))
fmt.Println("e", len(e), cap(e))
//列印結果
a 5 5
b 4 4
c 4 5
d 3 4
e 1 2
-
傳回的是每個元素的副本,而不是引用for-range
- 切片在函數件傳遞還是以值傳遞的方式傳遞,由于切片的尺寸很小,在函數間複制和傳遞切片的成本也很低。在64位結構的機器上,一個切片需要24個位元組,指針字段8位元組,長度和容量分别需要8位元組,由于與切片關聯的資料包含在底層數組裡面,不屬于切片本身,是以将切片複制給人以數組時對底層數組大小都不會有影響。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iYzQ2Y4YTY3Y2YiRDNiRDNxIGOiBTN0YmZ0IDZwUmMw8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
映射
- 鍵可以是任何值值,這個值的類型可以是内置的類型,也可以是結構類型,隻要這個值可以使用
運算符做比較,切片、函數以及包含切片的結構類型由于具有引用意義,是以不能作為映射的鍵。==
- 映射的值可以為任何值
- 指派是通過指定适當的鍵并給這個鍵賦一個值來完成:
colors["red"] = "#da1337"
- 未初始化的映射稱為nil映射,不能夠進行指派
- 判斷是否存在某個鍵
- 同時獲得值以及一個鍵是否存在的标記
- 隻傳回鍵的值,通過判斷鍵的值是否為零值判斷是否存在
示例:
1、
value,exists := colors["blue"]
if exists{
//
}
2、
value := colors["blue"]
if velue != ""{
//
}
- 通過鍵來索引映射時,即便這個鍵不存在的時候也總會傳回一個值
- 可通過
來疊代映射,for-range
for key,value := range colors{}
- 可通過内置的
函數将一個鍵值對從映射中删除,delete
delete(colors,"orange")
- 在函數中傳遞映射時,當這個映射被修改,所有對這個映射的引用都會察覺到這個修改,這個特性于切片類似,保證可以用很小的成本來複制映射。