Golang 知識點

變量聲明

var a
a=100
//或
var b = 100
//或
var c int = 100

// := 是聲明并賦值帅腌,并且系統(tǒng)自動推斷類型,不需要var關(guān)鍵字
d := 100

package main

import "fmt"

func main() {
    // 切片的一種定義方式是 用 make
    // var x = make([]float64, 5) ,切片用make
    //另外一種是通過數(shù)組切片賦值礁凡,采用[low_index:high_index]的方式獲取數(shù)值切片庐冯,其中切片元素包括low_index的元素孽亲,但是不包括high_index的元素。

    ar := new([3]int)// 指針
    ar1 := [3]int{0, 0, 0}
    var ar2 = [3]int{0, 0, 0}
    var ar3 [3]int
    var ar4 = [3]int{0: 1, 1: 2, 2: 3}
    fp(ar)
    fp(&ar1)
    fp(&ar2)
    fp(&ar3)
    fp(&ar4)

    fp1(ar)
    fp1(&ar1)
    fp1(&ar2)
    fp1(&ar3)
    fp1(&ar4)

}

func fp(a *[3]int)  { print(*a) }
func fp1(a *[3]int) { print(a) }

與 Python不同

任何空值(nil)或者零值(0, 0.0, "")都不能作為布爾型來直接判斷展父。

func main() {
    if 0 {
        fmt.Println("hello world")
    }
    if nil {
        fmt.Println("hello world")
    }
    if "" {
        fmt.Println("hello world")
    }
}

常用命令

go build: 編譯出可執(zhí)行文件
go install: go build + 把編譯后的可執(zhí)行文件放到GOPATH/bin目錄下
go get: git clone + go install

何時使用指針

指針的一大用途就是可以將變量的指針作為實參傳遞給函數(shù)返劲,從而在函數(shù)內(nèi)部能夠直接修改實參所指向的變量值。

Go的變量傳遞都是值傳遞栖茉。

package main

import (
    "fmt"
)

func change(x int) {
    x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(x)
    fmt.Println(x)
}
上面的例子輸出結(jié)果為

100
100
很顯然篮绿,change函數(shù)改變的僅僅是內(nèi)部變量x的值,而不會改變傳遞進(jìn)去的實參吕漂。其實亲配,也就是說Go的函數(shù)一般關(guān)心的是輸出結(jié)果,而輸入?yún)?shù)就相當(dāng)于信使跑到函數(shù)門口大叫惶凝,你們這個參數(shù)是什么值吼虎,那個是什么值,然后就跑了梨睁。你函數(shù)根本就不能修改它的值鲸睛。不過如果是傳遞的實參是指針變量,那么函數(shù)一看坡贺,小子這次你地址我都知道了官辈,哪里跑。那么就是下面的例子:

package main

import (
    "fmt"
)

func change(x *int) {
    *x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(&x)
    fmt.Println(x)
}
上面的例子中遍坟,change函數(shù)的虛參為整型指針變量拳亿,所以在main中調(diào)用的時候傳遞的是x的地址。然后在change里面使用*x=200修改了這個x的地址的值愿伴。所以x的值就變了肺魁。這個輸出是:

100
200

一個函數(shù)何時該用指針類型做receiver對初學(xué)者而言一直是個頭疼的問題。如果不知道該如何取舍隔节,選擇指針類型的receiver鹅经。但有些時候value receiver更加合適,比如對象是一些輕量級的不變的structs怎诫,使用value receiver會更加高效瘾晃。下面是列舉了一些常用的判斷指導(dǎo)。

如果receiver是map幻妓、func或者chan蹦误,不要使用指針

如果receiver是slice并且該函數(shù)并不會修改此slice,不要使用指針

如果該函數(shù)會修改receiver,此時一定要用指針

如果receiver是struct并且包含互斥類型sync.Mutex强胰,或者是類似的同步變量舱沧,receiver必須是指針,這樣可以避免對象拷貝

如果receiver是較大的struct或者array偶洋,使用指針則更加高效熟吏。多大才算大?假設(shè)struct內(nèi)所有成員都要作為函數(shù)變量傳進(jìn)去涡真,如果覺得這時數(shù)據(jù)太多分俯,就是struct太大

如果receiver是struct,array或者slice哆料,并且其中某個element指向了某個可變量缸剪,則這個時候receiver選指針會使代碼的意圖更加明顯

