Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

The way to go language learning-10-go function

Tian Shuai 2021-01-21 00:04:31 阅读数:16 评论数:0 点赞数:0 收藏数:0

function

  • Function is used to solve duplicate code , It puts the same function code : organization 、 Encapsulated in a function
  • You can call , This code block

Go Support function in language 、 Anonymous functions and closures , And the function is in Go Language belongs to “ First class citizen ”

first-class ( First-class ) function 、 Supports first class functions (First Class Function) Programming language , You can assign functions to variables , You can also use functions as parameters or return values of other functions

Definition of function

func function_name( [ parameter list - You can write multiple parameters ] ) ( Returns a list of types - Multiple types of results can be returned ]){
The body of the function
}
  • Function name : By letter 、 Numbers 、 Underline composition . But the first letter of a function name cannot be a number . In the same package , Function name cannot be repeated
  • Parameters : Parameters consist of parameter variables and their types , Use... Between multiple parameters , Separate
  • Return value : The return value consists of the return value variable and its variable type , You can also write only the type of the return value , Multiple return values must use () The parcel , And use , Separate
  • The body of the function : A block of code that implements a specified function , What did you do
// ageInfo Return age-related information
func ageInfo(name string, age int) (string, int) {
nextAget := age + 1
return fmt.Sprintf("%s This year, %d 了 ", name, age), nextAget
}

The parameters and return values of the function are optional , We can just encapsulate a top-down code and put it inside a function

// sayHello Just output a text
func sayHello(){
fmt.Println(" Hello, tomorrow ")
}

Function call

package main
import "fmt"
func main() {
// You can execute a function by parenthesizing the function name
sayHello()
}
func sayHello() {
// Duplicate code can be encapsulated in functions
fmt.Println(" It's repetitive code xxxxxxxxx")
}

Function arguments

Standard parameters

Function accepts arguments , Then the code inside the function can dynamically calculate and produce different results according to the parameters

package main
import "fmt"
func main() {
// You can execute a function by parenthesizing the function name , Parameters can be passed in parentheses
result := sayHello("eson")
fmt.Println(result) // Output results : Hello eson
}
func sayHello(name string) string {
// Duplicate code can be encapsulated in functions
return fmt.Sprintf("Hello %s", name)
}

Short for the same type of parameter

func sayHello(name string, add string) string {
// Duplicate code can be encapsulated in functions
return fmt.Sprintf("Hello %s", name)
}

The above function receives two arguments of the same type , You can optimize it by shorthand

func sayHello(name, address string) string {
// Duplicate code can be encapsulated in functions
return fmt.Sprintf("Hello %s, address is :%s", name, address)
}

Variable parameters of the same type

package main
import "fmt"
func main() {
ret := countNumber("eson", 1, 2, 3, 4, 5)
fmt.Printf("%s", ret) // eson count number :[1 2 3 4 5]
}
// Note that the variable length parameter can only be used in the last
func countNumber(name string, number ...int) string {
// Duplicate code can be encapsulated in functions
return fmt.Sprintf("%s count number :%v", name, number)
}

Function return value

Go Through... In language return Keyword output, return value

Returns a single return value

package main
import "fmt"
func main() {
result := calculate(1, 10)
fmt.Printf("result is:%v", result) // result is:11
}
// Single return value
func calculate(x, y int) int {
return x + y
}

Return multiple return values

package main
import "fmt"
func main() {
sum, sub := calculate(10, 1)
fmt.Printf("sum is:%v, sub is: %v\n", sum, sub) // sum is:11, sub is: 9
}
// Return multiple values
func calculate(x, y int) (int, int) { // Of course, the values here can return different types, depending on the actual situation
return x + y, x - y
}

Return value naming

package main
import "fmt"
func main() {
sum, result := calculate(10, 1)
fmt.Printf("sum is:%v, %v\n", sum, result) // sum is:11, calculate sum is:11
}
// Returns multiple values named
func calculate(x, y int) (sum int, result string) { // Of course, the values here can return different types, depending on the actual situation
sum = x + y
result = fmt.Sprintf("calculate sum is:%d", sum)
return sum, result
}

Scope of variable

  • Global scope
  • Local scope
  • Scope of the package

Global scope ( Global variables )

Global variables can be referenced inside functions , But variables defined in a function are only valid inside the function

package main
import "fmt"
func main() {
}
// Global variables
var num int = 18
func sum() {
fmt.Printf(" The value of the global variable is :%d", num) // You can use global variables directly inside functions
sumRet := num + 1
fmt.Printf("%v\n", sumRet)
}
func referSum() {
// I want to quote sum Functional sumRet Value ? No No, values inside functions can only be used inside functions
}

Local scope ( local variable )

  • Function scope is a local scope , Variables defined inside a function can only be used in a function
  • Logic operation is also a local scope, such as

Local scope logic operations & Quote up

