1 函数的定义
注: 小写字母开头的函数, 变量和类型只在本包内可见,大写字母开头的函数才能被其他包使用。
package mymath
import "errors"
func Add(a int, b int) (ret int, err error) {
if a < 0 || b < 0 { // 假设这个函数只支持两个非负数字的加法
err= errors.New("Should be non-negative numbers!")
return
}
return a + b, nil // 支持多重返回值
}
如果参数列表中若干个相邻的参数类型的相同,比如上面例子中的 a 和 b ,则可以在参数列表中省略前面变量的类型声明
func Add(a, b int)(ret int, err error) {
// ...
}
// 如果返回值列表中多个返回值的类型相同,也可以用同样的方式合并。如果函数只有一个返回值,也可以这么写:
func Add(a, b int) int {
// ...
}
2 函数的调用
import "mymath"// 假设Add被放在一个叫mymath的包中
// ...
c := mymath.Add(1, 2)
3 不定参数
指函数传入的参数个数为不定数量。
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
从内部实现机理上来说,类型 …type 本质上是一个数组切片,也就是 []type ,
这也是为什么上面的参数 args 可以用 for 循环来获得每个传入的参数。
假如没有 …type 这样的语法糖,开发者将不得不这么写:
func myfunc2(args []int) {
for _, arg := range args {
fmt.Println(arg)
}
}
但从调用方来说,情形则完全不同:我们不得不加上 []int{} 来构造一个数组切片实例。
myfunc2([]int{1, 3, 7, 13})
如果你希望传任意类型,可以指定类型为interface{}
package main
import "fmt"
func MyPrintf(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case int64:
fmt.Println(arg, "is an int64 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
}
func main() {
var v1 int = 1
var v2 int64 = 234
var v3 string = "hello"
var v4 float32 = 1.234
MyPrintf(v1, v2, v3, v4)
}
4 多返回值
如果读取文件成功,则返回值中的 n 为读取的字节数, err 为 nil ,否则 err 为具体的出错信息
func (file *File) Read(b []byte) (n int, err Error)
同样,从上面的方法原型可以看到,我们还可以给返回值命名,就像函数的输入参数一样。返回值被命名之后,它们的值在函数开始的时候被自动初始化为空。
在函数中执行不带任何参数的 return 语句时,会返回对应的返回值变量的值。
如果调用方调用了一个具有多返回值的方法,但是却不想关心其中的某个返回值,可以简单地用一个下划线“ _ ”来跳过这个返回值
n, _ := f.Read(buf)
5 函数签名
type DisposeFunc func(seq string, message []byte) (code uint32)