如果receiver使較小的struct或者array,并且其變量都是些不變量东亦、常量杏节,例如time.Time,value receiver更加適合典阵,因為value receiver可以減少需要回收的垃圾量奋渔。

最后,如果不確定用哪個壮啊,使用指針類的receiver

常量

變量定義的類型推斷方式 := 不能夠用來定義常量

快速聲明

Go還提供了一種同時定義多個變量或者常量的快捷方式嫉鲸。


import (
"fmt"
)

func main() {
    var (
        a int     = 10
        b float64 = 32.45
        c bool    = true
    )
    const (
        Pi   float64 = 3.14
        True bool    = true
    )

    fmt.Println(a, b, c)
    fmt.Println(Pi, True)
}

if 判斷的()

package main

import (
"fmt"
)

func main() {
const Male = 'M'
const Female = 'F'

var dog_age = 10
var dog_sex = 'M'

if (dog_age == 10 && dog_sex == 'M') {
    fmt.Println("dog")
}

}


但是如果你使用Go提供的格式化工具來格式化這段代碼的話,Go會智能判斷你的括號是否必須有歹啼,否則的話玄渗,會幫你去掉的。你可以試試狸眼。

go fmt test_bracket.go
然后你會發(fā)現(xiàn)藤树,咦?拓萌!果真被去掉了岁钓。

#  for 循環(huán)

package main

import (
"fmt"
)

在Go里面沒有提供while關(guān)鍵字,如果你懷念while的寫法也可以這樣:

func main() {
    var i int = 1

    for i <= 100 {
        fmt.Println(i)
        i++
    }
}
或許你會問微王,如果我要死循環(huán)呢屡限?是不是for true?呵呵炕倘,不用了钧大,直接這樣。

for{

}

切片

我們發(fā)現(xiàn)arr1的長度變?yōu)?1激才,因為元素個數(shù)現(xiàn)在為11個。另外我們發(fā)現(xiàn)arr1的容量也變了,變?yōu)樵瓉淼膬杀丁?/p>

這是因為Go在默認(rèn)的情況下瘸恼,如果追加的元素超過了容量大小劣挫,Go會自動地重新為切片分配容量,容量大小為原來的兩倍东帅。

總結(jié)一下压固,數(shù)組和切片的區(qū)別就在于[]里面是否有數(shù)字或者...!!!!!!!!!!!

因為數(shù)值長度是固定的,而切片是可變的靠闭。

函數(shù)預(yù)定義

命名返回值

Go的函數(shù)很有趣帐我,你甚至可以為返回值預(yù)先定義一個名稱,在函數(shù)結(jié)束的時候愧膀,直接一個return就可以返回所有的預(yù)定義返回值拦键。例如上面的例子,我們將sum作為命名返回值檩淋。

package main

import (
"fmt"
)

func slice_sum(arr []int) (sum int) {
    sum = 0
    for _, elem := range arr {
        sum += elem
    }
    return
}

func main() {
    var arr1 = []int{1, 3, 2, 3, 2}
    var arr2 = []int{3, 2, 3, 1, 6, 4, 8, 9}
    fmt.Println(slice_sum(arr1))
    fmt.Println(slice_sum(arr2))
}

這里要注意的是芬为,如果你定義了命名返回值,那么在函數(shù)內(nèi)部你將不能再重復(fù)定義一個同樣名稱的變量蟀悦。比如第一個例子中我們用sum := 0來定義和初始化變量sum媚朦,而在第二個例子中,我們只能用sum = 0初始化這個變量了日戈。因為 := 表示的是定義并且初始化變量询张。

異常處理

panic & recover

當(dāng)你周末走在林蔭道上,聽著小歌浙炼,哼著小曲份氧,很是愜意。突然之間鼓拧,從天而降瓢潑大雨半火,你頓時慌張(panic)起來,
沒有帶傘啊季俩,淋著雨感冒就不好了钮糖。于是你四下張望,忽然發(fā)現(xiàn)自己離地鐵站很近酌住,那里有很多賣傘的店归,心中頓時又安定了下來(recover),于是你飛奔過去買了一把傘(defer )

