GO的第一天,聲明和變量

其實以前有自學過go的基礎,可是時隔蠻久的,而後也沒有去常常性的使用,如今重頭開始學習啦ide

聲明

聲明語句定義了程序的各類實體對象以及部分或所有的屬性。Go語言主要有四種類型的聲明語句:變量(var)常量(const)類型(type)函數(func)實體對象的聲明。
一個Go語言編寫的程序對應一個或多個以.go爲文件後綴名的源文件中。每一個源文件編寫順序是函數

  • 說明該源文件是屬於哪一個包。
package main
  • 包聲明語句以後是import語句導入依賴的其它包
import "fmt"
  • 而後是包一級的類型、變量、常量、函數的聲明語句,包一級的各類類型的聲明語句的順序可有可無
var x, y int
const pi = 3.14

func sayhi(){
    fmt.Println("Hello")
}

變量

var聲明語句能夠建立一個特定類型的變量,而後給變量附加一個名字,而且設置變量的初始值。變量聲明的通常語法以下:學習

var 變量名字 類型 = 表達式

其中「類型」或「= 表達式」兩個部分能夠省略其中的一個。若是省略的是類型信息,那麼將根據初始化表達式來推導變量的類型信息。若是初始化表達式被省略,那麼將用零值初始化該變量。測試

var x int = 1
var y = 2
var i, j, k int                 // int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string

簡短變量聲明

在函數內部,有一種稱爲簡短變量聲明語句的形式可用於聲明和初始化局部變量。它以「名字 := 表達式」形式聲明變量,變量的類型根據表達式來自動推導ui

i := 100

和var形式聲明語句同樣,簡短變量聲明語句也能夠用來聲明和初始化一組變量:指針

i, j := 0, 1

請記住「:=」是一個變量聲明語句,而「=」是一個變量賦值操做。code

若是重複使用簡短變量聲明定義一個變量,那這個變量的第二次聲明就是賦值對象

in, err := os.Open(infile)
// 這裏只聲明瞭out一個變量,err進行了賦值操做
out, err := os.Create(outfile)

簡短變量聲明語句中必須至少要聲明一個新的變量,下面的代碼將不能編譯經過:生命週期

f, err := os.Open(infile)
// ...
f, err := os.Create(outfile) // compile error: no new variables

解決的方法是第二個簡短變量聲明語句改用普通的多重賦值語句。內存

簡短變量聲明語句只有對已經在同級詞法域聲明過的變量才和賦值操做語句等價,若是變量是在外部詞法域聲明的,那麼簡短變量聲明語句將會在當前詞法域從新聲明一個新的變量。

ps:簡單來講就是,簡短變量聲明你就當作普通聲明來用,可是通常都是用在函數體內,重複聲明一個變量的時候注意細節

指針

想了好久,沒辦法用比較通俗易懂的說法來簡述,若是你跟我同樣會PHP,那你就把這個指針理解爲PHP中的引用就好了,直接用代碼展現吧

x := 1
p := &x         // p, of type *int, points to x
fmt.Println(*p) // "1"
*p = 2          // equivalent to x = 2
fmt.Println(x)  // "2"

若是用「var x int」聲明語句聲明一個x變量,那麼&x表達式(取x變量的內存地址)將產生一個指向該整數變量的指針,指針對應的數據類型是 *int ,指針被稱之爲「指向int類型的指針」。若是指針名字爲p,那麼能夠說「p指針指向變量x」,或者說「p指針保存了x變量的內存地址」。同時 *p 表達式對應p指針指向的變量的值。通常 *p 表達式讀取指針指向的變量的值,這裏爲int類型的值,同時由於 *p 對應一個變量,因此該表達式也能夠出如今賦值語句的左邊,表示更新指針所指向的變量的值。

var x, y int
fmt.Println(&x == &x, &x == &y, &x == nil) // "true false false"

任何類型的指針的零值都是nil。若是p指向某個有效變量,那麼p != nil測試爲真。指針之間也是能夠進行相等測試的,只有當它們指向同一個變量或所有是 nil 時才相等。
簡單的函數使用指針:

func incr(p *int) int {
    *p++ // 很是重要:只是增長p指向的變量的值,並不改變p指針!!!
    return *p
}

v := 1
incr(&v)              // side effect: v is now 2
fmt.Println(incr(&v)) // "3" (and v is 3)

new函數

另外一個建立變量的方法是調用用內建的new函數。表達式new(T)將建立一個T類型的匿名變量,初始化爲T類型的零值,而後返回變量地址,返回的指針類型爲*T。
用new建立變量和普通變量聲明語句方式建立變量沒有什麼區別,除了不須要聲明一個臨時變量的名字外,咱們還能夠在表達式中使用new(T)。換言之,new函數相似是一種語法糖,而不是一個新的基礎概念。
下面的兩個newInt函數有着相同的行爲:

func newInt() *int {
    return new(int)
}

func newInt() *int {
    var dummy int
    return &dummy
}

變量的生命週期

變量的生命週期指的是在程序運行期間變量有效存在的時間間隔。對於在包一級聲明的變量來講,它們的生命週期和整個程序的運行週期是一致的。而相比之下,局部變量的聲明週期則是動態的:每次從建立一個新變量的聲明語句開始,直到該變量再也不被引用爲止,而後變量的存儲空間可能被回收。函數的參數變量和返回值變量都是局部變量。它們在函數每次被調用的時候建立。

參考

《GO語言聖經》

相關文章
相關標籤/搜索