天天看點

golang 數組 最後一個_Golang總結(2)

Web工作方式
  • Go通過

    ListenAndServe

    來建立web伺服器,底層是初始化一個

    server

    對象,然後調用

    net.Listen("tcp",addr)

    來監聽端口。
  • 調用

    srv.serve(net.Listener)

    函數來處理接收用戶端請求。函數裡面為一個

    for{}

    ,首先通過

    accept

    接受請求,接着建立一個Conn,最後單獨開一個goroutine取執行:

    go c.server()

  • 使用者的每一次請求都是一個新的goroutine去執行。
  • conn通過解析request

    c.readRequest()

    擷取相應的

    handler := c.server.Handler

    ,它本質是一個路由器,通過它來比對url跳到對應的handle函數。
  • 可通過`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

    之後傳回的是一個新的切片
  • 擴容:
    • capacity

      小于1000時,兩倍擴容
    • capacity

      大于1000時,增長因子為

      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位元組,由于與切片關聯的資料包含在底層數組裡面,不屬于切片本身,是以将切片複制給人以數組時對底層數組大小都不會有影響。
golang 數組 最後一個_Golang總結(2)

映射

  • 鍵可以是任何值值,這個值的類型可以是内置的類型,也可以是結構類型,隻要這個值可以使用

    ==

    運算符做比較,切片、函數以及包含切片的結構類型由于具有引用意義,是以不能作為映射的鍵。
  • 映射的值可以為任何值
  • 指派是通過指定适當的鍵并給這個鍵賦一個值來完成:

    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")

  • 在函數中傳遞映射時,當這個映射被修改,所有對這個映射的引用都會察覺到這個修改,這個特性于切片類似,保證可以用很小的成本來複制映射。