国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Go語言學(xué)習(xí)筆記(狂神說)

這篇具有很好參考價值的文章主要介紹了Go語言學(xué)習(xí)筆記(狂神說)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

Go語言學(xué)習(xí)筆記(狂神說)

視頻地址:https://www.bilibili.com/video/BV1ae41157o9

1、聊聊Go語言的歷史

聊聊Go語言的歷史-KuangStudy-文章

2、Go語言能做什么

下面列舉的是原生使用Go語言進(jìn)行開發(fā)的部分項目。

Docker

Docker 是一種操作系統(tǒng)層面的虛擬化技術(shù),可以在操作系統(tǒng)和應(yīng)用程序之間進(jìn)行隔離,也可以稱之為容器。Docker 可以在一臺物理服務(wù)器上快速運(yùn)行一個或多個實例。例如,啟動一個 CentOS 操作系統(tǒng),并在其內(nèi)部命令行執(zhí)行指令后結(jié)束,整個過程就像自己在操作系統(tǒng)一樣高效。

項目鏈接:https://github.com/docker/docker

Go語言

Go語言自己的早期源碼使用C語言和匯編語言寫成。從 Go 1.5 版本后,完全使用Go語言自身進(jìn)行編寫。Go語言的源碼對了解Go語言的底層調(diào)度有極大的參考意義,建議希望對Go語言有深入了解的讀者讀一讀。

項目鏈接:https://github.com/golang/go

Kubernetes

Google 公司開發(fā)的構(gòu)建于 Docker 之上的容器調(diào)度服務(wù),用戶可以通過 Kubernetes 集群進(jìn)行云端容器集群管理。系統(tǒng)會自動選取合適的工作節(jié)點(diǎn)來執(zhí)行具體的容器集群調(diào)度處理工作。其核心概念是 Container Pod(容器倉)。

項目鏈接:https://github.com/kubernetes/kubernetes

etcd

一款分布式、可靠的 KV 存儲系統(tǒng),可以快速進(jìn)行云配置。由 CoreOS 開發(fā)并維護(hù)鍵值存儲系統(tǒng),它使用Go語言編寫,并通過 Raft 一致性算法處理日志復(fù)制以保證強(qiáng)一致性。

項目鏈接:https://github.com/coreos/etcd

beego

beego 是一個類似 Python 的 Tornado 框架,采用了 RESTFul 的設(shè)計思路,使用Go語言編寫的一個極輕量級、高可伸縮性和高性能的 Web 應(yīng)用框架。

項目鏈接:https://github.com/astaxie/beego

martini

一款快速構(gòu)建模塊化的 Web 應(yīng)用的Go語言框架。

項目鏈接:https://github.com/go-martini/martini

codis

國產(chǎn)的優(yōu)秀分布式 Redis 解決方案??梢詫?codis 理解成為 Web 服務(wù)領(lǐng)域的 Nginx,它實現(xiàn)了對 Redis 的反向代理和負(fù)載均衡。

項目鏈接:https://github.com/CodisLabs/codis

delve

Go語言強(qiáng)大的調(diào)試器,被很多集成環(huán)境和編輯器整合。

項目鏈接:https://github.com/derekparker/delve

哪些大公司在用

Go語言是谷歌在 2009 年發(fā)布的一款編程語言,自面世以來它以高效的開發(fā)效率和完美的運(yùn)行速度迅速風(fēng)靡全球,被譽(yù)為“21 世紀(jì)的C語言”。

現(xiàn)在越來越多的公司開始使用Go語言開發(fā)自己的服務(wù),同時也誕生了很多使用Go語言開發(fā)的服務(wù)和應(yīng)用,比如 Docker、k8s 等,下面我們來看一下,有哪些大公司在使用Go語言。

Google

作為創(chuàng)造了Go語言的 google 公司,當(dāng)然會力挺Go語言了。Google 有很多基于 Go 開發(fā)的開源項目,比如 kubernets,docker,大家可以參考《哪些項目使用Go語言開發(fā)》一節(jié)了解更多的Go語言開源項目。

Facebook

Facebook 也在使用Go語言,為此他們還專門在 Github 上建立了一個開源組織 facebookgo。大家可以通過 https://github.com/facebookgo 訪問查看 facebook 開源的項目,其中最具代表性的就是著名平滑重啟工具 grace。

騰訊

騰訊在 15 年就已經(jīng)做了 Docker 萬臺規(guī)模的實踐。因為騰訊主要的開發(fā)語言是 C/C++ ,所以在使用Go語言方面會方便很多,也有很多優(yōu)勢,不過日積月累的 C/C++ 代碼很難改造,也不敢動,所以主要在新業(yè)務(wù)上嘗試使用 Go。

百度

百度主要在運(yùn)維方面使用到了Go語言,比如百度運(yùn)維的一個 BFE 項目,主要負(fù)責(zé)前端流量的接入,其次就是百度消息通訊系統(tǒng)的服務(wù)器端也使用到了Go語言。

七牛云

七牛云算是國內(nèi)第一家選Go語言做服務(wù)端的公司。早在 2011 年,當(dāng)Go語言的語法還沒完全穩(wěn)定下來的情況下,七牛云就已經(jīng)選擇將 Go 作為存儲服務(wù)端的主體語言。

京東

京東云消息推送系統(tǒng)、云存儲,以及京東商城的列表頁等都是使用Go語言開發(fā)的。

小米

