Go-函數高級使用-條件分支-包管理-for循環-switch語句-數組及切片-與或非邏輯符

科普 python 註釋 #

爲何幾乎就 python 中的註釋是 # ?python

  • 起初 python 在 linux 中用的最多,linux 中大量的配置、shell 腳本等都是 # 做爲註釋的,因此 python 的註釋也就沿用了 #

代碼幾乎都要寫在 main 函數裏執行(本文寫的都是僞代碼)linux

本文僅是跟着視頻學習作的筆記,並未花時間去校對,若有錯誤,別太當真git

重複定義是錯誤的,個人代碼裏有不少重複定義,只是爲了寫出來,你 copy 過去用的時候記得把重複定義刪掉github

函數高級

內層函數:定義在函數內部的函數shell

閉包函數:定義在函數內部,對外部做用域有引用(閉包函數本質也是內層函數)django

  • go 中函數內部定義的函數是不能有名的,須要定義匿名函數:沒有名字

在 go 語言中沒有像 python 中的裝飾器語法糖,但能夠本身實現相似功能flask

// 內層函數
func test(a int) (func()) {
    // var c int = 100
    b := func() {
        fmt.println("我是內層函數(定義在了函數內部,但沒有引用外部做用域)")
	}
}

// 閉包函數
func test(a int) (func()) {
    // var c int = 100
    b := func() {
        fmt.println(a)  // 是閉包函數,自己也是內層函數
	}
}


// 模仿 python 裝飾器的寫法
// 定義一個函數,傳入函數,返回函數
func test(a func()) func()  {
	b:= func() {
		fmt.Println("我先執行")
		a()
		fmt.Println("函數執行完了")
	}
	return b
}

func test2()  {
	fmt.Println("xxxx")
}

func main() {
	a := test2
	a = test(a)
	a()
	//我先執行
	//xxxx
	//函數執行完了
}

給類型取別名 type MyFunc func(a, b int) func()數組

取了別名以後,用了別名的變量和原來的類型不是同一個類型了閉包

// 給類型命別名
func main() {
    type MyInt int
    var a MyInt = 10
    var b int = 90
    // a = b  // 會報錯,類型不匹配
    a = MyInt(b)  // 強轉成一個類型
	fmt.Println(a)
	// 90
}


// 用在函數上面來簡化寫法
type MyFunc func(a int,b int) func()

type MyInt int
func test() (MyFunc)  {
	c:= func(a int,b int) func(){
		return func() {
            
		}
	}
	return c
}
func main() {
	var a MyInt=10
	var b int =90
	a=MyInt(b)
	fmt.Println(a)
	// 90
}

if else if else

跟 js 的寫法差很少架構

  • if 條件 { 三個之間不能有換行(全部語言每一句結束都應該有一個 ;,不少語言都作了封裝),若是加了換行,go 會自動在條件後面加上 ;,那麼語義就錯了

  • 在條件中能夠定義變量,可是它的做用域範圍只在 if 判斷內部使用

package main

import "fmt"

func main() {
	if a := 90; a > 90 {
		fmt.Println("a>90")
	} else if a > 70 {
		fmt.Println("a>70")
	} else {
		fmt.Println(a)
	}
}
//a>70

包管理

go 的包管理一直被人所詬病(go 仍是一門比較年輕的語言,須要時間來成長)

1)一般狀況下,包名就是文件夾,在同一個文件夾下的 go 文件,文件裏的包名必須一致

2)同一個包下定義的東西(變量、常量、函數)不能重名

  • 下面的兩個文件同在 mypackage 包下(裏面寫的 package),因此第二次寫 test 函數時,goland 編輯器就直接報錯了

3)在包內定義的函數若是是小寫字母開頭,表示只能在包內使用(外部沒法引用)

  • 要想在外部使用,必須首字母大寫(函數定義的時候)

    package main
    import "fmt"
    import "mypackage"
    
    func main() {
    	mypackage.Test1()
    	fmt.Println("xxx")
    }

4)go 裏導包只能導到包名那一層,不能說導裏面的方法屬性這些(import 包名

5)全部的包都必須在 gopath 路徑下的 src 文件夾下

  • 目前 go 的包管理還不是很成熟,若是依賴了第三方包的不一樣版本,會不能兼容(只能有一個版本)

    若是非要兼容兩個版本,開發的時候能夠暫時先把 gopath 改一下,這樣就能夠放另外一個版本了

Go 語言架構

GOPATH 的工做區包含 bin、src 和 pkg(沒有這三個文件夾時須要本身建立)

  • src ------- 源碼(包含第三方的和本身項目的)
  • bin ------- 編譯生成的可執行程序
  • pkg ------ 編譯時生成的對象文件

下載第三方包

go 是一個開源的社區語言,因此並無 python 那樣一個專門的 pipy 來下載模塊鏡像,都是去各個地方下載

go get github.com/astaxie/beego(地址)

比較熱門的框架

  • beego 是中國人寫的,因此官網文檔也是中文的
  • gin 是外國人寫的

go 的優勢之一

  • go 寫小接口很快,也很簡單,部署也很是方便(微服務可能比 flask 寫起來還要快)

