go_wed編程筆記

1、Go基礎mysql

①「調用」就是向被調用函數的參數賦值,執行被調用函數語句,並使用其返回值。git

這樣,函數就封裝了能夠被反覆調用的一些語句,根據須要賦值獲得不一樣的結果。github


② min,max := 0, 100web

   var s stringsql

min,max經過賦值引伸聲明爲int類型,s用var明確聲明爲string類型。數組


③Go使用字節而不是字符做爲字符串的單元。由於Go的字符采用UTF-8編碼,是不等長的。app

英文字母數字是1個字節,希臘字母要2個字節,漢字等大寫字符集,使用3個以上的字節ide

才能表示。因此字符串取其最小單位。函數


④計算結果的類型與操做數類型相同。 3/2 == 1.工具


⑤Go裏面switch默認至關於每一個case最後帶有break,匹配成功後不會

自動向下執行其餘case,

而是跳出整個switch, 可是可使用fallthrough強制執行後面的case代碼



⑥這樣,咱們就達到了修改x的目的。那麼到底傳指針有什麼好處呢?


1.傳指針使得多個函數能操做同一個對象。

2.傳指針比較輕量級 (8bytes),只是傳內存地址,咱們能夠用指針傳遞體積大的結構體。若是用參數值傳遞的話, 

在每次copy上面就會花費相對較多的系統開銷(內存和時間)。

因此當你要傳遞大的結構體的時候,用指針是一個明智的選擇。

3.Go語言中channel,slice,map這三種類型的實現機制相似指針,

因此能夠直接傳遞,而不用取地址後傳遞指針。

(注:若函數需改變slice的長度,則仍須要取地址傳遞指針)


⑦Go語言中有種不錯的設計,即延遲(defer)語句,你能夠在函數中添加多個defer語句。

當函數執行到最後時,這些defer語句會按照逆序執行,最後該函數返回。

特別是當你在進行一些打開資源的操做時,遇到錯誤須要提早返回,在返回前你須要關閉相應的資源,

否則很容易形成資源泄露等問題。

在defer後指定的函數會在函數退出前調用。


2、流程和函數

函數做爲值、類型

在Go中函數也是一種變量,咱們能夠經過type來定義它,它的類型就是全部擁有相同的參數,相同的返回值的一種類型

type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])

函數做爲類型到底有什麼好處呢?那就是能夠把這個類型的函數當作值來傳遞,請看下面的例子

package main

import"fmt"

 

type testInt func(int) bool// 聲明瞭一個函數類型

 

func isOdd(integer int) bool {

    if integer%2 == 0 {

       returnfalse

    }

    returntrue

}

 

func isEven(integer int) bool {

    if integer%2 == 0 {

       returntrue

    }

    returnfalse

}

 

// 聲明的函數類型在這個地方當作了一個參數

 

func filter(slice []int, f testInt) []int {

    var result []int

    for _, value := range slice {

       if f(value) {

           result = append(result, value)

       }

    }

    return result

}

 

func main(){

   slice := []int {1, 2, 3, 4, 5, 7}

   fmt.Println("slice= ", slice)

   odd := filter(slice, isOdd)    // 函數當作值來傳遞了

   fmt.Println("Oddelements of slice are: ", odd)

    even := filter(slice, isEven)  // 函數當作值來傳遞了

   fmt.Println("Evenelements of slice are: ", even)

}

函數當作值和類型在咱們寫一些通用接口的時候很是有用,經過上面例子咱們看到testInt這個類型是一個函數類型,而後兩個filter函數的參數和返回值與testInt類型是同樣的,可是咱們能夠實現不少種的邏輯,這樣使得咱們的程序變得很是的靈活。

 

PanicRecover

Go沒有像Java那樣的異常機制,它不能拋出異常,而是使用了panic和recover機制。必定要記住,你應當把它做爲最後的手段來使用,也就是說,你的代碼中應當沒有,或者不多有panic的東西。這是個強大的工具,請明智地使用它。那麼,咱們應該如何使用它呢?

Panic