Inside the logical operation block is an independent scope

// Global variables
var num int = 18
func sum() {
fmt.Printf(" The value of the global variable is :%d", num) // You can use global variables directly inside functions
sumRet := num + 1
// if It's a logical operation from if From beginning to end, it nebula Defined values can only be used internally , But it can be quoted up sumA
// Inside a function is a local scope that can be called by the scope below it
if sumRet > 1 {
sumA := 10
fmt.Printf("sumA The value of is :%v\n", sumA)
}
// fmt.Println(sumA) However, it is not allowed for a function scope to call its own sub scope code block
}

Local scope for loop & Quote up

Loop logic is also an independent scope , And you can refer up to its upper scope

// Global variables
var num int = 18
func sum() {
fmt.Printf(" The value of the global variable is :%d", num) // You can use global variables directly inside functions
sumRet := num + 1
for i := 0; i < sumRet; i++ {
// This i A new value is assigned to each loop
// The value defined in the loop is valid only in this loop
cycle := i + num
fmt.Printf("i is:%d\n", cycle)
}
}

Function parameter transfer mode

Value passed ( One assignment at a time is passed to the function reference )

When to pass by value ?

  • Don't want to change the pass value , Knowledge is a computing condition
  • This parameter is not very large , It doesn't cost much to assign a share
package main
import "fmt"
type person struct {
name string
age int
}
func main() {
p1 := person{name: "John", age: 18}
showInfo(p1)
}
// Just want to show when you can pass value
func showInfo(student person) {
fmt.Printf(" Student :%s The age of :%d", student.name, student.age)
}

quote 【 The pointer 】( Passing a pointer to one value at a time )

When to pass with a pointer ?

  • Want to change the value of the parameter
  • Parameters take up too much space
package main
import "fmt"
type person struct {
name string
age int
}
func main() {
p1 := person{name: "John", age: 18}
// After that 1 Years of age plus 1
happyNewYear(&p1)
fmt.Printf("name:%s, age is:%d", p1.name, p1.age)
}
func happyNewYear(p *person) {
p.age++
}

Of course, structs can use pointer variables directly

package main
import "fmt"
type person struct {
name string
age int
}
func main() {
p1 := &person{name: "John", age: 18} // Initialize a person Struct pointer variable for
// After that 1 Years of age plus 1
happyNewYear(p1)
fmt.Printf("name:%s, age is:%d", p1.name, p1.age)
}
func happyNewYear(p *person) {
p.age++
}

Higher order function ( The argument is a function or returns a function )

Understand the types of functions and use them in arguments

package main
import "fmt"
func main() {
// sum The type of this function
fmt.Printf("%T", sum) // func(int, int) int
}
func sum(x, y int) int {
return x + y
}

It can be seen from the above that each function has a type , That's what we can write when we pass a function in a function

package main
import "fmt"
func main() {
// sum The type of this function
fmt.Printf("%T\n", sum) // func(int, int) int
fmt.Printf("%v\n", calculate(100, 200, sum)) // 300
}
func sum(x, y int) int {
return x + y
}
// A calculation function is defined , It received 3 Parameters
// x,y int type
// op Is a function type func(x,y int) int
func calculate(x, y int, op func(x, y int) int) int {
return op(x, y)
}

Define a function type and use it in arguments

package main
import "fmt"
func main() {
// sum The type of this function
fmt.Printf("%T\n", sum) // func(int, int) int
fmt.Printf("%v\n", calculate(100, 200, sum)) // 300
}
func sum(x, y int) int {
return x + y
}
// Define a function type and use it
type fType func(int, int) int
// A calculation function is defined , It received 3 Parameters
// x,y int type
// op Is a function type ftype
func calculate(x, y int, op fType) int {
return op(x, y)
}

Similarly, return a function

package main
import (
"errors"
"fmt"
)
func main() {
a, b := 100, 200
var method string
// Get user input
_, _ = fmt.Scanln(&method)
// Get and put methods
job, err := calculate(method)
// perform
if err != nil {
fmt.Printf("%v\n", err)
} else {
fmt.Printf("%v\n", job(a, b))
}
}
func sum(x, y int) int {
return x + y
}
func sub(x, y int) int {
return x - y
}
// Define a function type and use it
type fType func(int, int) int
func calculate(op string) (fType, error) {
switch op {
case "+":
return sum, nil
case "-":
return sub, nil
default:
return nil, errors.New(" Unrecognized methods ")
}
}

Anonymous functions

When we need to use a function temporarily in a function, we can't use it as we define a normal function , Anonymous functions are used in this case ( A function without a name is an anonymous function )

// Anonymous functions don't have names
func( Parameters )( Return value ){
The body of the function
}

Anonymous functions assign variables and execute

package main
import "fmt"
func main() {
// Anonymous functions assign variables and assign
sum := func(x, y int) int { return x + y }
fmt.Printf("%v\n", sum(100, 200))
}

