Golang快速入門
Go語言簡介:
Golang
簡稱 Go
,是一個開源的程式語言,Go是從2007年末由 Robert Griesemer
, Rob Pike
, Ken Thompson
主持開發,後來還加入了Ian Lance Taylor
, Russ Cox
等人,並最終於2009年11月開源,在2012年早些時候釋出了Go 1穩定版本。
1.Go語言用途:
Go 語言被設計成一門應用於搭載 Web 伺服器,儲存叢集或類似用途的巨型中央伺服器的系統程式語言。
Go 語言在用於高效能分散式系統開發中,無疑比大多數其它語言有著更高的開發效率。此外,它提供了海量並行的支援,這對於遊戲服務端的開發而言也是不錯的選擇。
2.Go語言開源專案:
有著媲美C語言的效能和Python的開發效率,被稱為21世紀的C語言。目前使用Go語言開發的一些優秀的開源專案有:Docker
、etcd
、kubernetes
等。
3.Go語言特點:
優點:
- 簡潔、快速、安全
- 支援併發程式設計
- 自動垃圾回收
- 編譯迅速
- 便捷部署:go最終生成的是一個 可執行檔案,不管你的程式依賴多少庫,都會被打包進行,生成一個可執行檔案,所以相比java龐大的jar庫來說,他的部署非常方便,執行執行這個可執行檔案就好了。
缺點:
- 錯誤處理比較繁瑣,需要寫很多
err
判斷
- 錯誤處理比較繁瑣,需要寫很多
Go開發環境配置:
訪問 Golang官網
Windows
、MacOS X
、Linux
和 FreeBSD
四個平臺,這裡我們以Windows為例:
1.*Windows下的安裝:*
檢查版本:
直接開啟cmd命令列,輸入一下指令查詢安裝Go的版本:C:\Users\Administrator>go version go version go1.8.3 windows/amd64
2.Linux下的安裝:
- 解壓到
/usr/local
目錄:tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
- 將
/usr/local/go/bin
目錄新增到Path
環境變數中:export PATH=$PATH:/usr/local/go/bin
。
3.Hello World:
Tour編輯器:
假如只是前期的語法學習,可以考慮先不安裝開發環境,可以直接在 Golang官網 上的網頁內嵌 Tour編輯器 中編寫程式碼和執行:
在編輯器中編寫如下程式碼:package main import "fmt" func main() { fmt.Println("Hello world!") }
執行結果:
本地執行:
也可以在本地建立一個hello.go
檔案,內容與上述一致,然後在命令列定位到建立.go
檔案的目錄下,執行go run (.go檔名)
:E:\Go\Projects>go run hello.go Hello world!
此過程會將
.go
原始碼編譯成二進位制檔案,但是編譯結果不會儲存到本地,可以go build
實現此過程,編譯結果hello.exe
會儲存到本地,可以直接在命令列執行:E:\Go\Projects>hello.exe Hello world!
原始碼解析:
package
:是一個關鍵字,定義一個包,和Java中的Package
一樣,用於模組化程式設計;import
:也是一個關鍵字,用於引入包,與Java的import
一樣,引入包之後可以使用其中的功能;fmt
:Go語言的一個自帶功能包;main()
:主函式,也是程式執行的入口;fmt.Println
:用於輸出一段字串。
不難發現Go語言與Java的關鍵字、函式和包等很相似,但是,Go語言不需要以
;
(分號)符號結尾,一行代表一個語句結束。
Go基本語法:
1.基本資料型別:
數值型別 | 說明 |
---|---|
bool | 布林 |
string | 字元 |
int,int8,int16,int32,int64 | int長度與平臺相關 |
uint,uint8,uint16,uint32,uint64 | uint長度與平臺相關 |
uintptr | 同指針,32位平臺為4位元組,64位八位元組 |
byte | 等價於uint8 |
rune | 等價於uint32,單個unicode字元 |
float32,float64 | |
complex64,complex128 | 複數型別, value = 3.2+12i |
2.數值定義:
Go語言最獨特的就是:宣告變數或者常量時,型別表示寫在變數或者常量名稱之後。
常量:
- 顯式定義
const a int = 1
- 隱式定義
const a = 1
可以進行多個相同或不同型別的宣告:
const a, b, c = 1, false, "str" //多重賦值
變數:
var s string = "hehe"
聲明後若不賦值,使用預設值:
int a
假如輸出
a
結果,則為int預設值0。還可以同時對多個相同或不同型別的變數進行宣告:var e, f = 123, "hello"
也有一種簡化的宣告方式,不需顯示宣告變數型別也省去了
var
,變數的型別由go根據值推匯出來:s := "hehe"
有興趣的還可以瞭解一下
值型別
和引用型別
的區別。
3.操作符:
- 賦值:
=
,:=
- 數值運算:
+
(相加),-
(相減),*
(相乘),/
(相除),%
(求餘),++
(自增),--
(自減) - 比較運算:
>
,<
,==
,>=
,<=
,!=
- 邏輯運算:
&&
,||
,!
- 位執行:
>>
,<<
,^
,&
(與),|
(或),^x
(取反) - 其他:
&
(變數儲存地址),*
(指標變數)
其中有兩個比較特殊的操作符:
特殊操作符 | 說明 |
---|---|
:= | 無需指定型別即可賦值:i, j := true, "hello" |
_ | 空白識別符號,可以賦任意值的空物件:_ = "string" |
空白識別符號
_
也被用於拋棄值,如值 5 在:_, b = 5, 7
中被拋棄。
_
實際上是一個只寫變數,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被宣告的變數,但有時你並不需要使用從一個函式得到的所有返回值。
4.大小寫標記訪問許可權:
在go中不能隨便使用大小寫的問題,是因為大小寫具有特殊意義,在go中,大寫字母開頭的變數或者函式等是public
的,可以被其他包訪問;小寫的則是private
的,不能被其他包訪問到。這樣就省去了public和private宣告的煩惱,使程式碼變的更簡潔。
5.關鍵字:
關鍵字 | 作用 |
---|---|
package | 程式碼所屬包 |
import | 匯入依賴包,不能匯入不使用的包 |
main | 主函式入口,無引數無返回值,命令列引數儲存在os.Args中 |
func | 函式宣告 |
go | 開啟協程(併發核心) |
map | 字典型別, map[string]bool |
delete | 專用來刪除字典中的元素 |
chan | 通道,協程通訊核心 |
select | 同時讀取多個chan的資訊 |
close | 用來關閉通道 |
make | 用來建立chan或map |
type | 型別定義,定義任意需要的型別 |
struct | C中的結構體,但可以定義方法以實現類功能 |
interface | 介面型別,用來定義介面 |
new | 新建物件, 並獲得它的指標 |
range | 類似python的range,配合for遍歷列表、陣列或map的元素 |
defer | 自動關閉資源,退出程式碼體(一般是函式)時執行 |
error | error介面,只要實現Error()string方法就是一個error介面 |
panic | 丟擲異常,如果不用recover捕獲則會終止程式 |
recover | 捕獲panic異常,防止程式終止,與recover結合 |
6.註釋:
Go
程式的程式碼註釋與 C++
保持一致,主持:塊註釋 與 行註釋
塊註釋:
/* 塊註釋 */
行註釋:
// 行註釋
7.流程控制:
條件:
條件語句 說明 if if 語句 由一個布林表示式後緊跟一個或多個語句組成。 if…else if 語句 後可以使用可選的 else 語句, else 語句中的表示式在布林表示式為 false 時執行。 if 巢狀 你可以在 if 或 else if 語句中嵌入一個或多個 if 或 else if 語句。 switch switch 語句用於基於不同條件執行不同動作。 select select 語句類似於 switch 語句,但是select會隨機執行一個可執行的case。如果沒有case可執行,它將阻塞,直到有case可執行。 if
if i>0 { //條件執行內容 }
相比於其他語言,Go語言的條件判斷語句不需要小括號。
// 特殊用法, 判斷語句中可以初始化變數 if i:=4;i>0{ fmt.Println("i = ",i) }
switch,case
switch i { case 0: // ... case 1: // ... default: // ... }
Go語言的
switch
不需要break
來跳出一個case
。select
可以看做是專用於通訊的switch
語句,每一個case
必須是一個通訊操作,要麼是傳送要麼是接收。select
執行邏輯:隨機執行一個可執行的case。如果沒有case可執行,它將阻塞,直到有case可執行。一個預設的子句應該總是可執行的。select { case communication clause : statement(s); case communication clause : statement(s); /* 你可以定義任意數量的 case */ default : /* 可選 */ statement(s); }
執行
select
的語法大致如下:- 每個
case
都必須是一個通訊 channel
表示式都會被求值- 所有被髮送的表示式都會被求值
- 如果任意某個通訊可以進行,它就執行;其他被忽略。
- 如果有多個
case
都可以執行,select
會隨機公平地選出一個執行。其他不會執行。 - 否則:
1.如果有default
子句,則執行該語句。
2.如果沒有default
字句,select
將阻塞,直到某個通訊可以執行;Go不會重新對channel或值進行求值。
- 每個
迴圈:
迴圈語句 說明 for 重複執行語句塊 for巢狀 在 for 迴圈中巢狀一個或多個 for 迴圈 Go語言中的for迴圈與Java、C#等的區別就是三個由
;
(分號)分開的組成部分不需要小括號括起來:for i := 0; i < 10; i++ { sum += i }
Go語言中沒有其他語言中
while
的用法,for
在Go語言中可以當做while
來用:sum := 1 //迴圈條件 for sum < 1000 { sum += sum } //死迴圈 for {// 無退出條件,變成死迴圈 }
其他:
在Go語言中,同樣可以使用break
、continue
和goto
來控制流程:控制語句 說明 break 經常用於中斷當前 for
迴圈或跳出switch
語句continue 跳過當前迴圈的剩餘語句,然後繼續進行下一輪迴圈。 goto 將控制轉移到被標記的語句。 例如
goto
,需要用一個文字來標誌某個語句(寫在該語句前面):goto label .. . label: statement
label
就是用來標誌的文字,statement
是一個普通的Go語句,goto label
執行之後,程式將調到statement
然後順序往下執行。
8.函式:
Go語言中定義一個函式的格式如下:
func 方法名稱([傳入引數表]) [返回結果資料型別]{
//函式體
}
上面使用[]
符號括起來的部分表示 非必須 的,可根據使用情況決定是否可以不寫,例如無需傳入引數時,傳入引數列表可以省略。注意:傳入的引數列表中形式引數定義的格式也是:變數名在前,變數型別在後。
普通用法:
package main import "fmt" func main(){ PrintSth(1,2) sum := 0 sum = mSum(10,20) fmt.Println("sum = ",sum) } func PrintSth(x,y int){ fmt.Println("x = ",x,";y = ",y) } func mSum(x,y int) int{ return x+y }
返回多個值:
例如定義一個值互換的方法://定義函式 func swap(x, y string) (string, string) { return y, x } //呼叫函式 a,b := swap("a","b")
函式作為值:
定義函式的時候,也可以將函式宣告為一個函式變數,呼叫的時候用函式變數替換函式真是名稱來呼叫即可:/* 宣告函式變數 */ getSquare := func(x float64) float64 { return x*x } /* 使用函式 */ fmt.Println(getSquare(3))
閉包:
閉包,是匿名函式(一個“內聯”語句或表示式)的一種宣告方式,好處就是可以直接使用函式內的變數不必宣告://沒呼叫一次getSequence,i就自增1 func getSequence() func() int { i:=0 return func() int { i+=1 return i } }
函式的返回結果是另一個函式。
方法:
與函式略有不同,方法宣告時會指定其所附的是命名型別或結構型別的一個值或者是一個指標,所有給定型別的方法屬於該型別的方法集。例如://定義結構體 type Circle struct { radius float64 } //此屬於 Circle 型別物件中的方法 func (c Circle) getArea() float64 { //c.radius 即為 Circle 型別物件中的屬性 return 3.14 * c.radius * c.radius } //呼叫 main(){ var c Circle c.radius = 1 fmt.Println("Area of c = ", c.getArea()) }
9.指標:
指標變數:
一個 指標變數 可以指向任何一個值的記憶體地址,使用指標前需要宣告,宣告格式如下:var var_name *var-type
var_name
是變數名,var-type
是指標型別,例如:var ip *int // 此指標只能指向整型
使用步驟:
建立指標變數,為指標賦值(如:指向變數),輸出結果:var a int = 1 //建立指標變數 var ptr *int //指標賦值(指向變數a的地址) ptr = &a /* 指標變數的儲存地址 */ fmt.Printf("ptr 變數儲存的指標地址: %x\n", ptr ) /* 使用指標訪問值 */ fmt.Printf("*ptr 變數的值: %d\n", *ptr )
取址符:
Go語言中,使用&
作 取址符,假如放在變數前可以返回相應變數的記憶體地址:var a int = 1 fmt.Printf("變數的地址: %x\n", &a )
輸出結果:
變數的地址: c0420382a0
空指標:
Go語言中的空指標是nil
,表示沒有分配到任何變數,判斷指標是否為空指標://宣告指標,不賦值 var ptr *int if ptr == nil{ //條件執行塊 }
10.結構體:
以關鍵字 type
和 struct
來一起宣告一個結構體,格式如下:
type structure_variable_type struct{
member menberType
member menberType
...
}
其中 structure_variable_type
是當前定義結構體的名稱,建立結構體操作:
variable_name := structure_variable_type(value1,value2,...)
例如:
//定義
type Info struct{
id int
name string
}
//宣告
var mInfo Info
//賦值
mInfo.id = 1
mInfo.name = "linsh"
11.包的使用:
每個Go程式都是由包組成的,其中程式執行入口包為 main
,通常包名與匯入目錄路徑最後一級目錄名稱一致。例如:匯入“math、rand”包,這個包必然是以 package rand
語句開始的。
匯入包:
以import
關鍵字來實現包的匯入,有兩種格式:多個匯入語句:
import "fmt" import "math"
“打包”匯入:
import ( "fmt" "math" )
使用第二種方式匯入包更為方便。
匯出命名:
在Go程式設計中,某個包中 使用首字母大寫的名稱定義的屬性或者方法可以被匯入了此包的指令碼呼叫,相當於是開放了訪問許可權,例如:這裡我們定義了一個 ··Test·· 包,然後再main
包中引入此包並呼叫其匯出方法:package Test func SetName(_name string){ } func setName(_name string){ }
在
main
中先import Test
,然後只能呼叫SetName
函式而不能呼叫setname
。