在上一篇文章中講述了配置與輸出,接下來我們進入下一步的學習
前言:Go語言特性
Go語言是Google公司開發的一種靜態的,編譯型並自帶垃圾回收和併發的變成語言.
Go語言的風格類似C語言,其語法在C語言的基礎上進行了大幅度的優化,去掉了不需要的表達式括號,循環也只有for一種表示方法,就可以實現數值,鍵值等各種遍歷.因此, Go語言上手非常容易.
Go語言最具有特色的特性莫過於goroutine. Go語言在語言層可以通過goroutine對函數實現併發並行. goroutine類似於線程,但並非線程, goroutine會在Go語言運行時進行自動調度.因此,Go語言非常適合用於高併發網絡服務的編寫.
一、Go的基本語法以及使用
1、整型類型
Go對類型的長度有極大要求
長度類型:int8 int16 int32 int64
對應無符號類型:uint8 uint16 uint32 uint64
2、浮點型
Go語言支持兩種浮點整數:
float32:最大範圍約爲 3.4e38,可以使用常量定義:math.MaxFloat32
float64:最大範圍約爲 1.8e308,可以使用常量定義:math.MaxFloat64
3、布爾型
布爾型數據只有true和false
Go語言中不允許將整型強制轉換爲布爾型,代碼如下:
fmt.Println(int(n) * 2)
編譯錯誤,輸出如下:
cannot convert n (type bool) to type int
布爾型無法參與數值運算,也無法與其他類型進行轉換
4、字符串型
對於字符串類型,以雙引號爲擴住的則爲字符串類型,可放入非ASCII碼的字符
str := "hello world"
ch := "中文"
5、切片
接下來講述Go語言中的切片(能夠動態的的分配空間)是一個擁有相同類型元素的可變長度序列
var arr[]類型 // 初始化的時候定義,後面追加上類型 如int string float等
例:var arr[]int
切片的元素使用”[]“來進行訪問,在[]裏提供數值索引可獲取相對應的value值,切片的索引默認訪問是從0開始,如賦值時沒有從對應數字開始則默認值會自定義爲0,以下貼上代碼
// 創建切片
item := make([]int, 3) //創建一個容量爲3的整型切片 ps:其實就是創建一個容量只能爲3的切片,但是value都只能爲int
item[0] = 0 //爲切片元素賦值
item[1] = 1
item[2] = 2
fmt.Println(item)
輸出:[0 1 2]
如不按順序來進行賦值
// 創建切片
item := make([]int, 10) //創建一個容量爲10的整型切片 ps:其實就是創建一個容量只能爲10的切片,但是value都只能爲int
item[7] = 77
item[8] = 88
fmt.Println(item)
輸出:[0 0 0 0 0 0 0 77 88 0] // 未定義的索引值則默認爲0
我們也可以進行切片追加(append)
info := append(item, 99)
fmt.Println(item, info)
輸出: [0 0 0 0 0 0 0 77 88 0 99] // 在原來的基礎上追加了99
替換覆蓋(copy)
test := []int{1,2,3,4,5}
copy(info, test)
fmt.Println(info)
輸出:[1 2 3 4 5 0 0 77 88 0 99]
字符串也可以按照切片的方式進行操作(字符串截取功能,從第1位開始數)
str := "hello world"
fmt.Println(str[6:])// 輸出截取,這裏注意的是截取只能截取字符串類型的,其他類型截不了
輸出:world
以上是簡單的一些小案例,還有更多的一些語法技巧函數,可上Go官方文檔查看http://docscn.studygolang.com/doc/
二、變量
1、變量聲明
var a int//聲明一個整型類型的變量,可以保存整數數值
var b string//聲明一個字符串類型的變量
var c []float32//聲明一個32位浮點切片類型的變量,浮點切片表示由多個浮點類型組成的數據結構
var d func() bool//聲明一個返回值爲布爾類型的函數變量,這種形式一般用於回調函數,即將函數以變量的形式保存下來,在需要的時候重新調用這個函數
var e struct{//聲明一個結構體變量,擁有一個整型的x字段
x int
}
標準定義:var 參數名 類型
批量聲明
var (
a int
b string
c []float32
d func() bool
e struct{
x int
}
)
初始化變量(標準格式)
var 變量名 類型 = 表達式
例:小明考試考了100分
var score int = 100
初始化變量(短變量聲明)
score := 100
// 如果score已經被var初始化過,則這個時候會報錯,例如以下
var score int = 90
score := 80
// error : no new variables on left side of :=
// 報錯提示的原因是左邊沒有新的變量名出現,則不允許重新賦值
// ps:也可以支持多個變量一直賦值
info, score, x = 0, 1, 2
2、匿名變量(沒有名字並且不需要用到的變量,可減少內存空間)
在開發過程中,有時候調用某個方法後,發現一些參數是不需要的,但是又不想浪費內存去接收到,那麼可以用”_“下劃線進行代替
func item() (int,int) {
return 100, 200
}
a, _ := item()
fmt.Println(a)
輸出:100
// 當然,我們也可以在賦值的時候這麼做
_, score := 0, 80
fmt.Println(score)
輸出:80
Go在內存這方面還是很強大的,完全不用擔心內存溢出,可以大膽放心使用
三、函數
函數的常規定義
func 方法名(參數列表) 返回值 {
定義
}
例:
func item(a) int {
return 100
}
1、函數的值(閉包)
函數值不僅僅是一串代碼,還記錄了狀態。Go使用閉包(closures)技術實現函數值,Go程序員也把函數值叫做閉包。我們看個閉包的例子:
func f1(limit int) (func(v int) bool) {
//編譯器發現limit逃逸了,自動在堆上分配
return func (v int) bool { return v > limit}
}
func main(){
closure := f1(3)
fmt.Printf("%v\n", closure(1)) //false
fmt.Printf("%v\n", closure(3)) //false
fmt.Printf("%v\n", closure(10)) //true
}
ps:程序執行流程
1、程序進入main後,發現調用了f1方法並帶入了”3“,此時返回一個閉包
2、走到下面closure(1)時,程序發現有傳入閉包值”1“
3、程序走進上面的方法內,此時limit = 3, 閉包內的v = 1
4、走到下面的邏輯判斷中,引用閉包內的v,並且將v與limit做比較
5、最終得到結果,返回給下面的 fmt.Printf("%v\n", closure(1))進行輸出
6、依次類推
函數可變參數
可變參數,即參數不是固定死的一個值,可以有無限N個,例如fmt.Printf函數那樣, 但只有最後一個參數可設置爲可變參數
聲明
func 函數名(變量名...類型) 返回值
舉例:
func getData(str string, vals... int) (num int) {
for _,v := range vals {
num += v
}
num += len(str)
return
}
func main(){
fmt.Printf("%d\n", getData("abc", 1,2,3,4,5 ))
}
輸出:18
將傳入的1,2,3,4,5 循環追加給num值,最後再加上str的長度 15 + 3 = 18
注意:在for後面一點要加上匿名函數,否則始終不會循環追加最後一個值,如去掉加起來則爲13
getData第二個參數即最後一個參數則爲可變參數
2、函數的延遲執行 defer
包含defer語句的函數執行完畢後(例如return、panic),釋放堆棧前會調用被聲明defer的語句,常用於釋放資源、記錄函數執行耗時等,有一下幾個特點:
- 當defer被聲明時,其參數就會被實時解析
- 執行順序和聲明順序相反
- defer可以讀取有名返回值
//演示defer的函數可以訪問返回值
func f2() (v int) {
defer func (){ v++}()
return 1 //執行這個時,把v置爲1
}
//演示defer聲明即解釋
func f3(i int) (v int) {
defer func(j int) {
v+= j
} (i) //此時函數i已被解析爲10,後面修改i的值無影響
v = 9 // v = 9
i = i*2 // i = 20
return
}
//演示defer的執行順序,與聲明順序相反
func f4() {
defer func() {fmt.Printf("first\n")} ()
defer func() {fmt.Printf("second\n")} ()
}
func main(){
fmt.Printf("%d\n", f2()) // 13
fmt.Printf("%d\n", f3(10)) // 19
f4() //second\nfirst\n
最終輸出:
2
19
second
first
執行過程:
1、首先調用了f2,由於defer是在return執行後再去執行的,所以當return 1時,附加v++ 所以最終返回值爲2
2、調用了f3並傳入值爲10,進入到f3方法中,v = 9,i = 20,走到defer,此時i已經被解析成了10,所以後面的相乘無影響
3、接着進入defer後,設定了j值,此時j = i = 10,v是後面新賦的值,也沒有被解析,所以v+=j 則等於 v = 9+10 = 19,最後返回19
4、最後一步f4是返回的順序是相反的,則驗明瞭defer是在聲明的倒序執行的
ps:一般典型的用來計算耗時,資源關閉等,相關操作可按照業務邏輯編寫
Golang學習文章會持續更新,謝謝