Anonymous functions define self executing

package main
import "fmt"
func main() {
// Define an anonymous variable followed by an extension, directly transfer the value and run
func(x, y int) {
fmt.Printf("sum : %d + %d result is :%d\n", x, y, x+y)
}(100, 200)
// result : sum : 100 + 200 result is :300
}

Anonymous functions are mostly used to implement callback functions and closures

Closure

Closure is :

  • Through the properties of higher-order functions , Functions can contain functions ( External function ), And return a function ( Internal function )
  • When the external function is destroyed , Values referenced by internal functions will not be destroyed
package main
import (
"errors"
"fmt"
)
// This function returns one func(int) Function of type
func wapper() func(arg int) {
x := 0
return func(y int) {
x += y
fmt.Println(x)
}
}
func main() {
// When this happens, the external function is destroyed , however x This variable doesn't have , Because it's referenced by an internal function
f := wapper()
f(10)
f(10)
f(10)
}
// result :
10
20
30

Use scenarios

  • Decoration function
  • Variable references

Decoration function example ( Calculate function run time )

A simple example

package main
import (
"fmt"
"time"
)
func main() {
// adopt timed Function can get the running time of the function
timed(run)()
}
// This function takes a function , And return a function
func timed(f func()) func() {
return func() {
start := time.Now()
f()
fmt.Printf(" This function requires :%dms\n", time.Since(start)/1000000)
}
}
func run() {
time.Sleep(time.Second * 3)
}

Practical application examples

package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/hello", timed(hello))
http.ListenAndServe(":3000", nil)
}
func timed(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
f(w, r)
end := time.Now()
fmt.Println("The request took", end.Sub(start))
}
}
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "<h1>Hello!</h1>")
}

Variable references

Normally, you use a variable in a function , Or define a global variable , You can use , Or call... Through closures

A simple example

package main
import (
"errors"
"fmt"
)
// This function returns one func(int) Function of type
func wapper() func(arg int) {
x := 0
return func(y int) {
x += y
fmt.Println(x)
}
}
func main() {
// When this happens, the external function is destroyed , however x This variable doesn't have , Because it's referenced by an internal function
f := wapper()
f(10)
f(10)
f(10)
}
// result :
10
20
30

Application examples

package main
import (
"fmt"
"net/http"
)
type Database struct {
Url string
}
func NewDatabase(url string) Database {
return Database{url}
}
func main() {
db := NewDatabase("localhost:5432")
http.HandleFunc("/hello", hello(db))
http.ListenAndServe(":3000", nil)
}
func hello(db Database) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, db.Url)
}
}

defer sentence

defer yes go Delay function in language , It's defined in a function defer The following expression will delay execution

  • After the other logic in the function is executed defer sentence
  • defer Statements need to be defined in return Before the statement
  • If there are more than one defer It will be executed in reverse order
package main
import (
"fmt"
"time"
)
func main() {
runTasks()
}
func runTasks() int {
start := time.Now()
// Define a delay function directly here
// Used to count how long this function has been running
defer func(stime time.Time) { fmt.Printf(" This function requires :%dms\n", time.Since(start)/1000000) }(start)
// Start running functional logic
fmt.Println(" Logic execution within a function 1")
time.Sleep(time.Second * 2)
fmt.Println(" Logic execution within a function 2")
return 666
// defer fmt.Println(" If in return It is not possible to add a delay statement after a statement ")
}

defer Usage scenarios of

Delay action

  • close resource
  • Statistics of execution results are shown in the example above

exception handling

golang At present, there is no exception handling similar to other languages :try catch, But it can go through defer To capture Exceptions, for example !~

stay go Function through panic To trigger an exception and exit the program , Here we need to be careful not to abuse :panic,panic It will cause the whole program to hang up

  • When the initialization data is needed to start the program, it can't be retrieved. At this time, it needs to exit
  • If there is a problem, it doesn't make sense to continue the execution later. You need to exit at this time
  • If the client's illegal request parameter returns an error parameter information prompt , Let the caller handle the problem himself , Not myself panic Hang up

If a function has an unknown exception , Its processing logic is based on the call chain , Keep going up until you meet recover function

package main
import (
"fmt"
)
func main() {
f1()
}
func f1() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("f1 The function caught an exception , Abnormal error is :%v\n", err)
}
}()
fmt.Println(" This is the second one 1 Layer function ")
f2()
}
func f2() {
panic("f2 Triggered panic")
fmt.Println(" This is the second one 2 Layer function ") // panic After that, it is not implemented here
}

Sum up

  • recover() It has to go with defer Use
  • panic After the exception, it will continue to call the chain to return , Until I met recover()
  • panic Don't mess with
Copyright statement
In this paper,the author:[Tian Shuai],Reprint please bring the original link, thank you

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;