Go語言提供了關(guān)鍵字defer來在函數(shù)運(yùn)行結(jié)束的時候運(yùn)行一段代碼或調(diào)用一個清理函數(shù)酪我。上面的例子中消痛,雖然second()函數(shù)寫在first()函數(shù)前面,但是由于使用了defer標(biāo)注都哭,所以它是在main函數(shù)執(zhí)行結(jié)束的時候才調(diào)用的秩伞。


package main

import (
    "fmt"
)

func main() {

    //defer一定是在函數(shù)執(zhí)行結(jié)束的時候運(yùn)行的逞带。不管是正常結(jié)束還是異常終止,相當(dāng)于finally
    defer func() {
        //panic用來觸發(fā)異常,而recover用來終止異常并且返回傳遞給panic的值纱新。(注意recover并不能處理異常展氓,而且recover只能在defer里面使用,否則無效脸爱。)
        msg := recover()
        fmt.Println(msg)
    }()
    fmt.Println("I am walking and singing...")
    panic("It starts to rain cats and dogs")
}

指針

定義
Go函數(shù)的參數(shù)傳遞方式是值傳遞
而指針的主要作用就是在函數(shù)內(nèi)部改變傳遞進(jìn)來變量的值

至于使不使用結(jié)構(gòu)體指針和使不使用指針的出發(fā)點是一樣的遇汞,那就是你是否試圖在函數(shù)內(nèi)部改變傳遞進(jìn)來的參數(shù)的值。再舉個例子如下:

在學(xué)Python的時候簿废,經(jīng)常要注意不小心修改了可變類型空入,如list。事實上這種可變和不可變了類型族檬,是Python為了簡化你的操作歪赢。

但是在Golang中,數(shù)組和切片导梆,你可以當(dāng)做可變類型轨淌,也可以當(dāng)做不可變類型,來使用看尼,通過使用*递鹉,&指針。

所謂指針其實你可以把它想像成一個箭頭藏斩,這個箭頭指向(存儲)一個變量的地址躏结。

因為這個箭頭本身也需要變量來存儲,所以也叫做指針變量狰域。

new 的使用發(fā)現(xiàn)


package main

import (
    "fmt"
)

func set_value(x_ptr *int) {

//指針指向的地址內(nèi)容設(shè)置為100
    *x_ptr = 100
}
func main() {
    //開辟一塊內(nèi)存媳拴,用于存貯指針地址,且此指針地址的變量名為x_ptr
    x_ptr := new(int)

    set_value(x_ptr)

    //指針變量指向的地址,因為本身就是指針變量兆览,存貯的就是指向的地址
    fmt.Println(x_ptr)
    //指針變量本身的地址
    fmt.Println(&x_ptr)

    //打印指針變量指向的地址內(nèi)容
    fmt.Println(*x_ptr)
}

0xc084000040
0xc084000038
100

結(jié)構(gòu)體組合函數(shù)

上面我們在main函數(shù)中計算了矩形的面積屈溉,但是我們覺得矩形的面積如果能夠作為矩形結(jié)構(gòu)體的“內(nèi)部函數(shù)”提供會更好。這樣我們就可以直接說這個矩形面積是多少抬探,而不用另外去取寬度和長度去計算∽咏恚現(xiàn)在我們看看結(jié)構(gòu)體“內(nèi)部函數(shù)”定義方法:

package main

import (
"fmt"
)

type Rect struct {
width, length float64
}

func (rect Rect) area() float64 {
return rect.width * rect.length
}

func main() {
var rect = Rect{100, 200}

fmt.Println("Width:", rect.width, "Length:", rect.length,
    "Area:", rect.area())

}
咦?這個是什么“內(nèi)部方法”小压,根本沒有定義在Rect數(shù)據(jù)類型的內(nèi)部跋吖!?

確實如此怠益,我們看到仪搔,雖然main函數(shù)中的rect變量可以直接調(diào)用函數(shù)area()來獲取矩形面積,但是area()函數(shù)確實沒有定義在Rect結(jié)構(gòu)體內(nèi)部蜻牢,這點和C語言的有很大不同烤咧。Go使用組合函數(shù)的方式來為結(jié)構(gòu)體定義結(jié)構(gòu)體方法馍盟。我們仔細(xì)看一下上面的area()函數(shù)定義耘拇。

