最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

go語言基礎(chǔ)學(xué)習(xí)

2023-07-20 19:52 作者:青陽小棧  | 我要投稿

## Go 語言背景

Go 是一個開源的編程語言,它能讓構(gòu)造簡單、可靠且高效的軟件變得容易。


Go 是從2007年末由 Robert Griesemer, Rob Pike, Ken Thompson 主持開發(fā),后來還加入了 Ian Lance Taylor, Russ Cox 等人,并最終于2009年11月開源,在2012年早些時候發(fā)布了 Go 1穩(wěn)定版本?,F(xiàn)在 Go 的開發(fā)已經(jīng)是完全開放的,并且擁有一個活躍的社區(qū)。


### go 語言特色

-? ?簡潔、快速、安全

-? ?并行、有趣、開源

-? ?內(nèi)存管理、數(shù)組安全、編譯迅速


### go 語言環(huán)境安裝:

Go 語言支持以下系統(tǒng):


-? ?Linux

-? ?FreeBSD

-? ?Mac OS X(也稱為 Darwin)

-? ?Windows


安裝包下載地址為:[https://go.dev/dl/](https://go.dev/dl/)。


如果打不開可以使用這個地址:[https://golang.google.cn/dl/](https://golang.google.cn/dl/)。


#### windows 下安裝:

Windows 下可以使用 .msi 后綴(在下載列表中可以找到該文件,如 go1.4.2.windows-amd64.msi)的安裝包來安裝。


默認(rèn)情況下 **.msi** 文件會安裝在 **c:\Go** 目錄下。你可以將 **c:\Go\bin** 目錄添加到 **Path** 環(huán)境變量中。添加后你需要重啟命令窗口才能生效。


#### linux 類系統(tǒng)安裝:

以下介紹了在 UNIX/Linux/Mac OS X, 和 FreeBSD 系統(tǒng)下使用源碼安裝方法:


1、下載二進制包:go1.4.linux-amd64.tar.gz。


2、將下載的二進制包解壓至 /usr/local目錄。


tar -C /usr/local -xzf go1.4.linux-amd64.tar.gz


3、將 /usr/local/go/bin 目錄添加至 PATH 環(huán)境變量:


export PATH=$PATH:/usr/local/go/bin


以上只能暫時添加 PATH,關(guān)閉終端下次再登錄就沒有了。


我們可以編輯 ~/.bash_profile 或者 /etc/profile,并將以下命令添加該文件的末尾,這樣就永久生效了:


export PATH=$PATH:/usr/local/go/bin


添加后需要執(zhí)行:


source ~/.bash_profile

source /etc/profile


> **注意:**MAC 系統(tǒng)下你可以使用 **.pkg** 結(jié)尾的安裝包直接雙擊來完成安裝,安裝目錄在 **/usr/local/go/** 下。


## go 語言程序編寫

### Go 的語言結(jié)構(gòu):


Go 的語言基礎(chǔ)組成由以下幾個部分:

1. 包聲明;

2. 引入包;

3. 函數(shù);

4. 變量;

5. 語句&表達(dá)式;

6. 注釋



第一個 hello. go

```

package main??

??

import "fmt"??

??

func main() {??

/* 這是我的第一個簡單的程序 */

? ? fmt.Println("Hello, World!")??

}

```

1.? 第一行代碼 _package main_ 定義了包名。你必須在源文件中非注釋的第一行指明這個文件屬于哪個包,如:package main。package main 表示一個可獨立執(zhí)行的程序,每個 Go 應(yīng)用程序都包含一個名為 main 的包。

? ??

2.? 下一行 _import "fmt"_ 告訴 Go 編譯器這個程序需要使用 fmt 包(的函數(shù),或其他元素),fmt 包實現(xiàn)了格式化 IO(輸入/輸出)的函數(shù)。

? ??

3.? 下一行 _func main()_ 是程序開始執(zhí)行的函數(shù)。main 函數(shù)是每一個可執(zhí)行程序所必須包含的,一般來說都是在啟動后第一個執(zhí)行的函數(shù)(如果有 init() 函數(shù)則會先執(zhí)行該函數(shù))。

? ??

4.? 下一行 /*...*/ 是注釋,在程序執(zhí)行時將被忽略。單行注釋是最常見的注釋形式,你可以在任何地方使用以 // 開頭的單行注釋。多行注釋也叫塊注釋,均已以 /* 開頭,并以 */ 結(jié)尾,且不可以嵌套使用,多行注釋一般用于包的文檔描述或注釋成塊的代碼片段。

? ??

5.? 下一行 _fmt.Println(...)_ 可以將字符串輸出到控制臺,并在最后自動增加換行字符 \n。??

? ? 使用 fmt.Print("hello, world\n") 可以得到相同的結(jié)果。??

? ? Print 和 Println 這兩個函數(shù)也支持使用變量,如:fmt.Println(arr)。如果沒有特別指定,它們會以默認(rèn)的打印格式將變量 arr 輸出到控制臺。

? ??

6.? 當(dāng)標(biāo)識符(包括常量、變量、類型、函數(shù)名、結(jié)構(gòu)字段等等)以一個大寫字母開頭,如:Group1,那么使用這種形式的標(biāo)識符的對象就可以被外部包的代碼所使用(客戶端程序需要先導(dǎo)入這個包),這被稱為導(dǎo)出(像面向?qū)ο笳Z言中的 public);標(biāo)識符如果以小寫字母開頭,則對包外是不可見的,但是他們在整個包的內(nèi)部是可見并且可用的(像面向?qū)ο笳Z言中的 protected )。


運行代碼:

go run hello.go

生成二進制文件:

go build hello.go


注意:

1. 需要注意的是 { 不能單獨放在一行。

2.? ? 文件名與包名沒有直接關(guān)系,不一定要將文件名與包名定成同一個。

3.? ? 文件夾名與包名沒有直接關(guān)系,并非需要一致。

4.? ? 同一個文件夾下的文件只能有一個包名,否則編譯報錯。


### go 的基礎(chǔ)語法


#### 行分隔符:

go 跟 python 一樣不使用;作為行分隔符。

如果時多個語句寫在同一行那就需要;作為分隔。


#### 注釋:

go 的注釋和其他語言一樣。


#### 標(biāo)識符:

go 的標(biāo)識符也和其他語言差不多。

標(biāo)識符用來命名變量、類型等程序?qū)嶓w。一個標(biāo)識符實際上就是一個或是多個字母(A~Z 和 a~z)數(shù)字(0~9)、下劃線_組成的序列,但是第一個字符必須是字母或下劃線而不能是數(shù)字。


#### 字符串:

go 的字符串連接和 python 的一樣。

Go 語言的字符串連接可以通過 + 實現(xiàn):


```

fmt.Println("Google" + "Runoob")

```


#### 關(guān)鍵字:

25 個關(guān)鍵字和保留字:

![[Pasted image 20230720112138.png]]

36 個預(yù)定義標(biāo)識符:

![[Pasted image 20230720112214.png]]


#### go 語言中的空格:

跟其他語言差不多。


#### 格式化字符串:

go 中使用 fmt. Sprintf 或 fmt. Printf 格式化字符串并復(fù)制給新串:

Sprintf 根據(jù)格式化參數(shù)生成格式化的字符串并返回該字符串。

Printf 根據(jù)格式化參數(shù)生成格式化的字符串并寫入標(biāo)準(zhǔn)輸出。


```

?var stockcode=123??

? ? var enddate="2020-12-31"??

? ? var url="Code=%d&endDate=%s"??

? ? var target_url=fmt.Sprintf(url,stockcode,enddate)??

? ? fmt.Println(target_url)

? ??

var stockcode=123??

? ? var enddate="2020-12-31"??

? ? var url="Code=%d&endDate=%s"??

? ? fmt.Printf(url,stockcode,enddate)

? ?輸出結(jié)果為:Code=123&endDate=2020-12-31

```


### go 語言數(shù)據(jù)類型


在 go 中,數(shù)據(jù)類型用于聲明函數(shù)和變量。

數(shù)據(jù)類型的出現(xiàn)是為了把數(shù)據(jù)分成所需內(nèi)存大小不同的數(shù)據(jù),需要用大數(shù)據(jù)的時候申請大內(nèi)存,不需要可以申請小內(nèi)存,提高內(nèi)容利用率。


按類別 go 有下面幾種數(shù)據(jù)類型:

1、布爾型

布爾型的值只可以是 true 或者 false。 var b bool=true

2、數(shù)字類型

整形 int 浮點型 float32 和 float 64,go 支持整形和浮點型數(shù)字,并支持復(fù)數(shù),位的運算采用補碼。

3、字符串類型

go 的字符串由單個字節(jié)拼接,使用 utf-8 編碼標(biāo)識的 unicode 文本。

4、派生類型

1. 指針類型

2. 數(shù)組類型

3. 結(jié)構(gòu)化類型(struct)

4. channel 類型

5. 函數(shù)類型

6. 切片類型

7. 接口類型

8. map 類型


#### 數(shù)字類型:


##### 整型:

uint 8:無符號 8 位整型(2 到 255)

uint 16:無符號 16 位整型(0 到 65535)

uint 32:無符號 32 位整型(0 到 4294967295)

int 8:有符號 8 位整型(-127 到 127)

int 16:有符號 16 位整型(-32768 到 32767)

int 32:有符號 32 位整型(-2147483648 到 2147483647)

int 64:有符號 64 位整型 (-9223372036854775808 到 9223372036854775807)


##### 浮點型:


float 32:IEEE-754 標(biāo)準(zhǔn) 32 位浮點型整數(shù);

float 64:IEEE-754 標(biāo)準(zhǔn) 64 位浮點數(shù);

complex:32 位實數(shù)和虛數(shù);

complex 128:64 位實數(shù)和虛數(shù);


##### 其他數(shù)字類型:


byte:類似 uint8;

rune:類似 int32;

uint:32 位或 64 位;

int:和 uint 一樣大??;

uintptr:無符號整型用于存放一個指針;


注意:

在 go1.9 版本后,無需定義 int、float 32、float 64,系統(tǒng)會自動識別,類似 python 的處理方式。


### go 語言變量

go 語言變量名由字母、數(shù)字、下劃線組成,其中首個字符不能為數(shù)字。

聲明變量一般使用 var 關(guān)鍵字,可以一次聲明多個變量。


變量聲明:

1、智能變量類型,如果沒有初始化,則變量默認(rèn)為零值(沒有做初始化時系統(tǒng)默認(rèn)設(shè)置的值)。

對于零值:

- 數(shù)值類型(包括 complex64/128)為 **0**

- 布爾類型為 **false**

- 字符串為 **""**(空字符串)

- 以下幾種類型為 **nil**:

- var a *int

- var a []int

- var a map[string] int

- var a chan int

- var a func(string) int

- var a error // error 是接口


2、根據(jù)值自行判定變量類型


3、如果變量已經(jīng)使用 var 聲明過了,再使用 := 聲明變量,就產(chǎn)生編譯錯誤。


### go 語言常量


常量是一個簡單值的標(biāo)識符,在程序運行時,不會被修改的量。常量中的數(shù)據(jù)類型只可以時布爾型、數(shù)字型(整數(shù)型、浮點數(shù)型和復(fù)數(shù))和字符串型。

> const identifier [type] = value

-? ?顯式類型定義: `const b string = "abc"`??

-? ?隱式類型定義: `const b = "abc"`



**iota**

iota,特殊常量,可以認(rèn)為是一個可以被編譯器修改的常量。


iota 在 const 關(guān)鍵字出現(xiàn)時將被重置為 0(const 內(nèi)部的第一行之前),const 中每新增一行常量聲明將使 iota 計數(shù)一次(iota 可理解為 const 語句塊中的行索引)。


### go 語言運算符


go 語言內(nèi)置,和其他語言基本一致。

-? ?算術(shù)運算符

-? ?關(guān)系運算符

-? ?邏輯運算符

-? ?位運算符

-? ?賦值運算符

-? ?其他運算符


算術(shù)運算符:

![[Pasted image 20230720145941.png]]


關(guān)系運算符:

![[Pasted image 20230720150018.png]]


邏輯運算符:

![[Pasted image 20230720150053.png]]


位運算符:

![[Pasted image 20230720150437.png]]


![[Pasted image 20230720150451.png]]


賦值運算符:

![[Pasted image 20230720150517.png]]


其他運算符:

![[Pasted image 20230720150550.png]]


運算符優(yōu)先級:

![[Pasted image 20230720150658.png]]


注意:

go 的自增自檢智能作為表達(dá)式使用,不能用于賦值語句,不然會編譯出錯。


### go 語言條件語句:

![[Pasted image 20230720151010.png]]


switch 語句:


```

switch var1 {

? ? case val1:

? ? ? ? ...

? ? case val2:

? ? ? ? ...

? ? default:

? ? ? ? ...

}

```


select 語句:

```

Select {

? Case <- channel 1:

? ? // 執(zhí)行的代碼

? Case value := <- channel 2:

? ? // 執(zhí)行的代碼

? Case channel 3 <- value:

? ? // 執(zhí)行的代碼


? ? // 你可以定義任意數(shù)量的 case


? Default:

? ? // 所有通道都沒有準(zhǔn)備好,執(zhí)行的代碼

}

```


### go 語言循環(huán)語句

#### for 循環(huán):

跟 c 語言中的一樣


```

For init; condition; post { }

```


-? ?init: 一般為賦值表達(dá)式,給控制變量賦初值;

-? ?condition: 關(guān)系表達(dá)式或邏輯表達(dá)式,循環(huán)控制條件;

-? ?post: 一般為賦值表達(dá)式,給控制變量增量或減量。


多層嵌套:


```

for [condition |? ( init; condition; increment ) | Range]??

{??

? ?for [condition |? ( init; condition; increment ) | Range]??

? ?{??

? ? ? statement(s);??

? ?}??

? ?statement(s);??

}

```


#### 循環(huán)中的 break:

在 Go 語言中,break 語句用于終止當(dāng)前循環(huán)或者 switch 語句的執(zhí)行,并跳出該循環(huán)或者 switch 語句的代碼塊。


break 語句可以用于以下幾個方面:。


-? ?用于循環(huán)語句中跳出循環(huán),并開始執(zhí)行循環(huán)之后的語句。

-? ?break 在 switch 語句中在執(zhí)行一條 case 后跳出語句的作用。

-? ?break 可應(yīng)用在 select 語句中。

-? ?在多重循環(huán)中,可以用標(biāo)號 label 標(biāo)出想 break 的循環(huán)。



```

Package main


Import "fmt"


Func main () {

? ? For i := 0; i < 10; i++ {

? ? ? ? If i == 5 {

? ? ? ? ? ? Break // 當(dāng) i 等于 5 時跳出循環(huán)

? ? ? ? }

? ? ? ? Fmt.Println (i)

? ? }

}

```


#### continue 語句:


Go 語言的 continue 語句有點像 break 語句。但是 continue 不是跳出循環(huán),而是跳過當(dāng)前循環(huán)執(zhí)行下一次循環(huán)語句。


for 循環(huán)中,執(zhí)行 continue 語句會觸發(fā) for 增量語句的執(zhí)行。


在多重循環(huán)中,可以用標(biāo)號 label 標(biāo)出想 continue 的循環(huán)。


#### goto 語句:


Go 語言的 goto 語句可以無條件地轉(zhuǎn)移到過程中指定的行。


goto 語句通常與條件語句配合使用??捎脕韺崿F(xiàn)條件轉(zhuǎn)移, 構(gòu)成循環(huán),跳出循環(huán)體等功能。


但是,在結(jié)構(gòu)化程序設(shè)計中一般不主張使用 goto 語句, 以免造成程序流程的混亂,使理解和調(diào)試程序都產(chǎn)生困難。



```

goto label;

..

.

label: statement;

```



```

Package main


Import "fmt"


Func main () {

? ?/* 定義局部變量 */

? ?Var a int = 10


? ?/* 循環(huán) */

? ?LOOP: for a < 20 {

? ? ? If a == 15 {

? ? ? ? ?/* 跳過迭代 */

? ? ? ? ?A = a + 1

? ? ? ? ?Goto LOOP

? ? ? }

? ? ? Fmt.Printf ("a 的值為 : %d\n", a)

? ? ? A++? ? ?

? ?}??

}

```


### go 語言函數(shù):


函數(shù)定義:


```

func function_name( [parameter list] ) [return_types] {

? ?函數(shù)體

}

```


函數(shù)定義解析:


-? ?func:函數(shù)由 func 開始聲明

-? ?function_name:函數(shù)名稱,參數(shù)列表和返回值類型構(gòu)成了函數(shù)簽名。

-? ?parameter list:參數(shù)列表,參數(shù)就像一個占位符,當(dāng)函數(shù)被調(diào)用時,你可以將值傳遞給參數(shù),這個值被稱為實際參數(shù)。參數(shù)列表指定的是參數(shù)類型、順序、及參數(shù)個數(shù)。參數(shù)是可選的,也就是說函數(shù)也可以不包含參數(shù)。

-? ?return_types:返回類型,函數(shù)返回一列值。return_types 是該列值的數(shù)據(jù)類型。有些功能不需要返回值,這種情況下 return_types 不是必須的。

-? ?函數(shù)體:函數(shù)定義的代碼集合。



```

/* 函數(shù)返回兩個數(shù)的最大值 */??

func max(num1, num2 int) int {??

? ?/* 聲明局部變量 */??

? ?var result int??

??

? ?if (num1 > num2) {??

? ? ? result = num1??

? ?} else {??

? ? ? result = num2??

? ?}??

? ?return result??

}

```


函數(shù)里面也要注意變量操作,在函數(shù)里面改了變量,主函數(shù)也會受影響。

![[Pasted image 20230720152721.png]]


### go 語言變量作用域


-? ?函數(shù)內(nèi)定義的變量稱為局部變量

-? ?函數(shù)外定義的變量稱為全局變量

-? ?函數(shù)定義中的變量稱為形式參數(shù)


### go 語言數(shù)組



```

var arrayName [size]dataType

```


初始化數(shù)組:


```

var numbers [5]int

var numbers = [5]int{1, 2, 3, 4, 5}

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

```


如果長度不確定,可以使用... 來代替數(shù)據(jù)的長度,編譯器會根據(jù)元素個數(shù)自行推斷數(shù)組的長度。


```

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

```


### go 語言指針

go 語言指針和 c 語言中的類似



### go 語言結(jié)構(gòu)體


結(jié)構(gòu)體有點類似類的概念。


定義結(jié)構(gòu)體

結(jié)構(gòu)體定義需要使用 type 和 struct 語句。struct 語句定義一個新的數(shù)據(jù)類型,結(jié)構(gòu)體中有一個或多個成員。type 語句設(shè)定了結(jié)構(gòu)體的名稱。結(jié)構(gòu)體的格式如下:


```

Type struct_variable_type struct {

? ?Member definition

? ?Member definition

? ?...

? ?Member definition

}

```


```

Variable_name := structure_variable_type {value 1, value 2... Valuen}

Variable_name := structure_variable_type { key 1: value 1, key 2: value 2..., keyn: valuen}

```


### go 語言切片


切片時數(shù)組的衍生抽象。

go 數(shù)組長度不可變,于是切片來實現(xiàn)一種動態(tài)數(shù)組的功能。


**定義切片:**

```

var identifier []type

```


```

Var slice 1 []type = make ([]type, len)

也可以簡寫為

Slice 1 := make ([]type, len)

也可以指定容量,capacity 是可選參數(shù)

Make ([]T, length, capacity)

```


**切片初始化:**



```

s :=[] int {1,2,3 }

直接初始化切片,[] 表示是切片類型,**{1,2,3}** 初始化值依次是 1,2,3,其 **cap=len=3**。

s := arr[:]

初始化切片 **s**,是數(shù)組 arr 的引用。

s := arr[startIndex:endIndex]

將 arr 中從下標(biāo) startIndex 到 endIndex-1 下的元素創(chuàng)建為一個新的切片。

s := arr[startIndex:]

默認(rèn) endIndex 時將表示一直到arr的最后一個元素。

s := arr[:endIndex]

默認(rèn) startIndex 時將表示從 arr 的第一個元素開始

s1 := s[startIndex: endIndex]

通過切片 s 初始化切片 s1。

s :=make([]int,len,cap)

通過 make()函數(shù)初始化

```


len() 方法獲取長度

cap() 可以測量切片最長可以達(dá)到多少

一個切片在未初始化之前默認(rèn)為 nil,長度為 0

切片擴容方法:從拷貝切片的 copy 方法和向切片追加新元素的 append 方法


### go 語言范圍(range)


go 里面的 range 和 python 里面的 range 類似。


```

for key, value := range oldMap {

? ? newMap[key] = value

}

```


如果只想讀 key,也可以


```

for key := range oldMap

for key, _ := range oldMap

```

如果只想讀 value


```

for _, value := range oldMap

```


### go 語言 map(集合)

go 中的 map 類似 python 里面的 tupple 元組。


map 是一種無序的鍵值對的集合,可以通過 key 來快速檢索數(shù)據(jù),key 類似于索引,指向數(shù)據(jù)的值。

map 是一種集合,可以像迭代數(shù)組那樣進行迭代,但它是無序的,遍歷 map 時返回的鍵值對的順序不確定。

在獲取 map 的值時,如果鍵不存在,則反饋該類型的零值,如 int 類型的零值是 0,string 類型的零值是""。


**定義 map:**


```

/* 使用 make 函數(shù) */

Map_variable := make (map[KeyType]ValueType, initialCapacity)

```


```

// 創(chuàng)建一個空的 Map

M := make (map[string]int)


// 創(chuàng)建一個初始容量為 10 的 Map

M := make (map[string]int, 10)

```


```

// 使用字面量創(chuàng)建 Map

M := map[string]int{

? ? "apple": 1,

? ? "banana": 2,

? ? "orange": 3,

}


獲取元素:

// 獲取鍵值對

V 1 := m["apple"]

V 2, ok := m["pear"]? // 如果鍵不存在,ok 的值為 false,v 2 的值為該類型的零值


修改元素:

// 修改鍵值對

M["apple"] = 5


獲取 map 的長度:

// 獲取 Map 的長度

Len := len (m)


遍歷 map:

// 遍歷 Map

For k, v := range m {

? ? Fmt.Printf ("key=%s, value=%d\n", k, v)

}


刪除元素:

// 刪除鍵值對

Delete (m, "banana")


```


### go 語言遞歸函數(shù)


go 的遞歸函數(shù)跟其他語言類似。


### go 語言類型轉(zhuǎn)換

整體上跟其他語言類似。


```

Type_name (expression)

type_name 為類型,expression 為表達(dá)式。

```


**數(shù)值類型轉(zhuǎn)換:**


```

Var a int = 10

Var b float 64 = float 64 (a)

```


**字符串類型轉(zhuǎn)換:**


```

Var str string = "10"

Var num int

Num, _ = strconv.Atoi (str)

以上代碼將字符串變量 str 轉(zhuǎn)換為整型變量 num。


注意,strconv.Atoi 函數(shù)返回兩個值,第一個是轉(zhuǎn)換后的整型值,第二個是可能發(fā)生的錯誤,我們可以使用空白標(biāo)識符 _ 來忽略這個錯誤

```

**接口類型轉(zhuǎn)換:**

接口類型轉(zhuǎn)換有兩種情況**:類型斷言**和**類型轉(zhuǎn)換**。

類型斷言用于將接口類型轉(zhuǎn)換為指定類型,其語法為:


```

Value. (type)?

或者?

Value. (T)

```


其中 value 是接口類型的變量,type 或 T 是要轉(zhuǎn)換成的類型。

如果類型斷言成功,它將返回轉(zhuǎn)換后的值和一個布爾值,表示轉(zhuǎn)換是否成功。


```

Package main


Import "fmt"


Func main () {

? ? Var i interface{} = "Hello, World"

? ? str, ok := i.(string)

? ? If ok {

? ? ? ? Fmt.Printf ("'%s' is a string\n", str)

? ? } else {

? ? ? ? Fmt.Println ("conversion failed")

? ? }

}


```


以上實例中,我們定義了一個接口類型變量 i,并將它賦值為字符串 "Hello, World"。然后,我們使用類型斷言將 i 轉(zhuǎn)換為字符串類型,并將轉(zhuǎn)換后的值賦值給變量 str。最后,我們使用 ok 變量檢查類型轉(zhuǎn)換是否成功,如果成功,我們打印轉(zhuǎn)換后的字符串;否則,我們打印轉(zhuǎn)換失敗的消息。


類型轉(zhuǎn)換用于將一個接口類型的值轉(zhuǎn)換為另一個接口類型,其語法為:


```

T(value)

```


T 是目標(biāo)接口類型,value 是要轉(zhuǎn)換的值。

在類型轉(zhuǎn)換中,我們必須保證要轉(zhuǎn)換的值和目標(biāo)接口類型之間是兼容的,否則編譯器會報錯。


```

Package main


Import "fmt"


Type Writer interface {

? ? Write ([]byte) (int, error)

}


Type StringWriter struct {

? ? Str string

}


Func (sw *StringWriter) Write (data []byte) (int, error) {

? ? Sw. Str += string (data)

? ? Return len (data), nil

}


Func main () {

? ? Var w Writer = &StringWriter{}

? ? sw := w.(*StringWriter)

? ? Sw. Str = "Hello, World"

? ? Fmt.Println (sw. Str)

}

```

以上實例中,我們定義了一個 Writer 接口和一個實現(xiàn)了該接口的結(jié)構(gòu)體 StringWriter。然后,我們將 StringWriter 類型的指針賦值給 Writer 接口類型的變量 w。接著,我們使用類型轉(zhuǎn)換將 w 轉(zhuǎn)換為 StringWriter 類型,并將轉(zhuǎn)換后的值賦值給變量 sw。最后,我們使用 sw 訪問 StringWriter 結(jié)構(gòu)體中的字段 str,并打印出它的值。


### go 語言接口


接口真的就感覺像類的概念。


Go 語言提供了另外一種數(shù)據(jù)類型即接口,它把所有的具有共性的方法定義在一起,任何其他類型只要實現(xiàn)了這些方法就是實現(xiàn)了這個接口。


接口可以讓我們將不同的類型綁定到一組公共的方法上,從而實現(xiàn)多態(tài)和靈活的設(shè)計。


Go 語言中的接口是隱式實現(xiàn)的,也就是說,如果一個類型實現(xiàn)了一個接口定義的所有方法,那么它就自動地實現(xiàn)了該接口。因此,我們可以通過將接口作為參數(shù)來實現(xiàn)對不同類型的調(diào)用,從而實現(xiàn)多態(tài)。


```

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()


}

