go語(yǔ)言 - 初次見(jiàn)面

語(yǔ)言特性

  • 自動(dòng)垃圾回收
  • 更豐富的內(nèi)置類型
  • 函數(shù)多返回值
  • 錯(cuò)誤處理
  • 匿名函數(shù)和閉包
  • 類型和接口
  • 并發(fā)編程
  • 反射
  • 語(yǔ)言交互性

自動(dòng)垃圾回收

編程中,一個(gè)難題就是內(nèi)存管理,如果管理不好對(duì)內(nèi)存的使用,發(fā)生內(nèi)存泄露可能會(huì)引發(fā)嚴(yán)重的問(wèn)題,比如使程序崩潰。C和C++這樣的編程語(yǔ)言,提供了指針這樣靈活的類型,但卻必須手動(dòng)管理內(nèi)存,增加了編程的復(fù)雜性。Java等編程語(yǔ)言本身提供了自動(dòng)的垃圾回收機(jī)制,減少了編程的不少負(fù)擔(dān)。go語(yǔ)言融合了眾多編程語(yǔ)言的優(yōu)秀特點(diǎn),自然也引入了自動(dòng)的垃圾回收機(jī)制。

所謂垃圾回收,即所有的內(nèi)存分配動(dòng)作都會(huì)被在運(yùn)行時(shí)記錄,同時(shí)任何對(duì)該內(nèi)存的使用也都會(huì)被記錄,然后垃圾回收器會(huì)對(duì)所有已經(jīng)分配的內(nèi)存進(jìn)行跟蹤監(jiān)測(cè),一旦發(fā)現(xiàn)有些內(nèi)存已經(jīng)不再被任何人使用,就階段性地回收這些沒(méi)人用的內(nèi)存。當(dāng)然,因?yàn)樾枰M量最小化垃圾回收的性能損耗,以及降低對(duì)正常程序執(zhí)行過(guò)程的影響,現(xiàn)實(shí)中的垃圾回收算法要比這個(gè)復(fù)雜得多,比如為對(duì)象增加年齡屬性等,但基本原理都是如此。

更豐富的內(nèi)置類型

go語(yǔ)言不僅提供了幾乎所有語(yǔ)言都提供的整形,浮點(diǎn)型等簡(jiǎn)單類型,數(shù)組和字符串等高級(jí)類型,還提供了字典類型(map),數(shù)組切片(Slice)。

函數(shù)多返回值

Go語(yǔ)言革命性地在靜態(tài)開(kāi)發(fā)語(yǔ)言陣營(yíng)中率先提供了多返回值功能。這個(gè)特性讓開(kāi)發(fā)者可以從原來(lái)用各種比較別扭的方式返回多個(gè)值的痛苦中解脫出來(lái),既不用再區(qū)分參數(shù)列表中哪幾個(gè)用于輸入,哪幾個(gè)用于輸出,也不用再只為了返回多個(gè)值而專門定義一個(gè)數(shù)據(jù)結(jié)構(gòu)。

go語(yǔ)言函數(shù)返回多個(gè)值的簡(jiǎn)單示例:

func getName() (firstName, middleName, lastName, nickName string) {
    return "May", "M", "Chen", "Babe"
}

因?yàn)榉祷刂刀家呀?jīng)有名字,因此各個(gè)返回值也可以用如下方式來(lái)在不同的位置進(jìn)行賦值,從而提供了極大的靈活性:

func getName() (firstName, middleName, lastName, nickName string) {
    firstName = "May"
    middleName = "M"
    lastName = "Chen"
    nickName = "Babe"
    return
}

并不是每一個(gè)返回值都必須賦值,沒(méi)有被明確賦值的返回值將保持默認(rèn)的空值。
多返回值函數(shù)調(diào)用:

fn, mn, ln, nn := getName()

如果只對(duì)該函數(shù)其中的某幾個(gè)返回值感興趣的話,也可以直接用下劃線作為占位符來(lái)忽略其他不關(guān)心的返回值:

_, _, lastName, _ := getName()

錯(cuò)誤處理

