Go總結(2)

struct

go中struct結構默認字段都會有零值,故不能用nil來判斷struct是否爲空,可經過額外的字段來判斷struct是否填充或爲空web

type Demo struct{
    ready bool

    name string
    //其餘字段
}

在初始化的時候必須將ready設置爲true編程

var d Demo
if !d.ready{
    //do stuff
}

Web工做方式

  • Go經過ListenAndServer來創建web服務器,底層是初始化一個server對象,而後調用net.Listen("tcp",addr)來監聽端口。
  • 調用srv.server(net.Listener)函數來處理接收客戶端請求。函數裏面爲一個for{},首先經過accept接受請求,接着建立一個Conn,最後單獨開一個goroutine取執行:go c.server()
  • 用戶的每一次請求都是一個新的goroutine去執行。
  • conn經過解析requestc.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和float64app

    • 浮點類型在運算過程當中可能存在精度丟失的狀況
  • stringtcp

    • 字符串是不可變的,一旦建立,就不能改變字符串的內容
    • 可使用內置函數len來發現s的長度,若是字符串爲常量,則length是編譯時常量。
    • 字符串的字節能夠經過索引來獲取,可是取元素的地址是非法的,即&s[i]是無效的。

反射

反射在計算機中是程序檢查本身結構的一種能力,尤爲是經過類型,它是元數據編程的一種方式,也是混亂的重要來源

每一個語言的反射模型都不一樣(不少語言根本不支持它)函數

Type And interface

由於反射是創建在類型系統上,讓咱們先回顧一下Go中的類型。post

Go是靜態類型語言,每一個變量都有一個靜態類型,即在編譯時就已知被固定上一種類型:int, float32, &MyType, []byteui

type MyInt int

var i int
var j MyInt

變量i和j具備不一樣的靜態類型,雖然他們具備相同的底層類型,但若是沒有轉換,則沒法將他們分配給彼此。url

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

更多的可參考官方文檔:https://go-zh.org/pkg/reflect/#Value.Convert

反射講得比較好的一篇文章:http://www.javashuo.com/article/p-epkjfqjn-kw.html

Go運行時

儘管Go編譯器產生的是本地可執行代碼,這些代碼仍舊運行在Go的runtime(這部分的代碼能夠在runtime包中找到)當中,這個runtime相似虛擬機,它負責管理包括內存分配、垃圾回收、棧處理、goroutine、channel、slice、map和reflection等等。

Interface

Go中的interface並非顯示實現的,這就致使,一個方法接收的類型爲IPerson,可是雖然個人Student對象已經實現了IPerson,可是仍是不要在經過方法去new實現返回IPerson對象

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.2525%擴容
  • 賦值:將一個切片賦值給另外一個切片可指定索引

    • 第一個索引:指定切片的頭部
    • 第二個索引:指定切片長度的尾部
    • 第三個索引:限制切片的容量

參考下面代碼:

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字節,因爲與切片關聯的數據包含在底層數組裏面,不屬於切片自己,因此將切片複製給人以數組時對底層數組大小都不會有影響。

clipboard.png

相關文章
相關標籤/搜索