```

在上面的例子中,我們定義了一個接口 **Phone**,接口里面有一個方法 call()。然后我們在 **main** 函數(shù)里面定義了一個 **Phone** 類型變量,并分別為之賦值為 **NokiaPhone** 和 **IPhone**。然后調(diào)用 call() 方法,輸出結(jié)果如下:


### go 錯誤處理


go 語言有一個內(nèi)置的簡單錯誤處理機制。

error 類型是一個接口類型:


```

Type error interface {

? ? Error () string

}


func Sqrt(f float64) (float64, error) {

? ? if f < 0 {

? ? ? ? return 0, errors.New("math: square root of negative number")

? ? }

? ? // 實現(xiàn)

}

```


### go 并發(fā)


go 支持并發(fā),只需要通過 goroutine 即可。

goroutine 是輕量級線程,它的調(diào)度是 go 運行時進行管理的。


goruntine 語法格式:


```

go 函數(shù)名( 參數(shù)列表 )

go f(x, y, z)

```

f(x, y, z),聲明之后,每一個調(diào)用都是一個新的線程,但是所有線程都是共享一個地址空間,這里需要注意。

P

```

ackage main


Import (

? ? ? ? "fmt"

? ? ? ? "time"

)


Func say (s string) {

? ? ? ? For i := 0; i < 5; i++ {

? ? ? ? ? ? ? ? Time.Sleep (100 * time. Millisecond)

? ? ? ? ? ? ? ? Fmt.Println (s)

? ? ? ? }

}