是一個內建函數,能夠中斷原有的控制流程,進入一個使人恐慌的流程中。當函數F調用panic,函數F的執行被中斷,可是F中的延遲函數會正常執行,而後F返回到調用它的地方。在調用的地方,F的行爲就像調用了panic。這一過程繼續向上,直到發生panic的goroutine中全部調用的函數返回,此時程序退出。恐慌能夠直接調用panic產生。也能夠由運行時錯誤產生,例如訪問越界的數組。

Recover

是一個內建的函數,可讓進入使人恐慌的流程中的goroutine恢復過來。recover僅在延遲函數中有效。在正常的執行過程當中,調用recover會返回nil,而且沒有其它任何效果。若是當前的goroutine陷入恐慌,調用recover能夠捕獲到panic的輸入值,而且恢復正常的執行。

下面這個函數演示瞭如何在過程當中使用panic

var user = os.Getenv("USER")

 

func init() {

    if user == "" {

       panic("no value for $USER")

    }

}

下面這個函數檢查做爲其參數的函數在執行時是否會產生panic:

func throwsPanic(f func()) (b bool) {

    deferfunc() {

       if x := recover(); x != nil {

           b = true

        }

   }()

   f() //執行函數f,若是f中出現了panic,那麼就能夠恢復回來

    return

}

main函數和init函數

Go裏面有兩個保留的函數:init函數(可以應用於全部的package)和main函數(只能應用於package main)。這兩個函數在定義時不能有任何的參數和返回值。雖然一個package裏面能夠寫任意多個init函數,但這不管是對於可讀性仍是之後的可維護性來講,咱們都強烈建議用戶在一個package中每一個文件只寫一個init函數。

Go程序會自動調用init()和main(),因此你不須要在任何地方調用這兩個函數。每一個package中的init函數都是可選的,但package main就必須包含一個main函數。

程序的初始化和執行都起始於main包。若是main包還導入了其它的包,那麼就會在編譯時將它們依次導入。有時一個包會被多個包同時導入,那麼它只會被導入一次(例如不少包可能都會用到fmt包,但它只會被導入一次,由於沒有必要導入屢次)。當一個包被導入時,若是該包還導入了其它的包,那麼會先將其它包導入進來,而後再對這些包中的包級常量和變量進行初始化,接着執行init函數(若是有的話),依次類推。等全部被導入的包都加載完畢了,就會開始對main包中的包級常量和變量進行初始化,而後執行main包中的init函數(若是存在的話),最後執行main函數。下圖詳細地解釋了整個執行過程:

2.3 流程和函數

圖2.6 main函數引入包初始化流程圖

import

咱們在寫Go代碼的時候常常用到import這個命令用來導入包文件,而咱們常常看到的方式參考以下:

import(    "fmt")

而後咱們代碼裏面能夠經過以下的方式調用

fmt.Println("hello world")

上面這個fmt是Go語言的標準庫,實際上是去GOROOT環境變量指定目錄下去加載該模塊,固然Go的import還支持以下兩種方式來加載本身寫的模塊:

  1. 相對路徑

    import 「./model」 //當前文件同一目錄的model目錄,可是不建議這種方式來import

  2. 絕對路徑

    import 「shorturl/model」 //加載gopath/src/shorturl/model模塊

上面展現了一些import經常使用的幾種方式,可是還有一些特殊的import,讓不少新手很費解,下面咱們來一一講解一下究竟是怎麼一回事

  1. 點操做

    咱們有時候會看到以下的方式導入包

      import(
          . "fmt"
      )

    這個點操做的含義就是這個包導入以後在你調用這個包的函數時,你能夠省略前綴的包名,也就是前面你調用的fmt.Println("hello world")能夠省略的寫成Println("hello world")

  2. 別名操做

    別名操做顧名思義咱們能夠把包命名成另外一個咱們用起來容易記憶的名字

      import(      f "fmt"
      )

    別名操做的話調用包函數時前綴變成了咱們的前綴,即f.Println("hello world")

  3. _操做

    這個操做常常是讓不少人費解的一個操做符,請看下面這個import

      import (      "database/sql"
          _ "github.com/ziutek/mymysql/godrv"
      )

    _操做實際上是引入該包,而不直接使用包裏面的函數,而是調用了該包裏面的init函數。

相關文章
相關標籤/搜索