GoLang 學習筆記(一)

main 包中的main函數是程序的入口;java

包的兩種導入方式

1 逐個導入python

import "fmt"
import "math"
複製代碼

2 分組導入linux

import (
	"fmt"
	"math"
)
複製代碼

官方建議使用分組導入的方式數組

導出名

在 Go 中,若是一個名字以大寫字母開頭,那麼它就是已導出的;在導入一個包時,你只能引用其中已導出的名字。任何「未導出」的名字在該包外均沒法訪問。閉包

例如math 包中的Pi是導出的,pi是未導出的,執行程序時math.pi會報錯,而math.Pi能夠正常運行函數

函數

函數能夠沒有參數或接受多個參數;ui

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}
複製代碼

注意:當連續兩個或多個函數的已命名形參類型相同時,除最後一個類型之外,其它均可以省略。spa

func add(x, y int) int {
    return x + y
}
複製代碼

上面的函數中線程

x int, y int 
複製代碼

被縮寫爲指針

x, y int
複製代碼

多值返回

函數能夠返回任意數量的返回值。

func swap(x, y string) (string, string) {
	return y, x
}
複製代碼

變量

var 語句用於聲明一個變量或一個變量列表。

var c bool
var python, java bool
複製代碼

短變量

只在函數內有效的變量相似於Java中的局部變量,使用:= 符號聲明。

func main() {
    k := 3
}
複製代碼

注意::= 結構不能在函數外使用。

基本類型

bool 布爾

string 字符串

int int8 int16 int32 int64 整形

uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 的別名

rune // int32 的別名,表示一個 Unicode 碼點

float32 float64 浮點

complex64 complex128

注意:int, uint 和 uintptr 在 32 位系統上一般爲 32 位寬,在 64 位系統上則爲 64 位寬。 當你須要一個整數值時應使用 int 類型,除非你有特殊的理由使用固定大小或無符號的整數類型

類型轉換

能夠使表達式 T(v) 將值 v 轉換爲類型 T。例如:

var i int = 42
var f float64 = float64(i)
複製代碼

注意:Go 在不一樣類型的項之間賦值時必需要顯式轉換。

常量

常量的聲明與變量相似,使用 const 關鍵字。

常量能夠是字符、字符串、布爾值或數值。

常量不能用 := 語法聲明。

const Pi = 3.14
複製代碼

循環結構

Go 只有一種循環結構:for 循環

for i := 0; i < 10; i++ {
	sum += i
}
複製代碼

i := 0 初始化語句 i < 10 條件表達式 i++ 後置語句

和Java很是像了。

初始化語句和後置語句也是可選的

for ; sum < 1000; {
	sum += sum
}
複製代碼

無限循環

for {
}
複製代碼

if

if 語句與 for 循環相似,表達式外無需小括號 ( ) ,而大括號 { } 則是必須的。

if x < 0 {
	return sqrt(-x) + "i"
}
複製代碼

if 語句能夠在條件表達式前執行一個簡單的語句,該語句聲明的變量做用域僅在 if 以內。

if v := math.Pow(x, n); v < lim {
	return v
}
複製代碼

switch

switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        fmt.Printf("%s.\n", os)
}
複製代碼

case 無需爲常量,且取值沒必要爲整數。

沒有條件的 switch

沒有條件的 switch 同 switch true 同樣,一般用來代替較多的if-then-else。

func main() {
    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }
}
複製代碼

defer

defer 語句會將函數推遲到外層函數返回以後執行。例如:

func main() {
    defer fmt.Println("world")
    fmt.Println("hello")
}
複製代碼

結果爲:

hello
world
複製代碼

原理:推遲的函數調用會被壓入一個棧中。當外層函數返回時,被推遲的函數會按照後進先出的順序調用。

指針

Go 擁有指針。指針保存了值的內存地址。類型 *T 是指向 T 類型值的指針。其零值爲 nil。

var p *int

& 操做符會生成一個指向其操做數的指針。