Go語(yǔ)言引入了3個(gè)關(guān)鍵字用于標(biāo)準(zhǔn)的錯(cuò)誤處理流程。

  • defer
  • panic
  • recover

與C++和Java等語(yǔ)言中的異常捕獲機(jī)制相比, Go語(yǔ)言的錯(cuò)誤處理機(jī)制可以大量減少代碼量,讓開(kāi)發(fā)者也無(wú)需僅僅為了程序安全性而添加大量一層套一層的try-catch語(yǔ)句。
代碼中過(guò)多的嵌套,真是讓人抓狂。

匿名函數(shù)和閉包

在Go語(yǔ)言中,所有的函數(shù)也是值類型,可以作為參數(shù)傳遞。

類型和接口

Go語(yǔ)言不支持繼承和重載,而只是支持了最基本的類型組合功能。
Go語(yǔ)言引入了一個(gè)無(wú)比強(qiáng)大的“非侵入式” 接口的概念,讓開(kāi)發(fā)者從以往對(duì)C++和Java開(kāi)發(fā)中的接口管理問(wèn)題中解脫出來(lái)。

go語(yǔ)言簡(jiǎn)單的接口使用示例:

type Bird struct {
    ...
}

func (b *Bird) Fly() { //以鳥的方式飛行

}

在實(shí)現(xiàn)Bird類型時(shí)完全沒(méi)有任何IFly的信息。我們可以在另外一個(gè)地方定義這個(gè)IFly。

type IFly interface { 
    Fly()
}

上面兩個(gè)定義看起來(lái)絲毫沒(méi)有關(guān)系,現(xiàn)在看看如何使用它們:

func main() {
    var fly IFly = new(Bird) 
    fly.Fly()
}

可以看出,雖然Bird類型實(shí)現(xiàn)的時(shí)候,沒(méi)有聲明與接口IFly的關(guān)系,但接口和類型可以直接轉(zhuǎn)換,甚至接口的定義都不用在類型定義之前,這種比較松散的對(duì)應(yīng)關(guān)系可以大幅降低因?yàn)榻涌谡{(diào)整而導(dǎo)致的大量代碼調(diào)整工作。

并發(fā)編程

Go語(yǔ)言引入了goroutine概念,它使得并發(fā)編程變得非常簡(jiǎn)單。通過(guò)使用goroutine而不是裸用操作系統(tǒng)的并發(fā)機(jī)制,以及使用消息傳遞而不是共享內(nèi)存來(lái)通信,Go語(yǔ)言讓并發(fā)編程變得更加輕盈和安全。

通過(guò)在函數(shù)調(diào)用前使用關(guān)鍵字go,我們即可讓該函數(shù)以goroutine方式執(zhí)行。goroutine是一種比線程更加輕盈、更省資源的協(xié)程。Go語(yǔ)言通過(guò)系統(tǒng)的線程來(lái)多路派遣這些函數(shù)的執(zhí)行,使得每個(gè)用go關(guān)鍵字執(zhí)行的函數(shù)可以運(yùn)行成為一個(gè)單位協(xié)程。當(dāng)一個(gè)協(xié)程阻塞的時(shí)候,調(diào)度器就會(huì)自動(dòng)把其他協(xié)程安排到另外的線程中去執(zhí)行,從而實(shí)現(xiàn)了程序無(wú)等待并行化運(yùn)行。而且調(diào)度的開(kāi)銷非常小,這使得我們能夠創(chuàng)建大量的goroutine,從而可以很輕松地編寫高并發(fā)程序。

Go語(yǔ)言實(shí)現(xiàn)了CSP(通信順序進(jìn)程,Communicating Sequential Process)模型來(lái)作為goroutine間的推薦通信方式。在CSP模型中,一個(gè)并發(fā)系統(tǒng)由若干并行運(yùn)行的順序進(jìn)程組成,每個(gè)進(jìn)程不能對(duì)其他進(jìn)程的變量賦值。進(jìn)程之間只能通過(guò)一對(duì)通信原語(yǔ)實(shí)現(xiàn)協(xié)作。Go語(yǔ)言用channel(通道) 這個(gè)概念來(lái)輕巧地實(shí)現(xiàn)了CSP模型。channel的使用方式比較接近Unix系統(tǒng)中的管道(pipe)概念,可以方便地進(jìn)行跨goroutine的通信。

另外,由于一個(gè)進(jìn)程內(nèi)創(chuàng)建的所有g(shù)oroutine運(yùn)行在同一個(gè)內(nèi)存地址空間中,因此如果不同的goroutine不得不去訪問(wèn)共享的內(nèi)存變量,訪問(wèn)前應(yīng)該先獲取相應(yīng)的讀寫鎖。Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的sync包提供了完備的讀寫鎖功能。

反射

Go語(yǔ)言的反射實(shí)現(xiàn)了反射的大部分功能,但沒(méi)有像Java語(yǔ)言那樣內(nèi)置類型工廠,所以無(wú)法做到像Java那樣通過(guò)類型字符串創(chuàng)建對(duì)象實(shí)例。

反射最常見(jiàn)的使用場(chǎng)景是做對(duì)象的序列化(serialization)。 例如,Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)的encoding/json、encoding/xml、encoding/gob、encoding/binary等包就大量依賴于反射功能來(lái)實(shí)現(xiàn)。

