GO入門學習

go環境安裝

go不像java這種成熟的語言有eclipse這種編譯器,但是go提供了很多插件
首先先選擇一個編譯器,我這邊使用的vscode,接着在vscode中配置go的開發環境
配置開發環境之後,接着需要安裝一些go的插件方便開發,首先先了解每種插件的作用,像gocode的作用就是代碼補全,具體可參考https://blog.csdn.net/langzi7...
安裝插件有幾種方式,可以通過vscode自動安裝,也可以通過命令行安裝,但因爲有些插件需要vpn,故可先從github上clone插件包,然後再進行安裝,過程中可能會相關的問題.....
可跟着一下博文安裝https://blog.csdn.net/Yo_oYgo...

go build go install go getValue

  • go build:在當前目錄下生成可執行文件,注意:go build指令會調用所有引用包的源碼,重新編譯,而不是直接使用pkg裏的編譯後的文件,如果在$GOROOT或者$GOPATH下沒有找到import引入的項目源碼,就會報錯。
  • go install:編譯源代碼,如果爲可執行文件(package "main"且包含main方法),則會編譯生成可執行文件到$GOPATH\bin目錄下,可執行文件import引入其他包,就會被編譯到$GOPATH/pkg/$GOOS_$GOARCH目錄下。
  • go get:git clone到$GOPATH\src + go install

method和function的關係

method是特殊的function,定義在某一特定的類型上,通過類型的實例來進行調用,這個實例被叫receiver
method belongs to instance
fuction is a global function belongs to package

使用method的時候注意幾點:

  • 雖然method的名字一模一樣,但是如果接受者不一樣,那麼method就不一樣
  • method裏面可以訪問接收者的字段
  • 調用method通過.訪問,就像struct裏面訪問字段一樣

指針

類似於java的引用,但是也保證的內存安全,類似C語言內存泄漏而程序崩潰的指針運算(所謂的指針算法,如:pointer+2,移動指針指向字符串的字節數或數組的某個位置)是不允許的。
指針的傳遞很廉價,只佔用4或8個字節。
但傳遞一個變量的引用(函數的參數),這樣不會傳遞變量的拷貝。

 s := "good bye"
 var p *string = &s
 *p = "hello"
 fmt.Printf("Here is the pointer p:%p\n", p)
 fmt.Printf("Here is the string *p:%s\n", *p)
 fmt.Printf("Here is the string s:%s\n", s)

map的value值可以爲任何類型
interface的實現通過結構體實現相同的方式

package main

import (
    "fmt"
)

type stockPosition struct {
    ticker     string
    sharePrice float32
    count      float32
}

func (s stockPosition) getValue() float32 {
    return s.sharePrice * s.count
}

type car struct {
    make  string
    model string
    price float32
}

func (c car) getValue() float32 {
    return c.price
}

func getValue() float32 {
    return 0
}

type valueable interface {
    getValue() float32
}

func showValue(asset valueable) {
    fmt.Printf("Value of the asset is %f\n", asset.getValue())
}

func main() {

    s := getValue()
    fmt.Println(s)

    //接口實現
    // var o valueable = stockPosition{"GOOG", 577.20, 4}
    // showValue(o)
    // o = car{"BMW", "M3", 66500}
    // showValue(o)

    //map的value可以爲任何類型
    // mf := map[int]func() int{
    //     1: func() int { return 10 },
    //     2: func() int { return 20 },
    //     3: func() int { return 50 },
    // }
    // fmt.Println(mf)

    //map的value爲interface時
    //當value爲interface,即map中的value值爲interface的實現
    //跟java的面向對象有點繞,go的struct在java完全可以用class來實現
    //具有接口相同的方法就可以算是實現了接口
    var c car = car{"BMW", "M3", 66500}
    var v valueable = stockPosition{"GOOG", 577.20, 4}
    mf := map[string]interface{ getValue() float32 }{
        "account":  c,
        "password": v,
    }

    for _, value := range mf {
        fmt.Println(value)
        fmt.Println(value.getValue())
    }

}

interface萬能模型

測試

測試文件的後綴爲_test.go,並且應該跟被測試文件放在同一個目錄下
測試數據放在一個特殊的testdata目錄中,使用go build時,testdata目錄和_test.go文件都會被編譯器忽略

new跟make

func new(Type) *Type
分配空間,參數一個類型,返回值指向這個新分配的零值的指針
func make(Type,size IntegerType)
分配並且初始化一個slice,或者map或者chan對象,並且只能是這三種對象。
第一個參數爲類型,第二個參數爲長度
返回值是這個類型.

int類型跟string類型的切換

go主要通過strings包來完成對字符串的主要操作
strings.HasPrefix(s,prefix string) bool等

多返回值函數的錯誤

Go中函數經常使用兩個返回值表示執行是否成功,返回某個值以及true表示成功,返回零值(或nil)和false表示失敗。
當不使用true或false的時候,也可以使用一個error類型的變量來替代第二個返回值。
習慣用法:
value,err := pack1.Function(param1)
if err != nil{

fmt.Printf("An error occured in pack1.Function1 with parameter %v",param1)
return err

}
//未發生錯誤,繼續執行

