Switch
type switch
通過type switch可以來動態發現interface的類型。下面的type switch使用類型斷言,關於switch以及類型判斷,可以借鑑下下面的代碼。
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
Functions
多個返回值
Go的一大特徵就是函數和方法能返回多個值,不像C++,Java,這個特性在很多情況下可以使代碼變得簡潔。再加上go沒有throw exception,額外返回error就顯得特別重要,下面的代碼就是示例。
func (file *File) Write(b []byte) (n int, err error)
func nextInt(b []byte, i int) (int, int) {
for ; i < len(b) && !isDigit(b[i]); i++ {
}
x := 0
for ; i < len(b) && isDigit(b[i]); i++ {
x = x*10 + int(b[i]) - '0'
}
return x, i
}
for i := 0; i < len(b); {
x, i = nextInt(b, i)
fmt.Println(x)
}
Named result parameters
函數返回結果變量可以指定名稱,並且在函數體中像使用其他變量一樣使用。指定名稱後,這些變量就會被初始化爲零值,如果函數直接return,後面沒跟變量,那麼就會採用結果變量當前的值作爲返回結果。
這種使用方式不是強制的,但是在一些情況下也是會讓代碼變得更短、更簡潔。
func ReadFull(r Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
Data
new與make
go有兩個分配原語操作,分別是內置的函數 new 和 make 。它們是有區別的,也應用在不同的類型上,這個可能會讓人很困擾,我們挨個說下。首先是new,它是一個可以分配內存的內置函數,但是和其他語言不同,new 並不初始化內存,只是賦予個零值。例如 new(T),會分配爲T的零值,然後返回它的地址,也就是 *T,一個指向分配的零值的指針。
type Person struct {
Name string
Age int
City string
Man bool
}
per1 := new(Persion)
per2 := &Person{}
per3 := &Person{
Name : "Mike",
Age : 24
City : "Beijing",
Man : true,
}
per1採用new來創建一個Person類型的指針,作用其實和使用struct 字面量的方式創建per2差不多。
make函數與new不一樣,它只用來創建map,slice和channel,並且返回一個初始化了的(不是零值),類型爲T的值(不是指針)。這三種類型是無法使用new函數的,因爲這三個類型背後引用了使用前必須初始化的數據結構。
簡單的說,new只分配內存,make用於slice,map,和channel的初始化
未完待續