Func main () {

? ? ? ? Go say ("world")

? ? ? ? Say ("hello")

}

```


**通道(channel)**


通道是用來傳遞數(shù)據(jù)的一個數(shù)據(jù)結(jié)構(gòu),一個通道相當(dāng)于一個先進先出的隊列。

通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊。操作符 `<-` 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。


```

ch <- v? ? // 把 v 發(fā)送到通道 ch

v := <-ch? // 從 ch 接收數(shù)據(jù)

? ? ? ? ? ?// 并把值賦給 v

```


聲明一個通道很簡單,我們使用chan關(guān)鍵字即可,通道在使用前必須先創(chuàng)建:


```

ch := make(chan int)


```


單向通道:


```

Var WriteChan = make (chan<- interface{}, 1) // 只能發(fā)送不能接收的通道

Var ReadChan = make (<-chan interface{}, 1) // 只能接收不能發(fā)送的通道


```



**注意**:默認(rèn)情況下,通道是不帶緩沖區(qū)的。發(fā)送端發(fā)送數(shù)據(jù),同時必須有接收端相應(yīng)的接收數(shù)據(jù)。


**通道緩沖區(qū):**



```

Ch 1 := make (chan string, 3)

-? ?`chan` 是表示通道類型的關(guān)鍵字

-? ?`string` 表示該通道類型的元素類型

