1 函数的定义
注: 小写字母开头的函数, 变量和类型只在本包内可见,大写字母开头的函数才能被其他包使用。
package mymathimport "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 mainimport "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 = 1var v2 int64 = 234var v3 string = "hello"var v4 float32 = 1.234MyPrintf(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)