首先是關(guān)鍵字func表示這是一個函數(shù)琢感,第二個參數(shù)是結(jié)構(gòu)體類型和實例變量葡兑,第三個是函數(shù)名稱,第四個是函數(shù)返回值立膛。這里我們可以看出area()函數(shù)和普通函數(shù)定義的區(qū)別就在于area()函數(shù)多了一個結(jié)構(gòu)體類型限定。這樣一來Go就知道了這是一個為結(jié)構(gòu)體定義的方法梯码。

這里需要注意一點就是定義在結(jié)構(gòu)體上面的函數(shù)(function)一般叫做方法(method)

接口和鴨子類型

package main

import (
    "fmt"
)

type Phone interface {
    call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}

以前我們說過宝泵,Go語言式靜態(tài)類型語言,變量的類型在運(yùn)行過程中不能改變轩娶。但是在上面的例子中儿奶,phone變量好像先定義為Phone類型,然后是NokiaPhone類型鳄抒,最后成為了IPhone類型闯捎,真的是這樣嗎?

在Go語言里面许溅,一個類型A只要實現(xiàn)了接口X所定義的全部方法瓤鼻,那么A類型的變量也是X類型的變量。
就是贤重,你能叫茬祷,能游,你就是鴨子

數(shù)組和指針

package main
import "fmt"

func main() {
array := [3]float64{7.0, 8.5, 9.1}
x := Sum(&array) // Note the explicit address-of operator
// to pass a pointer to the array
fmt.Printf("The sum of the array is: %f", x)
}

func Sum(a *[3]float64) (sum float64) {
for _, v := range a { // derefencing *a to get back to the array is not necessary!
sum += v
}
return
}

*表示并蝗,你不用來祭犯,我去干你,我只接受你的地址滚停,不接受你沃粗。

&表示我告訴你的我的地址

不用*指針的方式的話,會復(fù)制一份數(shù)組键畴,浪費內(nèi)存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末最盅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子镰吵,更是在濱河造成了極大的恐慌檩禾,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疤祭,死亡現(xiàn)場離奇詭異盼产,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)勺馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門戏售,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨核,“玉大人,你說我怎么就攤上這事灌灾〈暌耄” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵锋喜,是天一觀的道長些己。 經(jīng)常有香客問我,道長嘿般,這世上最難降的妖魔是什么段标? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮炉奴,結(jié)果婚禮上逼庞,老公的妹妹穿的比我還像新娘。我一直安慰自己瞻赶,他們只是感情好赛糟,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著砸逊,像睡著了一般璧南。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上师逸,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天穆咐,我揣著相機(jī)與錄音,去河邊找鬼字旭。 笑死对湃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遗淳。 我是一名探鬼主播拍柒,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屈暗!你這毒婦竟也來了拆讯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤养叛,失蹤者是張志新(化名)和其女友劉穎种呐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弃甥,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡爽室,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了淆攻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阔墩。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘿架,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出啸箫,到底是詐尸還是另有隱情耸彪,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布忘苛,位于F島的核電站蝉娜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扎唾。R本人自食惡果不足惜蜀肘,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稽屏。 院中可真熱鬧,春花似錦西乖、人聲如沸狐榔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽薄腻。三九已至,卻和暖如春届案,著一層夾襖步出監(jiān)牢的瞬間庵楷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工楣颠, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留尽纽,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓童漩,卻偏偏與公主長得像弄贿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子矫膨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.安裝 https://studygolang.com/dl 2.使用vscode編輯器安裝go插件 3.go語...
    go含羞草閱讀 1,553評論 0 6
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉差凹,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,720評論 0 9
  • 新的一月,新的一周開始了侧馅,2018年已過一半危尿,感覺除了精神財富有點收獲以外,其他的都很匱乏馁痴! 前幾天蓓蕾老師說有個...
    鄢瑜含閱讀 717評論 5 0
  • 小時候院子里有棵絨花樹谊娇,姐姐常把絨花插在我的小辮子上,現(xiàn)在想想那個頭戴絨花的小姑娘一定很美很可愛吧罗晕,可惜我只能想想...
    慢慢走淺淺愛閱讀 943評論 14 14
  • 馬克思說過:“珠寶商人所看到的只是商業(yè)的價值邮绿,而不是珠寶的美和特性渠旁,他沒有珠寶的感覺”。 就如我們講的一些藝術(shù)販子...
    烽火煤閱讀 293評論 0 0