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的初始化
未完待续