最近接觸對象存儲,國際上鼎鼎有名的Amazon S3還有Google Cloud Service在國內因爲防火牆還有機房過遠的問題,並不能投入生產使用。國內有名的對象存儲,你們衆所周知的七牛雲,後臺就是Go語言實現的。對於第一個敢吃螃蟹的人,我一直很佩服。因而抱着憧憬的心態走進Go語言的大門。
首先,接觸一門語言,就從最囉嗦可是最不能缺乏的基礎語法和順序變成開始。對於接觸這些,我通常是從搭建好本身的編譯構建環境開始,首先下載Go語言SDK,國內下載地址:http://golangtc.com/download
我這裏用的是最新的1.7.2,若是你要用IDEA 的go plugin進行編程,則須要用1.4.2,不能用高版本的。以後,下載LiteIDE,進行編碼:http://www.golangtc.com/download/liteide
咱們打開LiteIDE,新建一個非GOPATH目錄下的示例項目(咱們這裏吐槽下LiteIDE,他並非一個很嚴謹,很好用,很完整的IDE,對於習慣了IDEA的懶人程序員,可能不太習慣。可是,迴歸原始也是頗有好處的),命名爲Gotest。
項目會自動生成目錄和代碼。咱們只保留main.go就能夠。Go語言有他智能的一面,首先擺上兩個原則:git
Go語言兼顧了自由性和嚴謹性:首先,對於變量的定義,咱們有三種方式,很自由。接着,沒用的元素在編譯時就不會經過。例如:沒用的包引入,沒用的變量定義,這些在編譯時就會報錯。
下面咱們寫一個小程序:
咱們在項目根目錄新建pkg和src兩個文件夾,src目錄存放咱們的源代碼,pkg是給go編譯器用的,會生成編譯好的文件,其實就是編譯好的庫文件。根目錄保留main.go
在src目錄下新建fundamental文件夾,在fundamental文件夾新建variables.go。
編寫源碼(這裏先提出一點Go語言不用分號分割,回車就能夠):程序員
package fundamental import "fmt" //包若是沒用,則會在編譯時報錯,這裏用了標準輸出函數 func Initialization() { //go,模塊中要導出的函數,必須首字母大寫。 var var1 int //變量若是沒有用過,也會在編譯時報錯,初始化爲默認值0 fmt.Println("var1:", var1) var var2 string //注意小寫s,初始化爲默認值"" fmt.Println("var2:", var2) var var3 [10]int //數組,初始化爲默認值[0 0 0 0 0 0 0 0 0 0] fmt.Println("var3:", var3) var var4 []int //動態數組,數組切片,初始化爲默認值[] fmt.Println("var4:", var4) var var5 struct { //至關於C語言中的結構體,,初始化爲默認值{0 ""} f int j string } fmt.Println("var5:", var5) var var6 *int //指針,初始化爲默認值<nil> fmt.Println("var6:", var6) var var7 map[string]int //Key爲string,value爲int,初始化爲默認值map[] fmt.Println("var7:", var7) var var8 func(a int) int //定義爲一個function,規定輸入輸出,初始化爲默認值<nil> fmt.Println("var8:", var8) var var9 = 10 //根據初始值自動判斷類型 fmt.Println("var9:", var9) var10 := 11 //第三種初始化 fmt.Println("var10:", var10) } func SwapDisplay1() { //常規思路的交換,利用a+b-a和a+b-b來達到交換的目的 var ( a = 19 b = -7 ) fmt.Println("Before swap:\n", "a:", a, ",b:", b) a = a + b b = a - b a = a - b fmt.Println("After swap:\n", "a:", a, ",b:", b) } func SwapDisplay2() { //Go語言交換,由於函數能夠返回多個值,並且支持相似於a,b=b,a的多重賦值語法 var ( a = 19 b = -7 ) fmt.Println("Before swap:\n", "a:", a, ",b:", b) a, b = swap(a, b) fmt.Println("After swap:\n", "a:", a, ",b:", b) } func swap(a int, b int) (int, int) { //go,對於模塊中不須要導出的函數,首字母不要大寫。 return b, a }
咱們總結下:github
1 變量有3種定義或初始化方式:golang
var var1 int var var9 = 10 var10 := 11
2.變量類型很是自由,有C語言的結構體,也有像Javascript那樣的函數類型變量。
3.變量賦值很自由,對於其餘語言,變量交換有兩種方式:一種是中間變量,另外一種是利用a+b-a和a+b-b來達到交換的目的。Go語言支持多重賦值,i,j=j,i編程
func SwapDisplay1() { //常規思路的交換,利用a+b-a和a+b-b來達到交換的目的 var ( a = 19 b = -7 ) fmt.Println("Before swap:\n", "a:", a, ",b:", b) a = a + b b = a - b a = a - b fmt.Println("After swap:\n", "a:", a, ",b:", b) } func SwapDisplay2() { //Go語言交換,由於函數能夠返回多個值,並且支持相似於a,b=b,a的多重賦值語法 var ( a = 19 b = -7 ) fmt.Println("Before swap:\n", "a:", a, ",b:", b) a, b = swap(a, b) fmt.Println("After swap:\n", "a:", a, ",b:", b) }
4.以上的多重賦值,也來源於Go語言的函數能夠返回多個值。小程序
func swap(a int, b int) (int, int) { //go,對於模塊中不須要導出的函數,首字母不要大寫。 return b, a }
5.Go語言的var關鍵字和import關鍵字都支持括號內多個定義,例如:數組
var( v1 int v2 string )
6.對於包外部可見的function,function名稱開頭必須大寫(就是說,利用開頭字母大寫的方法定義包外部可見能夠調用的function)
這裏咱們能夠調用的是Initialization(),SwapDisplay1(),SwapDisplay2()方法,而swap方法不能夠。
在main.go中編寫:markdown
// Gotest project main.go package main import ( "fmt" "fundamental" ) func main() { fundamental.Initialization() //go,模塊中要導出的函數,必須首字母大寫。 fmt.Println("Hello World!") fundamental.SwapDisplay1() //go,模塊中要導出的函數,必須首字母大寫 fundamental.SwapDisplay2() //go,模塊中要導出的函數,必須首字母大寫 }
編譯運行:ide
var1: 0 var2: var3: [0 0 0 0 0 0 0 0 0 0] var4: [] var5: {0 } var6: <nil> var7: map[] var8: <nil> var9: 10 var10: 11 Hello World! Before swap: a: 19 ,b: -7 After swap: a: -7 ,b: 19 Before swap: a: 19 ,b: -7 After swap: a: -7 ,b: 19
生成的文件:
如咱們以前所說,在pkg目錄下自動生成了.a庫文件。在根目錄下還生成了和項目名稱同樣的exe可執行文件。函數
Go語言的字面量是無類型的
在fundamental文件夾下新建constants.go:
package fundamental import "fmt" //包若是沒用,則會在編譯時報錯,這裏用了標準輸出函數 func ConstDefinition() { const PI_f32 float32 = 3.141592654 //不用像其餘語言那樣指定是float仍是double,末尾加上f,字面量常量都是無類型的,這裏其實是3.1415927 const PI_f64 float64 = 3.141592654 //不用像其餘語言那樣指定是float仍是double,末尾加上f,字面量常量都是無類型的,這裏其實是3.141592654 fmt.Println("PI_f32:", PI_f32) fmt.Println("PI_f64:", PI_f64) const PI = 3.141592654 //不指定類型也能夠,會自動匹配成能容納這個變量的浮點類型常量 fmt.Println("PI:", PI) const ( a, b, c = "a", 1, 3.0 d = "asd" ) fmt.Println("a:", a, ",b:", b, ",c:", c, ",d:", d) const ( //三種預約義常量,iota會在下一個const以前遞增,可是,必須在不一樣賦值語句才能遞增。 e1, e2 = true, false e3 = iota //0 e4 = iota //1 ) fmt.Println("e1:", e1, ",e2:", e2, ",e3:", e3, ",e4:", e4) const ( //iota必須在不一樣賦值語句才能遞增。 f1, f2 = iota, iota //0,0 f3, f4 = iota, iota //1,1 ) fmt.Println("f1:", f1, ",f2:", f2, ",f3:", f3, ",f4:", f4) }
總結以下幾點:
1.Go語言的字面量是無類型的,對於浮點型,不用像其餘語言那樣指定是float仍是double,末尾加上f,字面量常量都是無類型的
const PI_f32 float32 = 3.141592654 //不用像其餘語言那樣指定是float仍是double,末尾加上f,字面量常量都是無類型的,這裏其實是3.1415927 const PI_f64 float64 = 3.141592654 //不用像其餘語言那樣指定是float仍是double,末尾加上f,字面量常量都是無類型的,這裏其實是3.141592654
2.在定義常量時,不指定類型也能夠,會自動匹配成能容納這個變量的浮點類型常量
3.三種預約義常量(true,false,iota),iota會在下一個const以前遞增,可是,必須在不一樣賦值語句才能遞增。
const ( //三種預約義常量,iota會在下一個const以前遞增,可是,必須在不一樣賦值語句才能遞增。 e1, e2 = true, false e3 = iota //0 e4 = iota //1 ) const ( //iota必須在不一樣賦值語句才能遞增。 f1, f2 = iota, iota //0,0 f3, f4 = iota, iota //1,1 )
func TestBool() { var v1 bool //初始化爲bool類型,默認爲false fmt.Println("v1:", v1) v1 = true fmt.Println("v1:", v1) v2 := (1 >= 0 && 2 <= 3) //也能夠表達式賦值,須要加上括號 fmt.Println("v2:", v2) }
總結:
1. 布爾類型初始化,默認爲false
2. 布爾類型不支持其它賦值或者強制轉換,例如賦值爲1
func TestInt() { var a int8 a = 6 //int類型能夠指定長度 fmt.Println("a:", a) var b int32 b = 7.0000 //這個原本小數點全爲0的也能夠賦值給int類型,可是7.0001就不行了 b = int32(a) //同時,也不能將a賦值給b,由於不一樣類型,同時也不能互相比較 fmt.Println("b:", b) fmt.Println("b > 0.00:", b > 0.00) //不一樣類型也不能互相比較 fmt.Println("^b:", ^b) //其餘運算符都和其餘語言同樣,除了非運算,非運算符爲^ }
總結:
1. 不一樣類型的整型不能夠互相賦值,或者互相比較
2. 字面量無類型,能夠複製,能夠比較,可是必須爲整型
b = 7.0000 //這個原本小數點全爲0的也能夠賦值給int類型,可是7.0001就不行了
3. 其餘運算符都和其餘語言同樣,除了非運算,非運算符爲^
4. 通常都用int,uint來編程
func TestFloat() { var f1 float32 fmt.Println("f1:", f1) f2 := 12.0 //不能f2 = f1 ,f2爲float64 f3 := 11.9091 fmt.Println("isEqual(f2, f3, 1)", isEqual(f2, f3, 1)) } func isEqual(f1, f2, p float64) bool {//浮點數不能直接用==判斷相等,只能用精度比較 return math.Abs(f1-f2) < p }
總結:
1.不一樣類型的浮點型不能夠互相賦值,或者互相比較
2.浮點數不能直接用==判斷相等,只能用精度比較
func TestString() { str := "Hello World! by 張哈希" fmt.Println("str:", str) fmt.Println("len(str):", str)//利用內置函數len獲取長度 for i := 0; i < len(str); i++ {//遍歷 fmt.Println(i, str[i]) } for i, ch := range str {//以Unicode方式遍歷 fmt.Println(i, ch) } }
輸出:
str: Hello World! by 張哈希 len(str): Hello World! by 張哈希 0 72 1 101 2 108 3 108 4 111 5 32 6 87 7 111 8 114 9 108 10 100 11 33 12 32 13 98 14 121 15 32 16 229 17 188 18 160 19 229 20 147 21 136 22 229 23 184 24 140 0 72 1 101 2 108 3 108 4 111 5 32 6 87 7 111 8 114 9 108 10 100 11 33 12 32 13 98 14 121 15 32 16 24352 19 21704 22 24076