//測試用例需要包括

  • 正常的用例
  • 反面的用例
  • 邊界檢查用例

單元測試gomock

go中的實現泛型

go中並沒有泛型的概念,但可通過interface來實現
例如下面的冒泡排序

package main

import "fmt"

type Sortable interface {
    Len() int
    Less(int, int) bool
    Swap(int, int)
}

func bubbleSort(array Sortable) {
    for i := 0; i < array.Len(); i++ {
        for j := 0; j < array.Len()-1-i; j++ {
            if array.Less(j+1, j) {
                array.Swap(j, j+1)
            }
        }
    }
}

//實現接口的整形切片
type IntArr []int

func (array IntArr) Len() int {
    return len(array)
}

func (array IntArr) Less(i int, j int) bool {
    return array[i] < array[j]
}

func (array IntArr) Swap(i int, j int) {
    array[i], array[j] = array[j], array[i]
}
func main() {
    intArr1 := IntArr{3, 5, 1, 2, 3, 7, 88}
    bubbleSort(intArr1)
    fmt.Println(intArr1)
}

參考:https://studygolang.com/artic...

閉包

當不希望給函數起名字的時候,可以使用匿名函數,例如:func(x, y int) int {return x + y }
這樣一個函數不能夠獨立存在,但可以被賦值爲某個變量,例如 fplus := func(x, y int) int {return x + y },然後通過變量名對函數進行調用 fplus(3,4)

當然可以直接對匿名函數進行直接調用:func(x, y int) int {return x + y}(3,4)
表示參數列表的第一對括號必須緊着着關鍵字func,因爲匿名函數沒有名稱,花括號{}涵蓋着函數體,最後一堆括號表示對匿名函數的直接調用

linq

defer panic recover

defer

defer相當於java的finally

panic

panic是用來表示非常嚴重的不可恢復的錯誤,在Go語言是一個內置函數,接收一個interface{}類型的值作爲參數。panic的作用就像我們平常接觸的異常,不過Go沒有try...catch,所以panic一般會導致程序掛掉(除非recover),
所以在go語言中的異常就是真的異常了。
關鍵的一點,函數執行的時候panic了,將先到defer中執行完,panic再想傳遞

recover

recover用來捕獲panic,被recover捕獲到的panic將不會向上傳遞
recover之後,邏輯並不會恢復到panic那個點去,函數還在defer之後返回

導包下劃線"_"的作用

引入該包,但是並非真的需要使用使用這些包,同時會執行它的init()函數
//mysql的關鍵字index,處理,給該字段加上單引號反單引號Index

構建http服務

func IndexHander(w http.ResponseWriter,r *http.Request){

fmt.Fprintln("hello wrold")

}
func main(){

http.HandleFunc("/",IndexHander)
http.ListenAndServer("127.0.0.1:8080",nil)

}

接收request的過程,最重要的莫過於路由(router),即實現一個Multiplexer器,Go中既可以使用內置的multiplexer--DefaultServerMux,也可以自定義。
Multiplexer路由的目的就是爲了找到處理器函數(handle),後者講對request進行處理,同時構建response

函數作爲參數的優勢?

init函數

不能夠有任何參數,雖然每個package裏面可以寫任意多個init函數,但這無論是可讀性還是以後的可維護性來說,我們都強烈建議用戶在一個package中每個文件中只寫一個init函數

struct的聲明方式

type person struct{
    name string
    age int
}
//1、
var P person
p.name = "dack"
p.age = 21
//2、
p := person{"dack",21}
//3、
p := person{
    age : 21
    name : "dack"
}
//4、可以通過new函數分配一個指針,此處P的類型爲 *person

struct的匿名字段

當一個匿名字段是一個struct的時候,那麼這個struct所擁有的全部字段都被隱式地引入當前定義的這個struct
type Human struct{
    name string
    age int 
    weight int
}

type Student struct{
    Human    //匿名字段,那麼默認Student就包含了Human的所有字段
    speciality string
}

func main(){
    mark := Student{Human{"dacl",21,65},"Go Science"}
    mark.speciality = "AI"
    mark.age = 25
    mark.weight = 70
}

Student可以訪問name和age就像自己用自己的字段一樣
匿名對象能夠實現字段的繼承
Student還能訪問Human

mark.Human = Human{"tony",22,55}
mark.Human.age = 1

不僅struct可以作爲匿名字段,自定義類型、內置類型也可以作爲匿名字段

如果遇到human裏面有一個字段phone,student裏面的字段phone,那麼優先訪問最外最外層

golang API json ,struct結構中標籤(Tag)的使用

在golang中,命名都是推薦用駝峯方式,並且在首字母大小寫有特殊含義:包外無法引用
但由於經常需要和其他系統進行數據交互,例如轉換成json格式,存儲到Redis等。這個時候如果直接使用屬性名來作爲鍵值會不符合項目要求

於是就有了tag,也就是有了json:name

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章