go語(yǔ)言發(fā)射的簡(jiǎn)單示例:

package main

import (
    "fmt"
    "reflect"
)

type Bird struct {
    Name           string
    LifeExpectance int
}

func (b *Bird) Fly() {
    fmt.Println("I am flying...")
}
func main() {
    sparrow := &Bird{"Sparrow", 3}
    s := reflect.ValueOf(sparrow).Elem()
    typeOfT := s.Type()
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d: %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(),
            f.Interface())
    }
}

輸出結(jié)果:
0: Name string = Sparrow
1: LifeExpectance int = 3

語(yǔ)言交互性

Go語(yǔ)言為了方便的重用現(xiàn)有的C模塊,提供了Cgo。
在Go代碼中,可以按Cgo的特定語(yǔ)法混合編寫C語(yǔ)言代碼,然后Cgo工具可以將這些混合的C代碼提取并生成對(duì)于C功能的調(diào)用包裝代碼。

Go語(yǔ)言使用C模塊的簡(jiǎn)單示例:

package main
/*
#include <stdio.h> 
*/
import "C"
import "unsafe"
func main() {
    cstr := C.CString("Hello, world") 
    C.puts(cstr) 
    C.free(unsafe.Pointer(cstr))
}

語(yǔ)言結(jié)構(gòu)

基礎(chǔ)組成

  • 包聲明
  • 引入包
  • 函數(shù)
  • 變量
  • 語(yǔ)句 & 表達(dá)式
  • 注釋

簡(jiǎn)單示例

學(xué)習(xí)一門語(yǔ)言,從輸出“Hello,world!”開(kāi)始。

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")/* 輸出Hello, World! */
}
  • package main定義了包名。必須在源文件中非注釋的第一行指明這個(gè)文件屬于哪個(gè)包。package main表示一個(gè)可獨(dú)立執(zhí)行的程序,每個(gè) Go 應(yīng)用程序都包含一個(gè)名為 main 的包。
  • import "fmt" 告訴 Go 編譯器這個(gè)程序需要使用fmt包中的內(nèi)容。
  • func main() 是程序開(kāi)始執(zhí)行的函數(shù)。main函數(shù)是每一個(gè)可執(zhí)行程序所必須包含的。
  • /*...*/ 是多行注釋。你也可以使用單行注釋//
  • fmt.Println("Hello, World!"),使用fmt包中的輸出函數(shù)Println將“Hello, World!”字符串輸出到控制臺(tái)。

執(zhí)行g(shù)o程序

  1. 在你的機(jī)器上,安裝go語(yǔ)言開(kāi)發(fā)環(huán)境。
  2. 在你設(shè)置的工作目錄下,新建hello.go文件。
  3. 將上面示例代碼復(fù)制到hello.go文件中。
  4. 進(jìn)入hello.go所在目錄,執(zhí)行g(shù)o run hello.go命令行
$ go run hello.go
Hello, World!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容