i := 42

p = &i

星號操做符表示指針指向的底層值。

fmt.Println(*p) // 經過指針 p 讀取 i 結果爲42

*p = 21 // 經過指針 p 設置 i

fmt.Println(*p) //結果爲21

結構體

相似於Java中的實體,一個結構體(struct)就是一組字段(field)。

type Vertex struct {
	X int
	Y int
}

func main() {
	fmt.Println(Vertex{1, 2})
}
複製代碼

注意:結構體中的字段也能夠經過指針來訪問。

數組

表達式:[n]T 表示擁有 n 個 T 類型的值的數組。

var a [10]int
複製代碼

注意:數組的長度是其類型的一部分,所以數組不能改變大小。

切片

切片爲數組元素提供動態大小的、靈活的視角,在實踐中,切片比數組更經常使用。

類型 []T 表示一個元素類型爲 T 的切片。

切片經過兩個下標來界定,即一個上界和一個下界,兩者以冒號分隔:

a[low : high]

它會選擇一個半開區間,包括第一個元素,但排除最後一個元素。

如下表達式建立了一個切片,它包含 a 中下標從 1 到 3 的元素:

a[1:4]

切片並不存儲任何數據,它只是描述了底層數組中的一段。

更改切片的元素會修改其底層數組中對應的元素。

與它共享底層數組的切片都會觀測到這些修改。

對於數組

var a [10]int 來講,如下切片是等價的:

a[0:10]
a[:10]
a[0:]
a[:]
複製代碼

切片的長度就是它所包含的元素個數,能夠經過len(s)獲取 切片的容量是從它的第一個元素開始數,到其底層數組元素末尾的個數,能夠經過cap(s)獲取。

nil 切片

切片的零值是 nil。

nil 切片的長度和容量爲 0 且沒有底層數組。

切片能夠用內建函數 make 來建立,這也是建立動態數組的方式。

切片中能夠包含其餘切片。

函數的閉包?

方法

Go 沒有類。不過你能夠爲結構體類型定義方法。

方法就是一類帶特殊的 接收者 參數的函數。

方法接收者在它本身的參數列表內,位於 func 關鍵字和方法名之間。

在此例中,Abs 方法擁有一個名爲 v,類型爲 Vertex 的接收者。

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}
複製代碼

注意:方法只是個帶接收者參數的函數。

非結構體也可定義方法,例如:

type MyFloat float64
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
 	}
	return float64(f)
}
複製代碼

接口類型

接口類型 是由一組方法簽名定義的集合,接口類型的變量能夠保存任何實現了這些方法的值。

Go 程

Go 程(goroutine)是由 Go 運行時管理的輕量級線程。

go f(x, y, z)會啓動一個新的 Go 程並執行

f(x, y, z)f, x, y 和 z 的求值發生在當前的 Go 程中,而 f 的執行發生在新的 Go 程中。

Go 程在相同的地址空間中運行,所以在訪問共享的內存時必須進行同步。

信道

信道是帶有類型的管道,適合在各個 Go 程間進行通訊。你能夠經過它用信道操做符 <- 來發送或者接收值。

ch <- v    // 將 v 發送至信道 ch。

v := <-ch  // 從 ch 接收值並賦予 v。(「箭頭」就是數據流的方向。) 
複製代碼

和映射與切片同樣,信道在使用前必須建立:

ch := make(chan int)
複製代碼

默認狀況下,發送和接收操做在另外一端準備好以前都會阻塞。這使得 Go 程能夠在沒有顯式的鎖或競態變量的狀況下進行同步。

帶緩衝的信道

信道能夠是 帶緩衝的。將緩衝長度做爲第二個參數提供給 make 來初始化一個帶緩衝的信道:

ch := make(chan int, 100)
複製代碼

僅當信道的緩衝區填滿後,向其發送數據時纔會阻塞。當緩衝區爲空時,接受方會阻塞。

相關文章
相關標籤/搜索