能夠了解一下 Supervisord(beego 官網文檔裏有)

  • 是一個用python寫的進程管理工具
  • 因爲 beego 的做者之一是 Python 的忠實擁護者之一,因此 orm 設計沿用了 django 的 orm

for 循環

for 循環的幾種寫法

// 不能重複定義,這裏面的代碼只是案例
package main

import "fmt"

func main() {
	// 基礎寫法
	for i := 0; i < 10; i++ {
		fmt.Println(i)
	}

	// 三部分均可以省略
	i := 0
	for ; i < 10; i++ {
		fmt.Println(i)
	}

	i := 0
	// for ;i<10; {  // 或
	for i < 10 { // 等同於 python 裏的 while 循環 --> while True ==》 for True
		fmt.Println(i)
		i++
	}

	// 死循環
	// for ;; {  // 或
	for {
		fmt.Println("xxx")
	}

	// 注意下做用域範圍(循環裏定義的變量只能在循環裏用)

	// --------中斷或跳過本次循環--------
	// 用的是 break 和 continue,和其餘語言的用法是同樣的

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

}

switch 語句

package main

import "fmt"

func main() {
	//a := 10
	//switch a {
	//case 1:
	//	fmt.Println("1")
	//case 2, 3, 4:
	//	fmt.Println("2-4")
	//	fallthrough // 只要讀到這個,會無條件執行下面一個 case 內容
	//case 5:
	//	fmt.Println("5,a 是 2-4時順帶執行我")
	//default: // 都不匹配,會執行這個
	//	fmt.Println("都不是")
	//}
	////都不是

	// 無表達式的 switch
	a := 10
	switch {
	case a > 10:
		fmt.Println("a大於10")
	case a < 10:
		fmt.Println("a小於10")
	default:
		fmt.Println("a等於10")
	}
	// a等於10
}

數組及數組切片

  • 數組是同一類型元素的集合
  • 在定義階段,長度和類型就固定了,之後不能更改(這和 python 的列表有很大的區別)
  • 數組不支持負數索引
// 不能重複定義,這裏面的代碼只是案例
package main
import "fmt"

func main() {
	var a [5] int // 定義了一個長度爲5的 int 類型數組
	fmt.Println(a)
	// [0 0 0 0 0]

	a[1] = 100 // 索引是從 0 開始的
	fmt.Println(a)
	// [0 100 0 0 0]

	// 定義並賦初值
	var a [6]int = [6]int{1,2,3,4,5,6}
	var a = [6]int{1,2,3}  // int 類型省略的幾個自動用 0 填充
	
	a := [100]int{98:99} // 把第99個(索引是98)設置成99
	a := [100]int{1,2,3,98:99,87:88}
	// 不支持負數索引
    
	var a = [...]int{}  // 不是數組不定長
	fmt.Println(a)
	// []

	var a = [...]int{1,2,4}
	fmt.Println(a)
	// [1 2 4]

}
  • 數組是值類型,全部函數傳參都是 copy 傳遞(即 python 中的不可變類型)
package main
import "fmt"

func main() {
	a := [4]int{1,2,3}
	test7(a)
	fmt.Println(a)
}

func test7(b [4]int)  {
	b[0]=100
	fmt.Println(b)
}

// [100 2 3 0]
// [1 2 3 0]

go 1.5版本以前都是用C寫的,但後面就開始用go語言寫了

  • 數組的大小也是類型的一部分
// a 和 b 不是同一個類型
var a [4]int
var b [5]int
// 不一樣類型沒法直接賦值,也沒法直接作大小比較

數組迭代

package main
import "fmt"

func main() {
	var a [4]int = [4]int{1,2,}
	for i:=0;i<len(a);i++{  // len 能夠獲取數組長度
		fmt.Println(a[i])
	}
	//1
	//2
	//0
	//0

	// 經過 range 迭代(range是一個關鍵字)
	for i, v := range a {  // for 索引,值 range 可迭代對象
		fmt.Println("-----", i)  // 索引
		fmt.Println(v)  // 值
	}
	//----- 0
	//1
	//----- 1
	//2
	//----- 2
	//0
	//----- 3
	//0

	for i := range a {  // 一個值就是索引
		fmt.Println("-----", i)
	}
	//----- 0
	//----- 1
	//----- 2
	//----- 3
}

多維數組

package main
import "fmt"

func main() {
    var a [7][2]int
    fmt.Println(a)
    // [[0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]

    a[0][1]=100
    fmt.Println(a)
    // [[0 100] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]]
}

與或非 && || !

package main
import "fmt"
func main() {
	a := 13
	if !(a < 1 && a > 0 || a == 6) {
		fmt.Println("success.")
        // success.
	}
}

做業

  1. 寫一個閉包函數
  2. 定義一個包,內部寫一個test函數,只給包內部用,寫一個Test1函數,給外部包用,在main包內調用
  3. 使用go語言打印99乘法表
  4. 定義一個長度爲100的數組,初始化前5個值都爲8,第66個值爲66
  5. 經過兩種方式循環打印出上面的數組
  6. 將上面的數組的數據倒序放在另外一個100長的數組中
相關文章
相關標籤/搜索