Go语言的过程式编程 | 字数总计: 1.5k | 阅读时长: 6分钟 | 阅读量: |
Go语言中常用的内置函数
函数
用法
append(s, …)
将s后面的所有参数追加到切片s中,如果容量不够,则新建一个切片
cap(x)
返回切片或者通道的容量,数组的长度
len(x)
返回切片、数组或者通道的长度
close(ch)
关闭通道,即不可以再往通道中写入值,但还可以读取
complex(r, i)
生成一个复数
copy(dist, src)
将切片src中的项复制到切片dist中,或者讲字符串src复制到[]byte类型的切片dist中
delete(m, k)
从映射m中删除键值为k的项
real(cx)
返回复数cx的实部
imag(cx)
返回复数cx的虚部
make(T, l, c)
创建一个切片、通道或者映射
new(T)
一个指向类型为T的值的指针
panic(x)
抛出一个运行时异常,其值为x
recover()
捕获一个运行时异常
Go语言赋值
Go语言中的自增自减运算符都是后置的,且没有返回值。
可以使用=
来给变量赋值,如果前面没有加var
,那么变量必须是已经存在的。
可以使用逗号同时给多个变量赋值。a, b, c = 2, 3, 4
。
可以使用_
来忽略赋值,它与任意类型兼容。
可以使用:=
来同时声明和赋值一个变量。
当使用逗号和:=
来给多个变量赋值时,要求其中至少有一个变量是新建的。
如果函数声明了返回值变量的名字,那么它在刚开始的时候会被初始化为其类型的零值。
函数在返回的时候如果没有明确的指定变量名,那么它将返回函数声明中的变量。
类型
Go语言使用result := Type(expr)
来进行类型转换。
1 2 3 4 5 6 7 8 package mainimport "fmt" func main () { runeSlice := []rune {'a' , 'b' , 'c' } str := string (runeSlice) fmt.Println(runeSlice) fmt.Println(str) }
interface{}
类型用于表示空接口,它可以表示任意类型的值。
expr.(Type)
用于判断expr是不是类型Type。安全类型的成功判断返回expr的值和true,安全类型的失败判断返回该类型的零值和false。非安全类型的成功判断返回expr的值,失败触发panic。
1 2 3 4 5 6 7 8 9 10 11 package mainimport "fmt" func main () { var i interface {} = 99 var s interface {} = []string {"left" , "right" } j := i.(int ) fmt.Printf("%T -> %d\n" , i, j) fmt.Printf("%T -> %q\n" , s, s) }
分支
if
语句可以有可选的声明语句,在该语句中定义的变量其作用域限制在if语句之类。
1 2 3 4 5 6 7 if optionalStatement; booleanExpression { block } else if optionalStatement1; booleanExpression1 { block1 } else { block2 }
switch
语句默认不会向下贯穿,需要使用fallthrough
语句。
1 2 3 4 5 switch optionalStatement; optionalExpression {case expressionList1: block1... default : blockN}
例如:
1 2 3 4 5 6 7 8 switch Suffix(file) {case ".gz" : return GzipFileList(file) case ".tar" , ".tar.gz" , ".tgz" : return TarFileList(file) case ".zip" : return ZipFileList(file) }
1 2 3 4 5 switch x.(type ) {case bool : block0case int , int8 , int16 : block1default : blockN}
for循环语句
1 for optionalPrestatement; booleanExpress; optionalPoststatement { block }
1 2 for idx, char := range aString { block }for idx := range aString { block }
1 2 for idx, item := range anArrayOrSlice { block }for idx := range anArrayOrSlice { block }
1 2 for key, value := range aMap { block }for key := range aMap { block }
1 for item := range aChannel { block }
select语句 select语句用来从多个通道中接收或发送数据。其语法如下:
1 2 3 4 5 6 select {case sendOrReceive1: block1... case sendOrReceive2: block2default : blockD}
如果没有default语句,那么select语句是阻塞的,直到其中的一个channel可以执行。如果有default语句,那么select语句是非阻塞的,如果没有channel满足条件则会执行默认语句。
defer语句 defer语句的执行时机是:
所在函数返回之前,返回值计算完成之后执行。
多个defer语句以LIFO(Last In First Out)的方式执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport "fmt" func main () { fmt.Println(add1(1 )) } func add1 (a int ) (result int ) { defer func () { result = 10 }() defer func () { result = 20 }() result = a + 1 return result }
panic和recover函数 不同于错误,异常是指不可能发生的情况发生了,通常是程序本身的问题,我们希望尽早发现问题所以通过调用panic函数抛出异常。panic被调用后,调用函数会中止执行,然后所有延迟执行的语句会执行,最后返回到上一层调用函数重复这样的过程直到main函数终止程序。 recover函数可以捕获异常并终止panic函数的冒泡。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func ConvertInt64ToInt (x int64 ) int { if math.MinInt32 <= x && x <= math.MaxInt32 { return int (x) } panic (fmt.Sprintf("%d is out of the int32 range" , x)) } func IntFromInt64 (x int64 ) (i int , err error) { defer func () { if e:= recover (); e != nil { err = fmt.Errorf("%v" , e) } }() i = ConvertInt64ToInt(x) return i, nil }
自定义函数
Go语言可以在参数列表里的最后一个参数类型前面使用…实现可变参数
1 2 3 4 5 6 7 8 9 10 11 12 package mainimport "fmt" func main () { test(3 , "hello" , "world" ) } func test (n int , strs ...string ) { fmt.Println(strs) fmt.Println(n) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" type Options struct { n int str string } func main () { test(Options{n: 15 , str: "hello world" }) test(Options{n: 16 }) } func test (options Options) { fmt.Println(options.n) fmt.Println(options.str) }
init和main函数不接受任何参数也不返回任何值,init在main函数调用之前执行
闭包是指捕获了和它在同一作用域常量或者变量的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "fmt" "strings" ) func main () { addjpg := MakeAddSuffix(".jpg" ) addpng := MakeAddSuffix(".png" ) fmt.Println(addjpg("hello" )) fmt.Println(addpng("hello.png" )) } func MakeAddSuffix (suffix string ) func (string ) string { return func (name string ) string { if !strings.HasSuffix(name, suffix) { return name + suffix } return name } }