文章目錄
網上有些很好的資料,貼一些連結:
http://www.cnblogs.com/AllenDang/archive/2012/03/03/2378534.html
http://www.infoq.com/articles/google-go-primer
筆者從中選出一些個人覺得有用的特性拿來隨便說說。
變數定義
GO最基本的變數聲明和初始化:
var sum int // Just a declarationvar total int = 42 // A declaration with initialization
在這裡,把類型寫在後面的原因是為了避免C中int *a,b;這樣的定義其實a和b的類型不同的問題(a是指標,b是整數)。
GO的變數定義有了自動推導類別的功能,寫慣了指令碼的同志肯定不會覺得name:="GOGOGO"是一個多麼酷的定義+初始化,但是,對於go這種非解釋的語言來說,這的確是一種進步。
另外,想要一次聲明多個變數可以使用如下的方式:
var (
i, j int
s string u, v, s = 2.0, 3.0, "bar"
)
Go的條件運算式和迴圈語句
go的條件運算式是沒有括弧的C運算式,即可以寫成這樣:
if blablabla {
}
另外,Go也繼承了C的可以在if中執行過程的方法,例如if(a= function(), a)blablabla, 在Go中只是將逗號換成了分號;
go的迴圈語句只支援for一種,而且,go中沒有辦法寫出do while那種至少執行一次的迴圈!
(在這裡插一句廢話,支援go語言的vim外掛程式:http://www.vim.org/scripts/download_script.php?src_id=11734)
for在go中可以這麼用:
for a<b {}
for i:=0;i<10;i++{}
for i:= range("hello"){}
for{}
那個range版本的很爽,達到了指令碼語言的程度,和perl、python什麼的有一拼,比如遍曆一個map結構(會在下文中詳述):
package main import "fmt"func main() { fmt.Println("Hello, 世界") _map := map[string]int{"HIT":1,"PKU":2} for i,value := range _map{ fmt.Println(i, value) } }
在這一部分的最後,說說go裡面的switch語句,將switch作為迴圈部分的壓軸是絕對值得的。go中的switch語句多了如下的特性:
- Cases can be comma-separated lists of values, and fall-through is no longer the default behavior
情況之間可以使用逗號分隔,並且向下透傳不再是預設的行為了,這個特性意味著可以寫出如下的語句:
var result int
switch byte {
case 'a', 'b':
result = 1
default:
result = 0
}
see?no break at all
- Go switches can match on much more than integers and
characters. Any valid expression can be the value of a case statement
switch在go中可以使用有效條件運算式最為case的條件啦~~例如:
switch result := calculate(); true {
case result < 0:
/* negative */
case result > 0:
/* positive */
default:
/* zero */
}
但是,switch後面的true不要忘了~
函數個人感覺,go的函數有一點賤賤的,為啥呢?因為它的大括弧不讓放在第二行T_T但是go的函數也是有特點的:
- 使用關鍵字func表明其函數的身份 func fun(){}
- 延續了避免定義錯誤類型的方式 func sum(a, b int)int{return a+b}
- 倒數第二壓軸,可以返回多個數值,來一個簡單的例子,例如:func multiReturn(a, b int) (int,int){return a,b}
因為該部分在C中是不存在的,這裡詳細描述一下:
多值返回的時候,傳回值也可以是具名的變數:
func divide(a, b int) (quotient, remainder int) {
quotient = a / b
remainder = a % b
return
}
由於這種特性,就不用再像C++中使用參數的順序和參數是否具有const特性來區分是輸入參數還是輸出參數了,並且,可以使用更高端的傳回值處理方法:
if result, ok := moreMagic(); ok {
/* Do something with result */
}
函數的最後一個參數可以總返回一個bool型的值,用於確定當前的函數是否正確返回了資料。
- 壓軸大戲來啦!Go中可以存在匿名函數!真箇真心牛逼,不用在內部使用的函數前面後面各種添加__了,儘管以失去了裝B的樂趣為代價:)
func makeAdder(x int) (func(int) int) {
return func(y int) int { return x + y }//Look at me! Am I hot? Wanna a try?
}
func main() {
add5 := makeAdder(5)
add36 := makeAdder(36)
fmt.Println("The answer:", add5(add36(1))) //=> The answer: 42
}
Go中的基本類型
go和C比添加了一些新貨(為啥總和C比較。。。其實這些新貨在指令碼裡面都有,但是,總有一個但是,這些新貨在非解釋型的語言中出現,的確是新貨,好吧。。。),數組,unicode的string,slice(從perl偷來的吧?)和map。
- ARRAY:go中的array和c的一樣,都不動態,他們的大小是他們類型的一部分,並且都在編譯器決定。不再展開敘述
- SLICE: 這個在perl中的翻譯是切片,在這裡也引用這一翻譯,該資料結構的意義為:其為某個數組的片段,以下有一些定義方法:
/* Construct a slice on ary that starts at s and is len elements long */
s1 := ary[s:len]/* Omit the length to create a slice to the end of ary */
s2 := ary[s:]
/* Slices behave just like arrays */
s[0] == ary[s] //=> true
// Changing the value in a slice changes it in the array
ary[s] = 1
s[0] = 42
ary[s] == 42 //=> true
The segment of the array that the slice references can be changed by assigning a new slice to the same variable(這個不太好翻譯,大概的意思就是切片引用的數數組部分能夠被賦新值給原來的變數來進行改變。。。下面用一些實際的例子來闡述):
/* Move the start of the slice forward by one, but do not move the end */
s2 = s2[1:]
/* Slices can only move forward */
s2 = s2[-1:] // this is a compile error
可以試試如下的代碼,看看結果就比較明白了:
str := "hello"
s := str[2:]
fmt.Println(s, str)
s = s[1:]
fmt.Println(s, str)
切片的長度是可以改變的,只要不超過其引用的數組的最大長度即可。這玩意存在的意義說白了就是能夠更有效使用數組。可以使用內建的cap函數擷取切片的容量。
下面有一個簡單的例子:
a := [...]int{1,2,3,4,5} // The ... means "whatever length the initializer has"
len(a) //=> 5
/* Slice from the middle */
s := a[2:4] //=> [3 4]
len(s), cap(s) //=> 2, 3
/* Grow the slice */
s = s[0:3] //=> [3 4 5]
len(s), cap(s) //=> 3, 3
/* Cannot grow it past its capacity */
s = s[0:4] // this is a compile error
Often, a slice is all that is needed for a program. In that case, a programmer need not have an array at all. Go offers two ways to make slices directly without ever referencing the underlying storage:
說到這裡,一般使用GO語言的程式員都可以拋棄數組這個東西了,切片已經滿足了絕大多數的需求。
/* literal 常量切片*/
s1 := []int{1,2,3,4,5}
/* empty (all zero values) 空的切片數組,可以使用內建的make函數產生*/
s2 := make([]int, 10) // cap(s2) == len(s2) == 10
- MAP: C中最為稀缺的基本資料結構,至於怎麼使用,代碼伺候:
m := make(map[string] int) // A mapping of strings to ints/* Store some values */m["foo"] = 42m["bar"] = 30/* Read, and exit program with a runtime error if key is not present. */x := m["foo"]/* Read, with comma-ok check; ok will be false if key was not present. */x, ok := m["bar"]/* Check for presence of key, _ means "I don't care about this value." */_, ok := m["baz"] // ok == false/* Assign zero as a valid value */m["foo"] = 0;_, ok := m["foo"] // ok == true/* Delete a key */m["bar"] = 0, false_, ok := m["bar"] // ok == false