-? ?`3` 表示該通道的容量為 3,最多可以緩存 3 個元素值。

```

帶緩沖區(qū)的通道允許發(fā)送端的數(shù)據(jù)發(fā)送和接收端的數(shù)據(jù)獲取處于異步狀態(tài),就是說發(fā)送端發(fā)送的數(shù)據(jù)可以放在緩沖區(qū)里面,可以等待接收端去獲取數(shù)據(jù),而不是立刻需要接收端去獲取數(shù)據(jù)。


不過由于緩沖區(qū)的大小是有限的,所以還是必須有接收端來接收數(shù)據(jù)的,否則緩沖區(qū)一滿,數(shù)據(jù)發(fā)送端就無法再發(fā)送數(shù)據(jù)了。


**注意**:如果通道不帶緩沖,發(fā)送方會阻塞直到接收方從通道中接收了值。如果通道帶緩沖,發(fā)送方則會阻塞直到發(fā)送的值被拷貝到緩沖區(qū)內(nèi);如果緩沖區(qū)已滿,則意味著需要等待直到某個接收方獲取到一個值。接收方在有值可以接收之前會一直阻塞。


**非緩沖通道:**

非緩沖通道是容量為0的通道,不能緩存數(shù)據(jù)。

非緩沖通道的數(shù)據(jù)傳遞是同步的,發(fā)送操作或者接收操作在執(zhí)行后就會阻塞,需要對應(yīng)的接收操作或者發(fā)送操作執(zhí)行才會繼續(xù)傳遞。由此可以看出緩沖通道使用的是異步方式進行數(shù)據(jù)傳遞。


```