小米對Go語言的支持,在于運(yùn)維監(jiān)控系統(tǒng)的開源,它的官方網(wǎng)址是 http://open-falcon.org/ 此外,小米互娛、小米商城、小米視頻、小米生態(tài)鏈等團(tuán)隊都在使用Go語言。

360

360 對Go語言的使用也不少,比如開源的日志搜索系統(tǒng) Poseidon,大家可以通過.

https://github.com/Qihoo360/poseidon 查看,還有 360 的推送團(tuán)隊也在使用Go語言。

除了上面提到的,還有很多公司開始嘗試使用Go語言,比如美團(tuán)、滴滴、新浪等。

Go語言的強(qiáng)項在于它適合用來開發(fā)網(wǎng)絡(luò)并發(fā)方面的服務(wù),比如消息推送、監(jiān)控、容器等,所以在高并發(fā)的項目上大多數(shù)公司會優(yōu)先選擇 Golang 作為開發(fā)語言。

Go語言代碼清爽

Go語言語法類似于C語言,因此熟悉C語言及其派生語言([C++]、[C#]、Objective-C 等)的人都會迅速熟悉這門語言。

C語言的有些語法會讓代碼可讀性降低甚至發(fā)生歧義。Go語言在C語言的基礎(chǔ)上取其精華,棄其糟粕,將C語言中較為容易發(fā)生錯誤的寫法進(jìn)行調(diào)整,做出相應(yīng)的編譯提示。

去掉循環(huán)冗余括號

Go語言在眾多大師的豐富實戰(zhàn)經(jīng)驗的基礎(chǔ)上誕生,去除了C語言語法中一些冗余、煩瑣的部分。下面的代碼是C語言的數(shù)值循環(huán):

// C語言的for數(shù)值循環(huán)for(int a =0;a<10;a++){// 循環(huán)代碼}

在Go語言中,這樣的循環(huán)變?yōu)椋?/p>

for a :=0; a<10; a++ {// 循環(huán)代碼}

for 兩邊的括號被去掉,int 聲明被簡化為:=,直接通過編譯器右值推導(dǎo)獲得 a 的變量類型并聲明。

去掉表達(dá)式冗余括號

同樣的簡化也可以在判斷語句中體現(xiàn)出來,以下是C語言的判斷語句:

if(表達(dá)式){// 表達(dá)式成立}

在Go語言中,無須添加表達(dá)式括號,代碼如下:

if表達(dá)式{// 表達(dá)式成立}

強(qiáng)制的代碼風(fēng)格

Go語言中,左括號必須緊接著語句不換行。其他樣式的括號將被視為代碼編譯錯誤。這個特性剛開始會使開發(fā)者有一些不習(xí)慣,但隨著對Go語言的不斷熟悉,開發(fā)者就會發(fā)現(xiàn)風(fēng)格統(tǒng)一讓大家在閱讀代碼時把注意力集中到了解決問題上,而不是代碼風(fēng)格上。

同時Go語言也提供了一套格式化工具。一些Go語言的開發(fā)環(huán)境或者編輯器在保存時,都會使用格式化工具對代碼進(jìn)行格式化,讓代碼提交時已經(jīng)是統(tǒng)一格式的代碼。

不再糾結(jié)于 i++ 和 ++i

C語言非常經(jīng)典的考試題為:

int a, b;
a = i++;
b = ++i;

這種題目對于初學(xué)者簡直摸不著頭腦。為什么一個簡單的自增表達(dá)式需要有兩種寫法?

在Go語言中,自增操作符不再是一個操作符,而是一個語句。因此,在Go語言中自增只有一種寫法:

i++

如果寫成前置自增++i,或者賦值后自增a=i++都將導(dǎo)致編譯錯誤。

3、Go語言環(huán)境安裝

下載地址:https://studygolang.com/dl

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

下載完成后一路next即可!

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

接下來去配置環(huán)境變量。Go語言需要一個安裝目錄,還需要一個工作目錄。即GOROOT和GOPATH。

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

在**GOPATH**對應(yīng)的目錄下,需要建三個文件夾。src、pkg、bin。

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

接下來改一下用戶變量:

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

打開cmd進(jìn)行驗證:

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

4、GoLand安裝

如果是學(xué)生的話,可以通過大學(xué)郵箱每次免費(fèi)申請1年的正版軟件

如果是個人學(xué)習(xí)使用,可以通過一些公眾號等自行下載破解~

5、HelloWorld

新建一個Hello.go文件

package main

import "fmt"

func main(){
  fmt.Println("Hello World!")
}

打開當(dāng)前文件夾的cmd

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

用GoLang編寫HelloWorld

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

在Go語言里,命名為main 的包具有特殊的含義。Go語言的編譯程序會試圖把這種名字的包編譯為二進(jìn)制可執(zhí)行文件。所有用Go語言編譯的可執(zhí)行程序都必須有一個名叫main的包。一個可執(zhí)行程序有且僅有一個main包。

6、基礎(chǔ)語法

6.1、注釋

package main

import "fmt"

// 我是單行注釋

/*
	我是多行注釋
	這是main函數(shù),是程序的入口
*/
func main() {
	fmt.Println("Hello,World!")
}

6.2、變量

package main

import "fmt"

func main() {
    //name就是變量
	var name string = "kuangshen"
	name = "zhangsan"
	fmt.Println(name)
}

6.3、變量的定義

Go語言是靜態(tài)類型語言,就是所有的類型我們都需要明確的去定義
我們聲明一個變量一般是使用var關(guān)鍵字

var name type
  • 第一個var是聲明變量的關(guān)鍵字,是固定的寫法,大家記住即可
  • 第二個name,就是我們變量的名字,你可以按照自己的需求給它定一個名字
  • 第三個type,就是用來代表變量的類型
//定義一個字符串變量 name
var name String

//定義一個數(shù)字類型變量 int
var age int

批量定義變量

package main

import "fmt"

func main() {
	var (
		name string
		age  int
		addr string
	)
	fmt.Println(name, age, addr)
}

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

如果沒有顯式的給變量賦值,系統(tǒng)自動賦予它該類型的默認(rèn)值

  • 整形和浮點(diǎn)型變量的默認(rèn)值為0和0.0
  • 字符串變量的默認(rèn)值為空字符串
  • 布爾型變量默認(rèn)為false
  • 切片、函數(shù)、指針變量的默認(rèn)為nil

6.4、變量初始化

變量初始化的標(biāo)準(zhǔn)格式

// = 是賦值,將右邊的值賦給左邊的變量
var name string = "ss"

短變量聲明并初始化

package main

import "fmt"

func main() {
	name := "kuangshen"
	age := 3
	fmt.Printf("name:%s,age:%d",name,age)
}

這是Go語言的推導(dǎo)聲明寫法,編譯器會自動根據(jù)右值的類型推斷出左值的類型

因為簡潔和靈活的特點(diǎn),簡短變量聲明被廣泛用于大部分的局部變量的聲明和初始化

注意
由于使用了 := ,而不是賦值的 = ,因此推導(dǎo)聲明寫法的左值**必須是沒有被定義**過的,若定義過,將會發(fā)生編譯錯誤

打印變量類型

	fmt.Printf("%T,%T", name, age)
	// string,int

6.5、打印內(nèi)存地址

func main() {
	var num int = 5
	fmt.Printf("num:%d的內(nèi)存地址為:%p\n", num, &num)

	num = 100
	fmt.Printf("num:%d的內(nèi)存地址為:%p\n", num, &num)
}

/*
    num:5的內(nèi)存地址為:0xc0000a6058
    num:100的內(nèi)存地址為:0xc0000a6058
*/

6.6、變量交換

func main() {

	/*
		傳統(tǒng)交換
		a = 100;
		b = 200
		temp = 0;
		temp = a;
		a = b;
		b = temp;
	*/

	var a int = 100
	var b int = 200

	b, a = a, b
	fmt.Println(a, b)

}

/*
	200 100
*/

6.7、匿名變量

匿名變量的特點(diǎn)是一個下畫線"__",本身就是一個特殊的標(biāo)識符,被稱為空白標(biāo)識符。它可以像其他標(biāo)識符那樣用于變量的聲明或賦值(任何類型都可以賦值給它),但任何賦給這個標(biāo)識符的值都將被拋棄,因此這些值不能在后續(xù)的代碼中使用,也不可以使用這
個標(biāo)識符作為變量對其它變量進(jìn)行賦值或運(yùn)算。使用匿名變量時,只需要在變量聲明的地方使用下畫線替換即可。

func main() {
	a, _ := test()
	fmt.Println(a)
}

func test() (int, int) {
	return 100, 200
}

假如在未來我們需要接收一個對象的某個屬性,其他屬性就使用匿名變量接收。

匿名變量不占用內(nèi)存空間,不會分配內(nèi)存,且匿名變量與匿名變量之間也不會因為多次聲明而無法使用。

6.8、變量的作用域

一個變量(常量、類型或函數(shù))在程序中都要一定的作用范圍,稱之為作用域。

了解變量的作用域?qū)ξ覀儗W(xué)習(xí)Go語言來說是比較重要的,因為Go語言會在編譯時檢查每個變量是否使用過,一旦出現(xiàn)未使用的變量,就會報編譯錯誤。如果不能理解變量的作用域,就有可能會帶來一些不明所以的編譯錯誤。

局部變量

在函數(shù)體內(nèi)聲明的變量稱為局部變量,作用域只在函數(shù)體內(nèi)。

func main() {
	// a就是局部變量
	a, _ := test()
	fmt.Println(a)
}

全局變量

在函數(shù)體外聲明的變量稱之為全局變量,全局變量只需要在一個源文件中定義,就可以在所有源文件中使用,當(dāng)然,不包含這個全局變量的源文件需要使用"import"關(guān)鍵字引入全局變量所在的源文件之后才能使用這個全局變量。
全局變量聲明必須以var 關(guān)鍵字開頭,如果想要在外部包中使用全局變量的首字母必須大寫。

var name string = "s"

func main() {
	var name string = "a"
	fmt.Println(name)
}

/*
	a 	//就近原則
*/

6.9、常量

在Go語言中,我們使用**const**關(guān)鍵字來定義常量,常量的值不允許改變,一般用大寫表示。

func main() {
	const URL string = "192.168.1.1"	//顯式定義
	const URL2 = "192.168.1.1"			//隱式定義
	const a, b, c = 3.14, "www.baidu.com", true		//同時定義
	fmt.Println(a, b, c)
}

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

iota可以被用作枚舉值:

func main() {
	const (
		a = iota
		b = iota
		c = iota
	)
	fmt.Println(a, b, c)
}

/*
	0 1 2
*/

只要在同一組里,iota的值都會從0開始增加。

func main() {
	const (
		a = iota
		b
		c
		d = "haha"
		e
		f = 100
		g
		h = iota
		i
	)
    const (
		j = iota
		k
	)
	fmt.Println(a, b, c, d, e, f, g, h, i)
}

/*
	0 1 2 haha haha 100 100 7 8 0 1
*/

7、基本數(shù)據(jù)類型

Go語言是一種靜態(tài)類型的編程語言,在Go編程語言中,數(shù)據(jù)類型用于聲明函數(shù)和變量。數(shù)據(jù)類型的出現(xiàn)是為了把數(shù)據(jù)分成所需內(nèi)存大小不同的數(shù)據(jù),編程的時候需要用大數(shù)據(jù)的時候才需要申請大內(nèi)存,就可以充分利用內(nèi)存。編譯器在進(jìn)行編譯的時候,就要知道每個值的類型,這樣編譯器就知道要為這個值分配多少內(nèi)存,并且知道這段分配的內(nèi)存表示什么。

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

7.1、布爾型

布爾型的值只可以是常量true或者false。

默認(rèn)值是false。

func main() {
    
	var b1 bool			
	var b2 bool
	
	b1 = true
	b2 = false
	
	fmt.Printf("%T,%t\n", b1, b1)
	fmt.Printf("%T,%t\n", b2, b2)
	
}

/*
	bool,true
	bool,false
*/

7.2、數(shù)字類型

整型int和浮點(diǎn)型float32、float64,Go語言支持整型和浮點(diǎn)型數(shù)字,并且支持復(fù)數(shù),其中位的運(yùn)算采用補(bǔ)碼。

Go也有基于架構(gòu)的類型,例如:unit無符號、int有符號

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

func main() {
	var i1 int8
	var i2 uint8

	i1, i2 = 100, 200
    
	fmt.Println(i1)
	fmt.Println(i2)

}

浮點(diǎn)型,Go語言中默認(rèn)是float64

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

func main() {

	var money float64 = 3.14

	fmt.Printf("%T,%f\n", money, money) 	//默認(rèn)6位小數(shù)打印,四舍五入

}

常見的別名

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

7.3、字符與字符串

字符與字符串

func main() {
    
	var str string
	str = "Hello,Go"
	fmt.Printf("%T,%s\n", str, str)

	v1 := 'A'
	v2 := "A"

	fmt.Printf("%T,%s\n", v1, v1)
	fmt.Printf("%T,%s\n", v2, v2)

}

/*
	string,Hello,Go
    int32,%!s(int32=65)			//可以看到單引號定義的變量實際是int32類型,實際上打印的是對應(yīng)ASCII表中的十進(jìn)制值
    string,A 
*/

部分用法

func main() {

	// 拼接
	fmt.Printf("aaa" + "bbb\n")

	// 轉(zhuǎn)義
	fmt.Printf("hello\"bbb\n")
    
    // 換行
	fmt.Printf("hello\nbbb")
    
    // Tab
	fmt.Printf("hello\tbbb")
}

/*
	aaabbb             
	hello"bbb
    hello
    bbb
    hello  bbb
*/

7.4、數(shù)據(jù)類型的轉(zhuǎn)換

在必要以及可行的情況下,一個類型的值可以被轉(zhuǎn)換成另一種類型的值。由于Go語言不存在隱式類型轉(zhuǎn)換,因此所有的類型轉(zhuǎn)換都必須顯式的聲明。

類型B的值 = 類型B(類型A的值)

func main() {

	a := 3.14
	b := int(a)

	fmt.Println(a)
	fmt.Println(b)

}

/*
	3.14
	3			//直接舍去小數(shù)
*/

盡量小轉(zhuǎn)大,因為大轉(zhuǎn)小會造成精度丟失。

8、運(yùn)算符

8.1、算數(shù)運(yùn)算符

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

8.2、關(guān)系運(yùn)算符

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

8.3、邏輯運(yùn)算符

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

8.4、位運(yùn)算符

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

8.5、賦值運(yùn)算符

Go語言學(xué)習(xí)筆記(狂神說),狂神說,Go,golang,學(xué)習(xí),筆記,云原生

這里其實學(xué)過其他語言的話對這些運(yùn)算符應(yīng)該都認(rèn)識,如果學(xué)過C語言,其實Go語言的很多格式和C是一樣的。

9、流程控制

9.1、if語句

進(jìn)行一次判斷,根據(jù)判斷的結(jié)果執(zhí)行不同的代碼段。

/*
 if 判斷條件 {    //判斷條件的括號可加可不加
  	滿足條件執(zhí)行的代碼
 } else {
  	不滿足執(zhí)行的代碼
 }
 */

package main

import "fmt"

func main() {

    score := 90
    name := "zhuwenjie"

    // 測試1
    if score >= 90 && score <= 100 {
        fmt.Println("A")
    } else if score >= 80 && score < 90 {
        fmt.Println("B")
    } else if score >= 70 && score < 80 {
        fmt.Println("C")
    } else if score >= 60 && score < 70 {
        fmt.Println("D")
    } else {
        fmt.Println("不及格")
    }

    fmt.Println()

    // 嵌套if
    if score >= 90 {
        if name == "zhuwenjie" {
            fmt.Println("正確")
        } else {
            fmt.Println("姓名不正確")
        }
    } else {
        fmt.Println("成績不正確")
    }

}

9.2、switch和fallthrough

switch語句用于基于不同條件執(zhí)行不同動作,每一個case分支都是唯一的,從上至下逐一測試,直到匹配為止。

package main

import "fmt"

func main() {

    score := 90

    switch score {
        case 90:
        	fmt.Println("A")
        	fallthrough    // fallthrough 會無視下一個case的條件,直接執(zhí)行
        case 80:
        	fmt.Println("B")
        case 60,70:
        	fmt.Println("B")
        default:
        	fmt.Println("D)
     }

}

/*
 	A                                   
 	B  
*/

switch語句的執(zhí)行從上至下,直到找到匹配項,找到之后也不需要再加break,switch默認(rèn)情況下case最后自帶break語句。

9.3、for語句

for循環(huán)是一個循環(huán)控制結(jié)構(gòu),可以執(zhí)行指定次數(shù)的循環(huán)。

package main

import "fmt"

func main() {

    for i := 1; i <= 9; i++ {     //打印99乘法表
        for j := 1; j <= i; j++ {
            fmt.Printf("%d*%d=%d\t", j, i, j*i)
        }
        fmt.Println()
    }

}

9.4、break與continue

break 結(jié)束當(dāng)前整個循環(huán)

package main

import "fmt"

func main() {

    for i := 1; i <= 10; i++ {
        if i == 5 {
            break
        }
        fmt.Println(i)
    }

}

/*
  1
  2
  3
  4
*/

continue 結(jié)束本次循環(huán)

package main

import "fmt"

func main() {

    for i := 1; i <= 10; i++ {
        if i == 5 {
            continue
        }
        fmt.Println(i)
    }

}

/*
  1
  2
  3
  4
  6
  7
  8
  9
  10
*/

9.5、遍歷字符串

package main

import "fmt"

func main() {

    score := 90
    name := "zhuwenjie"

    println(len(name))    // len(str) 獲得字符串的長度

    fmt.Printf("%c,%d\n", name[1], name[1])

    for i := 0; i < len(name); i++ {
        fmt.Printf("%c,%d\n", name[i], name[i])
    }

    // i是下標(biāo),v是對應(yīng)元素
    for i, v := range name {   // for i, v := range name  其中i是下標(biāo),v是該下標(biāo)對應(yīng)的值
        fmt.Printf("%d,%c,%d\n", i, v, v)
    }

}

10、函數(shù)

什么是函數(shù)

  • 函數(shù)是基本的代碼塊,用于執(zhí)行一個任務(wù)
  • Go程序至少要有一個main函數(shù)
  • 通過函數(shù)來劃分功能,邏輯上每個函數(shù)執(zhí)行指定的任務(wù)
  • 函數(shù)聲明告訴了編譯器函數(shù)的名稱、返回類型和參數(shù)

10.1、函數(shù)的聲明

Go語言中函數(shù)定義格式如下:

func function_name( [parameter list] ) [return_types] {
    函數(shù)體
}
  • 無參無返回值函數(shù)
package main

func main() {
    printInfo()
}

func printInfo() {
    println("我執(zhí)行了printInfo函數(shù)")
}
  • 有一個參數(shù)的函數(shù)
package main

func main() {
    printInfo(5)
}

func printInfo(a int) {
    println(a)
}
  • 有兩個參數(shù)的函數(shù)
package main

func main() {
    println(add(1, 2))
}

func add(a int, b int) int {
    c := a + b
    return c
}
  • 有一個返回值的函數(shù)
package main

func main() {
    println(add(1, 2))
}

func add(a int, b int) int {
    c := a + b
    return c
}
  • 有多個返回值的函數(shù)
package main

func main() {
    add, del := addAndDel(1, 2)
    println(add, del)
}

func addAndDel(a int, b int) (int, int) {
    c := a + b
    d := a - b
    return c, d
}

10.2、形參和實參

package main

func main() {
    // 形參與實參要一一對應(yīng),包括類型和順序
    add, del := addAndDel(1, 2)
    println(add, del)
}

// addAndDel 計算兩個數(shù)相加和相減的結(jié)果
// 形式參數(shù): a b  定義函數(shù)時,用來接收外部傳入數(shù)據(jù)的參數(shù)
// 實際參數(shù): 1 2  調(diào)用函數(shù)時,傳給形參的實際數(shù)據(jù)
func addAndDel(a int, b int) (int, int) {
    c := a + b
    d := a - b

    //一個函數(shù)在定義時如果有返回值,那么函數(shù)中必須使用return語句
    return c, d
}

10.3、可變參數(shù)

概念:一個參數(shù)的參數(shù)類型確定,但個數(shù)不確定,就可以使用可變參數(shù)。

func myfunc(arg ...int){}

// arg ...int 告訴編譯器這個函數(shù)接收不定數(shù)量的參數(shù),類型全是int
package main

func main() {
    println(getSum(1, 3, 5, 7, 9))
}

func getSum(nums ...int) int {
    sum := 0
    for _, num := range nums {
        sum += num
    }
    return sum
}

注意事項:

  • 如果一個函數(shù)的參數(shù)是可變參數(shù),同時還有其他參數(shù),可變參數(shù)要放在參數(shù)列表的最后
  • 一個函數(shù)的參數(shù)列表中最多只能有一個可變參數(shù)

10.4、參數(shù)傳遞

按照數(shù)據(jù)的存儲特點(diǎn)來分:

  • 值類型的數(shù)據(jù):操作的是數(shù)據(jù)本身,基礎(chǔ)數(shù)據(jù)類型、array、struct…
  • 引用類型的數(shù)據(jù):操作的是數(shù)據(jù)的地址,slice、map、chan…
10.4.1、值傳遞
package main

import "fmt"

func main() {

    //值傳遞
    arr := [4]int{1, 2, 3, 4}
    fmt.Println(arr)

    update(arr, 1, 100)
    fmt.Println(arr)

}

// 更改數(shù)組中某個元素的值
func update(arr [4]int, j int, target int) {
    arr[j] = target
    fmt.Println(arr)
}

/*
  [1 2 3 4] //未修改前數(shù)組的值
  [1 100 3 4] //update方法里修改后的值
  [1 2 3 4]  //修改后數(shù)組的值
*/

這里學(xué)過C的話其實很容易明白,C語言里本身就有值傳遞和引用傳遞,程序會為每一個函數(shù)開辟一個空間,因此如果是值傳遞的類型,在這個函數(shù)里改變的其實是原來數(shù)據(jù)的拷貝,因此對原來的數(shù)據(jù)并沒有造成影響。

10.4.2、引用傳遞
package main

import "fmt"

func main() {

    //引用傳遞
    arr := []int{1, 2, 3, 4}
    fmt.Println(arr)

    update(arr, 1, 100)
    fmt.Println(arr)

}

// 更改切片中某個元素的值
func update(arr []int, j int, target int) {
    arr[j] = target
    fmt.Println(arr)
}

/*
  [1 2 3 4]  
  [1 100 3 4]
  [1 100 3 4]
*/

可以看到函數(shù)里對于切片數(shù)據(jù)的更改也同步到了原切片上,對于引用數(shù)據(jù)類型來說,傳遞的其實是這個參數(shù)對應(yīng)的地址,因此對這個參數(shù)的修改能同步到原函數(shù)里。

10.5、函數(shù)變量的作用域

主要分為全局變量和局部變量,使用時遵循就近原則。

  • 定義在函數(shù)內(nèi)的是局部變量
  • 定義在函數(shù)外的是全局變量

10.6、遞歸函數(shù)

定義:一個函數(shù)自己調(diào)用自己,就叫做遞歸函數(shù)

注意:遞歸函數(shù)一定要有出口,否則會形成死循環(huán)

/*
    以求1~5的和為例  getSum(i)
    則getSum(5) = getSum(4) + 5
    getSum(4) = getSum(3) + 4
    getSum(3) = getSum(2) + 3
    getSum(2) = getSum(1) + 2
    getSum(1) = 1
*/
package main

func main() {
    println(getSum(5))
}

func getSum(num int) int {
    if num == 1 {
        return 1
    } else {
        return getSum(num-1) + num
    }
}

10.7、defer

defer語義:推遲、延遲

在Go語言中,使用defer關(guān)鍵字來延遲一個函數(shù)或者方法的執(zhí)行。

package main

import "fmt"

func main() {

    f("1")
    fmt.Println("2")
    defer f("3")
    fmt.Println("4")

}

func f(s string) {
    fmt.Println(s)
}

/*
  1
  2
  4
  3
*/

defer函數(shù)或方法:該函數(shù)或方法的執(zhí)行被延遲

  • 如果一個函數(shù)中添加了多個defer語句,當(dāng)函數(shù)執(zhí)行到最后時,這些defer語句會按照逆序執(zhí)行,最后該函數(shù)返回。特別是當(dāng)進(jìn)行一些打開資源的操作時,遇到錯誤需要提前返回,在返回前需要關(guān)閉相應(yīng)的資源,不然容易造成資源泄露問題。
  • 如果有很多調(diào)用defer,那么defer用的是后進(jìn)先出(棧)模式。
package main

import "fmt"

func main() {

    f("1")
    defer f("2")
    defer f("3")
    fmt.Println("4")

}

func f(s string) {
    fmt.Println(s)
}

/*
  1
  4
  3
  2
*/

需要注意的是,在執(zhí)行到defer語句的時候,函數(shù)里的形參就已經(jīng)傳遞進(jìn)去了,只是函數(shù)被延遲執(zhí)行了。

package main

import "fmt"

func main() {

    a := 10
    fmt.Println("begin a=", a)
    defer f(a)
    a++
    fmt.Println("end a=", a)

}

func f(s int) {
    fmt.Println(s)
}

/*
  begin a= 10
  end a= 11
  10  
*/

常用場景:

  • 對象.close() 臨時文件的刪除

    • 文件.open
    • defer 文件.close
    • 對文件進(jìn)行操作
  • Go語言中關(guān)于異常的處理,使用panic()和recover()

    • panic 函數(shù)用于引發(fā)恐慌,導(dǎo)致函數(shù)中斷執(zhí)行
    • recover 函數(shù)用于恢復(fù)程序的執(zhí)行,recover() 語法上要求必須在 defer 中執(zhí)行

10.8、函數(shù)本質(zhì)的探究

函數(shù)本身也是有數(shù)據(jù)類型的,func()

package main

import "fmt"

func main() {
    fmt.Printf("%T", fs) 	// func()
}

func fs() {

}

既然函數(shù)本身有數(shù)據(jù)類型,那么它就可以作為變量,可以賦值。

package main

import "fmt"

func main() {

    fmt.Printf("%T\n", fs)

    //定義函數(shù)類型的變量
    var ff func(int, int) = fs
    ff(1, 2)

    //看看ff和fs是否相同
    fmt.Println(ff)
    fmt.Println(fs)

}

func fs(a int, b int) {
    fmt.Println(a + b)
}

/*
  func(int, int)
  3     
  0x107fe40
  0x107fe40
*/

函數(shù)在Go語言中是復(fù)合類型,可以看做是一種特殊的變量。

函數(shù)名 ():調(diào)用返回結(jié)果

函數(shù)名:指向函數(shù)體的內(nèi)存地址,一種特殊類型的指針變量

10.9、匿名函數(shù)推導(dǎo)

package main

import "fmt"

func main() {

    // 函數(shù)正常執(zhí)行
    f1()

    // 匿名函數(shù)就是沒有名字的函數(shù)
    f2 := f1
    f2()

    // 匿名函數(shù),函數(shù)體后增加一個()執(zhí)行,通常只能執(zhí)行一次
    func() {
        fmt.Println("我是一個匿名函數(shù)")
    }()

    // 將匿名函數(shù)賦值,單獨(dú)進(jìn)行調(diào)用
    f3 := func() {
        fmt.Println("我是一個匿名函數(shù)...")
    }
    f3()

    // 定義帶參數(shù)的匿名函數(shù)
    func(a int, b int) {
        fmt.Println(a, b)
    }(1, 2)

    // 定義帶返回值的匿名函數(shù)
    r1 := func(a int, b int) int {
        return a + b
    }(10, 20) //帶了()就是函數(shù)調(diào)用
    fmt.Println(r1)

}

func f1() {
    fmt.Println("我是f1函數(shù)")
}

/*
  我是f1函數(shù)
  我是f1函數(shù)     
  我是一個匿名函數(shù)  
  我是一個匿名函數(shù)...
  1 2         
  30   
*/

Go語言是支持函數(shù)式編程:

  • 將匿名函數(shù)作為另外一個函數(shù)的參數(shù),回調(diào)函數(shù)
  • 將匿名函數(shù)作為另外一個函數(shù)的返回值,可以形成閉包結(jié)構(gòu)

10.10、回調(diào)函數(shù)

fun1(),fun2()

將fun1函數(shù)作為fun2函數(shù)的參數(shù)

fun2函數(shù):叫做高階函數(shù),接收了一個函數(shù)作為參數(shù)

fun1函數(shù):叫做回調(diào)函數(shù),作為另外一個函數(shù)的參數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-614442.html

package main

import "fmt"

func main() {

    // 正常執(zhí)行
    r1 := add(1, 2)
    fmt.Println(r1)

    // 封裝
    r2 := oper(3, 4, add) //加
    fmt.Println(r2)

    r3 := oper(8, 4, sub) //減
    fmt.Println(r3)

    r4 := oper(8, 4, func(i int, i2 int) int { //乘
        return i * i2
    })
    fmt.Println(r4)

    r5 := oper(8, 4, func(i int, i2 int) int { //除
        if i2 == 0 {
            fmt.Println("除數(shù)不能為0")
            return 0
        }
        return i / i2
    })
    fmt.Println(r5)

}

// 高階函數(shù)
func oper(a int, b int, fun func(int, int) int) int {
    r := fun(a, b)
    return r
}

func add(a int, b int) int {
    return a + b
}

func sub(a int, b int) int {
    return a - b
}

/*
  3
  7
  4
  32
  2
*/

10.11、閉包的理解

package main

import "fmt"

/*
  一個外層函數(shù)中,有內(nèi)層函數(shù),這個內(nèi)層函數(shù)會操作外層函數(shù)的局部變量
  且該外層函數(shù)的返回值就是該內(nèi)層函數(shù)
  這個內(nèi)層函數(shù)和外層函數(shù)的局部變量,統(tǒng)稱為閉包結(jié)構(gòu)

  此時局部變量的聲明周期就會發(fā)生變化,正常的局部變量會隨著函數(shù)的調(diào)用而創(chuàng)建,隨著函數(shù)的結(jié)束而銷毀
  但是閉包中外層函數(shù)的局部變量并不會隨著外層函數(shù)的結(jié)束而銷毀,因為內(nèi)層函數(shù)還在繼續(xù)使用
*/
func main() {

    r1 := increment()
    fmt.Println(r1)

    fmt.Println(r1())

    v2 := r1()
    fmt.Println(v2)
    fmt.Println(r1())
    fmt.Println(r1())
    fmt.Println(r1())

    r2 := increment()
    fmt.Println(r2())

}

func increment() func() int {

    // 局部變量i
    i := 0

    // 定義一個匿名函數(shù),給變量自增并返回
    fun := func() int {
        i++
        return i
    }

    return fun
}


/*
  0x8ae800
  1
  2
  3
  4
  5

  1
*/

到了這里,關(guān)于Go語言學(xué)習(xí)筆記(狂神說)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • JUC并發(fā)編程——集合類不安全及Callable(基于狂神說的學(xué)習(xí)筆記)

    List不安全 CopyOnWriteArrayList與vector對比,以下來自CSDN智能助手的回答: Java中的CopyOnWriteArrayList和Vector都是線程安全的動態(tài)數(shù)組,可以在多線程環(huán)境下使用。 CopyOnWriteArrayList使用了一種特殊的寫時復(fù)制機(jī)制,它在對數(shù)組進(jìn)行修改時,會創(chuàng)建一個新的副本,而不是直接在原數(shù)組上

    2024年02月07日
    瀏覽(32)
  • 【Golang】一篇文章帶你快速了解Go語言&為什么你要學(xué)習(xí)Go語言

    【Golang】一篇文章帶你快速了解Go語言&為什么你要學(xué)習(xí)Go語言

    目錄 1. 為什么互聯(lián)網(wǎng)世界需要Go語言 1.1 硬件限制:摩爾定律已然失效? 1.2 Go語言為并發(fā)而生 1.3 Go性能強(qiáng)悍 1.4 Go語言簡單易學(xué) 1.4.1 語法簡潔 1.4.2 代碼風(fēng)格統(tǒng)一 1.4.3開發(fā)效率高? 2.Go語言的誕生與發(fā)展 2.1什么是Go語言? ?2.2 Go語言的誕生 2.3?Go Gopher——Go語言的吉祥物 3. 為什么

    2024年02月04日
    瀏覽(37)
  • 是時候回答【我為什么要學(xué)習(xí) Go 語言(golang)】這個問題了

    想必每個人在學(xué)習(xí)新事物之前,都會捫心自問:“我為什么要學(xué)習(xí)它呢?” 正如我們讀 四大名著 一般,也只有在您讀過了 四大名著 后,再細(xì)看中國幾千年歷史不就是 天下大勢合久必分,分久必合 ,再者,便是與友數(shù)人相聚,席間您述說您通勤時所遇到有意思的事了,而您

    2023年04月09日
    瀏覽(19)
  • SpringBoot筆記——(狂神說)——待續(xù)

    SpringBoot筆記——(狂神說)——待續(xù)

    路線 javase: OOPmysql:持久化 html+css+js+jquery+框架:視圖,框架不熟練,css不好; javaweb:獨(dú)立開發(fā)MVC三層架構(gòu)的網(wǎng)站了∶原始 ssm :框架:簡化了我們的開發(fā)流程,配置也開始較為復(fù)雜; war: tomcat運(yùn)行 spring再簡化: SpringBoot - jar:內(nèi)嵌tomcat;微服務(wù)架構(gòu)!服務(wù)越來越多: springcloud; 什么是Spring S

    2024年02月10日
    瀏覽(24)
  • 【go語言學(xué)習(xí)筆記】05 Go 語言實戰(zhàn)

    【go語言學(xué)習(xí)筆記】05 Go 語言實戰(zhàn)

    在做項目開發(fā)的時候,要善于借助已經(jīng)有的輪子,讓自己的開發(fā)更有效率,也更容易實現(xiàn)。 1. RESTful API 定義 RESTful API 是一套規(guī)范,它可以規(guī)范如何對服務(wù)器上的資源進(jìn)行操作。和 RESTful API 和密不可分的是 HTTP Method。 1.1 HTTP Method HTTP Method最常見的就是POST和GET,其實最早在

    2024年02月13日
    瀏覽(23)
  • 100天精通Golang(基礎(chǔ)入門篇)——第5天: Go語言中的數(shù)據(jù)類型學(xué)習(xí)

    100天精通Golang(基礎(chǔ)入門篇)——第5天: Go語言中的數(shù)據(jù)類型學(xué)習(xí)

    ?? 博主 libin9iOak帶您 Go to Golang Language.? ?? 個人主頁——libin9iOak的博客?? ?? 《面試題大全》 文章圖文并茂??生動形象??簡單易學(xué)!歡迎大家來踩踩~?? ?? 《IDEA開發(fā)秘籍》學(xué)會IDEA常用操作,工作效率翻倍~?? ?? 希望本文能夠給您帶來一定的幫助??文章粗淺,敬請批

    2024年02月08日
    瀏覽(34)
  • Mybatis筆記分享【狂神說java】

    Mybatis筆記分享【狂神說java】

    1.1什么是MyBatis MyBatis 是一款優(yōu)秀的 持久層框架 它支持自定義 SQL、存儲過程以及高級映射 MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作 MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為

    2023年04月26日
    瀏覽(19)
  • Git的基本使用筆記——狂神說

    Git的基本使用筆記——狂神說

    版本迭代, 版本控制( Revision control)是一種在開發(fā)的過程中用于管理我們對文件、目錄或工程等內(nèi)容的修改歷史,方便查看更改歷史記錄,備份以便恢復(fù)以前的版本的軟件工程技術(shù)。 實現(xiàn)跨區(qū)域多人協(xié)同開發(fā) 追蹤和記載一個或者多個文件的歷史記錄 組織和保護(hù)你的源代碼和

    2024年02月09日
    瀏覽(18)
  • 6.Go語言學(xué)習(xí)筆記-結(jié)合chatGPT輔助學(xué)習(xí)Go語言底層原理

    6.Go語言學(xué)習(xí)筆記-結(jié)合chatGPT輔助學(xué)習(xí)Go語言底層原理

    1、Go版本 2、匯編基礎(chǔ) 推薦閱讀:GO匯編語言簡介 推薦閱讀:A Quick Guide to Go\\\'s Assembler - The Go Programming Language 精簡指令集 數(shù)據(jù)傳輸: MOV/LEA 跳轉(zhuǎn)指令: CMP/TEST/JMP/JCC 棧指令: PUSH/POP 函數(shù)調(diào)用指令: CALL/RET 算術(shù)指令: ADD/SUB/MUL/DIV 邏輯指令: AND/OR/XOR/NOT 移位指令: SHL/SHR JCC有條件跳轉(zhuǎn): JE

    2024年02月04日
    瀏覽(29)
  • 【go語言學(xué)習(xí)筆記】04 Go 語言工程管理

    【go語言學(xué)習(xí)筆記】04 Go 語言工程管理

    1. 單元測試 單元測試是保證代碼質(zhì)量的好方法,但單元測試也不是萬能的,使用它可以降低 Bug 率,但也不要完全依賴。除了單元測試外,還可以輔以 Code Review、人工測試等手段更好地保證代碼質(zhì)量。 1.1 定義 顧名思義,單元測試強(qiáng)調(diào)的是對單元進(jìn)行測試。在開發(fā)中,一個單

    2024年02月13日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包