This is a creation in Article, where the information may have evolved or changed.
Function
Nesting (nested), overloading (overload), and default parameters are not supported (defaults parameter).
• No need to declare prototypes.
• Support for variable length parameters.
• Support for multiple return values.
• Named return parameters are supported.
• Supports anonymous functions and closures.
Use the keyword func to define the function, and the left brace cannot be another line.
func test(x,y int,s string) (int string) { //类型相同的相邻参数可合并。 n := x + y //多值返回必须用括号 return n, fmt.Sprintf(s,n)}
A function is a first class object that can be passed as a parameter. It is recommended that complex signatures be defined as function types for readability.
func test(fn func() int) int { return fn()}type FormatFunc func(s string, x,y int) string //定义函数类型func format(fn FormatFunc, s string, x,y int) string { return fn(s,x,y)}func main() { s1 := test(func() int { return 100}) //直接将匿名函数当参数 s2 := format(func(s string, x, y int) string { return fmt.Sprintf(s, x, y) }, "%d, %d", 10, 20) println(s1, s2)
Variable parameter
The argument is essentially a slice. There can be only one, and must be the last parameter bit.
func test(s string, n ...int) string { var x int for _, i := range n { x += i } return fmt.Sprintf(s, x)}func main() { println(test("sum: %d", 1, 2, 3))}
When you use a slice object to make a parameter, you must expand it.
func main() { s := []int{1, 2, 3} println(test("sum: %d",s...))}
return value
You cannot receive multiple return values with a container object. You can only use multiple variables, or "_" to ignore them. Multiple return values can be invoked directly as arguments to other functions.
func test() (int, int) { return 1, 2}func add(x, y int) int { return x + y}func sum(n ...int) int { var x int for _, i := range n { x += i } return x}func main() { println(add(test())) println(sun(test()))}
A named return parameter can be considered a local variable similar to a formal parameter, and finally returned implicitly by return.
func add(x, y int) (z int) { z = x + y return}func main() { println(add(1, 2))}
A named return parameter can be obscured by a local variable of the same name, which requires an explicit return.
func add(x, y int) (z int) { {// 不能在一个级别,引发 "z redeclared in this block" 错误。 var z = x + y // return // Error: z is shadowed during return return z // 必须显式返回。 }}
The named return parameter allows defer deferred calls to be read and modified through closures.
func add(x, y int) (z int) { defer func() { z += 100 }() z = x + y return}func main() { println(add(1, 2)) //输出:103}
The named return parameter is modified before the explicit return returns.
func add(x, y int) (z int) { defer func() { println(z) //输出:203 }() z = x + y return z + 200}func main() { println(add(1, 2)) //输出:203}
An anonymous function can be assigned to a variable, as a structure field, or in a channel. Closures replicate the original object pointers, which makes it easy to interpret the deferred reference phenomenon.
Deferred call
The keyword defer is used to register deferred calls. These calls are not executed until the RET, which is typically used to free resources or error handling. Multiple defer registrations, executed in FILO order. Even if a function or a deferred call has an error, these calls will still be executed.
Misuse of defer may cause performance problems, especially in a "cycle".
var log sync.Mutexfunc test() { lock.Lock() lock.Unlock()}func testdefer() { lock.Lock() defer lock.Unlock()}func BenchmarkTest(b *testging.B) { for i := 0; i < b.N; i++ { test() }}func BenchmarkTestDefer(b *testging.B) { for i := 0; i < b.N; i++ { testdefer() }}//输出:BenchmarkTest 50000000 43 ns/opBenchmarkTestDefer 20000000 128 ns/op
Error handling
Without a structured exception, panic throws an error and recover catches the error. Because the panic, recover parameter type is interface{}, any type object can be thrown. The capture function recover terminates the error only if it is called directly within the deferred call, otherwise it always returns nil. Any non-
The captured errors are passed out along the call stack.
func test() { defer func() { if err := recover(); err != nil { println(err.(string)) // 将interface{}转型为string类型 }() panic("panic erro!")}
In addition to using panic to throw a disruptive error, you can return an error type wrong object to represent the function call state. Standard library errors. New and FMT. The Errorf function is used to create an error object that implements the error interface. Determine the specific error type by judging the Error object instance. How to distinguish between using panic and error two ways?
The Convention is to use panic, which causes the critical process to appear unrecoverable errors, and the other uses error.