Golang 入門-基礎類型&函數定義篇

在上一篇文章中講述了配置與輸出,接下來我們進入下一步的學習

前言: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學習文章會持續更新,謝謝

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章