Package main


Import (

? ? "fmt"

)


Func main () {

? ? Str 1 := []string{"hello","world", "!"}

Ch 1 := make (chan string, 0)


? ? go func() {

? ? ? ? for _, str := range str1 {

? ? ? ? ? ? ch1 <- str

? ? ? ? }

? ? }()


for i := 0; i < len(str1); i++ {

elem := <- ch1

fmt.Println(elem)

}


}

```


**通道關(guān)閉:**

可以使用close()方法來關(guān)閉通道,通道關(guān)閉后,不能再對通道進行發(fā)送操作,可以進行接收操作。

如果通道關(guān)閉時,里面還有元素,進行接收操作時,返回的通道關(guān)閉標(biāo)志仍然為 true,由于通道的這種特性,可以讓發(fā)送方來關(guān)閉通道。


```

Package main


Import (

? ? "fmt"

)


Func main () {

? ? Str 1 := []string{"hello","world", "!"}

Ch 1 := make (chan string, 0)


? ? go func() {

? ? ? ? for _, str := range str1 {

? ? ? ? ? ? ch1 <- str

? ? ? ? }

? ? ? ? close(ch1)

? ? }()


for i := 0; i < len(str1); i++ {

elem := <- ch1

fmt.Println(elem)

}


}


```



go語言基礎(chǔ)學(xué)習(xí)的評論 (共 條)

分享到微博請遵守國家法律
法库县| 察隅县| 永安市| 沙河市| 清镇市| 米林县| 天峨县| 勐海县| 通化县| 武平县| 台州市| 长垣县| 连州市| 那曲县| 曲阳县| 锦屏县| 黄梅县| 桂平市| 南昌市| 合肥市| 新兴县| 漳浦县| 安福县| 盐城市| 安图县| 伽师县| 红原县| 巨野县| 河间市| 建始县| 辽阳县| 广汉市| 朔州市| 吐鲁番市| 大姚县| 庄浪县| 桂东县| 辉县市| 鄢陵县| 怀安县| 蕲春县|