go函数使用(一)https://developer.aliyun.com/article/1391408
输出:
The minimum is: 0
The minimum in the array arr is: 1
- 使用结构:
定义一个结构类型,假设它叫 Options ,用以存储所有可能的参数:
type Options struct { par1 type1, par2 type2, … }
函数 F1 可以使用正常的参数 a 和 b,以及一个没有任何初始化的 Options 结构:
F1(a, b, Options {}) 。如果需要对选项进行初始化,则可以使用F1(a, b, Options {par1:val1, par2:val2}) 。- 使用空接口:
如果一个变长参数的类型没有被指定,则可以使用默认的空接口 interface{} ,这样就可以接受任何类型的参数。该方案不仅可以用于长度未知的参数,还可以用于任何不确定类型的参数。一般而言我们会使用一个 for-range 循环以及 switch 结构对每个参数的类型进行判断:
func typecheck(..,..,values … interface{}) { for _, value := range values { switch v := value.(type) { case int: … case float: … case string: … case bool: … default: … } } }
defer 和追踪
关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数
关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。
package main import "fmt" func main() { Function1() } func Function1() { fmt.Printf("In Function1 at the top\n") defer Function2() fmt.Printf("In Function1 at the bottom!\n") } func Function2() { fmt.Printf("Function2: Deferred until the end of the calling function!") }
输出:
In Function1 at the top
In Function1 at the bottom!
Function2: Deferred until the end of the calling function!
请将 defer 关键字去掉并对比输出结果。
使用 defer 的语句同样可以接受参数,下面这个例子就会在执行 defer 语句时打印 0 :
func a() { i := 0 defer fmt.Println(i) i++ return }
当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):
func f() { for i := 0; i < 5; i++ { defer fmt.Printf(“%d “, i) } }
上面的代码将会输出: 4 3 2 1 0 。
关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:
- 关闭文件流:
// open a file defer file.Close() - 解锁一个加锁的资源
mu.Lock() defer mu.Unlock() - 打印最终报告
printHeader() defer printFooter() - 关闭数据库链接
// open a database connection defer disconnectFromDB()
合理使用 defer 语句能够使得代码更加简洁。
以下代码模拟了上面描述的第 4 种情况:
package main import "fmt" func main() { doDBOperations() } func connectToDB() { fmt.Println("ok, connected to db") } func disconnectFromDB() { fmt.Println("ok, disconnected from db") } func doDBOperations() { connectToDB() fmt.Println("Defering the database disconnect.") defer disconnectFromDB() //function called here with defer fmt.Println("Doing some DB operations ...") fmt.Println("Oops! some crash or network error ...") fmt.Println("Returning from function here!") return //terminate the program // deferred function executed here just before actually returning, even if // there is a return or abnormal termination before }
输出:
ok, connected to db
Defering the database disconnect.
Doing some DB operations …
Oops! some crash or network error …
Returning from function here!
ok, disconnected from db
使用 defer 语句实现代码追踪一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:
func trace(s string) { fmt.Println("entering:", s) } func untrace(s string) { fmt.Println("leaving:", s) }
以下代码展示了何时调用两个函数:
package main import "fmt" func trace(s string) { fmt.Println("entering:", s) } func untrace(s string) { fmt.Println("leaving:", s) } func a() { trace("a") defer untrace("a") fmt.Println("in a") } func b() { trace("b") defer untrace("b") fmt.Println("in b") a() } func main() { b() }
输出:
entering: b
in b
entering: a
win a
leaving: a
leaving: b
6.5 内置函数
Go 语言拥有一些不需要进行导入操作就可以使用的内置函数。它们有时可以针对不同的类型进行操作,
例如:len、cap 和 append,或必须用于系统级的操作,例如:panic。因此,它们需要直接获得编译器
的支持。
以下是一个简单的列表,我们会在后面的章节中对它们进行逐个深入的讲解。
名称 说明
close 用于管道通信
len、cap
len 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);cap 是容
量的意思,用于返回某个类型的最大容量(只能用于切片和 map)
new、
make
new 和 make 均是用于分配内存:new 用于值类型和用户定义的类型,如自定义结
构,make 用户内置引用类型(切片、map 和管道)。它们的用法就像是函数,但是
将类型作为参数:new(type)、make(type)。new(T) 分配类型 T 的零值并返回其地
址,也就是指向类型 T 的指针(详见第 10.1 节)。它也可以被用于基本类型:
v := new(int) 。make(T) 返回类型 T 的初始化之后的值,因此它比 new 进行更多的
工作(详见第 7.2.3/4 节、第 8.1.1 节和第 14.2.1 节)new() 是一个函数,不要忘记它
的括号
Go入门指南
本文档使用 看云 构建 - 118 -
copy、
append
用于复制和连接切片
panic、
recover
两者均用于错误处理机制
print、
println
底层打印函数(详见第 4.2 节),在部署环境中建议使用 fmt 包
complex、
real imag
用于创建和操作复数(详见第 4.5.2.2 节)
名称 说明