头图
It's time to start studying functions and methods. . .

function

Through functions, development tasks can be decomposed into small units, which can be reused by other units, thereby improving development efficiency and reducing code overlap.

1. Function declaration

func funcName(params) result {
    body
}
  • Keyword func
  • Function name funcName
  • The parameter params of the function, used to define the variable name and type of the formal parameter
  • result is the returned function value, used to define the type of the return value, if not, it can be omitted
  • body is the body of the function, you can write the code logic of the function here

Write a function that calculates the addition of two numbers:

package main

import (
    "fmt"
)

// 计算两值之和
// 变量名称在前,变量类型在后
// 变量名称叫做参数名称,也就是函数的形参
func addTwoNum(a int, b int) int{
    return a + b
}

func main(){
    fmt.Println(addTwoNum(12, 21))
}

The results of the operation are:
image.png

2. Multi-value return

Functions in Go language can return multiple values, that is, multi-value returns
The first value returns the result of the function, and the second value returns the error message of the function

package main

import (
    "errors"
    "fmt"
)

// 计算两值之和,如果为负数就返回错误
func addTwoNum(a int, b int) (int, error) {
    if a < 0 || b < 0 {
        return 0, errors.New("a或者b不能为负数")
    }
    return a + b, nil
}

func main() {
    // 获取结果和错误信息
    a, err := addTwoNum(-12, 21)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("计算结果为:", a)
    }
}

The results of the operation are:
image.png

3. Name the return parameters

The return value of a function can also have a variable name, this is not commonly used, understand
The transformation function is:

package main

import (
    "errors"
    "fmt"
)

// 计算两值之和,如果为负数就返回错误
func addTwoNum(a int, b int) (sum int, err error) {
    if a < 0 || b < 0 {
        // 这里按照正常进行返回
        return 0, errors.New("a或者b不能为负数")
    }
    // 这里按照返回值给相关参数赋值,return后面不需要任何参数
    sum = a + b
    err = nil
    return
}

func main() {
    // 获取结果和错误信息
    a, err := addTwoNum(-12, 21)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("计算结果为:", a)
    }
}

The results of the operation are:
image.png

4. Variable parameters

Variable parameters, that is, the number of parameters of the function is variable
If the function has both ordinary parameters and variable parameters, then the variable parameters must be placed at the end of the parameter list
The main thing is to add three points in front of the parameter type
E.g:

// 没有参数
fmt.Println()
// 一个参数
fmt.Println("zhouzhaodong")
// 两个参数
fmt.Println("zhouzhaodong","xiaoqiang")

We write a function that calculates the sum of all numbers:

package main

import (
    "fmt"
)

// 计算所有值之和
func addAllNum(params ...int) int {
    sum := 0
    for _, i := range params {
        sum += i
    }
    return sum
}

func main() {
    fmt.Println("计算结果为:", addAllNum(1, 2, 3, 3, 3, 4, 5, 9))
}

The results of the operation are:
image.png

5. Package-level functions

Whether it is a custom function
The functions we use are all subordinate to a package
is 1616d1b81644c8 package
Functions of different packages to be called, then the scope of a function must be public, that is the first letter of the function name to uppercase

  • The first letter and lowercase of the function name represent private functions, which can only be called in the same package
  • The first letter of the function name represents a public function, and different packages can also be called
  • Any function will belong to a package

6. Anonymous functions and closures

An anonymous function is a function without a name

package main

import (
    "fmt"
)

func main() {
    sum := func(a, b int) int {
        return a + b
    }
    fmt.Println("计算结果为:", sum(1, 2))
}

The results of the operation are:
image.png

In the function define the function (function nesting). The anonymous function defined can also be called internal function
More importantly, the internal function defined in the function can use the variables of the external function, etc. This method is also called closure

method

The method must have a receiver , this receiver is a type
In this way, the method is bound to this type, and becomes this type of method

The definition of the receiver is the same as ordinary variables, function parameters, etc.
The front is the variable name, and the back is the receiver type

package main

import (
    "fmt"
)

// 定义一个新的类型,该类型等价于 uint
// 可以理解为 uint 的重命名
type Age uint

// 定义一个方法,参数就是Age
func (age Age) String() {
    fmt.Println("the age is", age)
}

func main() {
    age := Age(25)
    age.String()
}

The results of the operation are:
image.png

receiver is the biggest difference between functions and methods

1. Value type receiver and pointer type receiver

The receiver type of the defined method is a pointer, so our modification to the pointer is effective. If it is not a pointer, the modification has no effect, as shown below:

package main

import (
    "fmt"
)

// 定义一个新的类型,该类型等价于 uint
// 可以理解为 uint 的重命名
type Age uint

// 定义一个方法,参数就是Age
func (age Age) String() {
    fmt.Println("the age is", age)
}

// 定义一个方法,参数就是Age指针
func (age *Age) Modify() {
    *age = Age(30)
}

func main() {
    age := Age(25)
    age.String()
    // 修改age的值
    age.Modify()
    age.String()
}

The results of the operation are:
image.png

Tip: When the method is called, the receivers passed are essentially copies, but one is a copy of the value, and the other is a copy of the pointer to the value. The pointer has the characteristic of pointing to the original value, so if the value pointed to by the pointer is modified, the original value is also modified. We can simply understand that the value receiver uses a copy of the value to call the method, while the pointer receiver uses the actual value to call the method.

This is what the Go language compiler does for us automatically:

  • If a value type variable is used to call the method of the pointer type receiver, the Go language compiler will automatically retrieve the pointer for us to call to meet the requirements of the pointer receiver.
  • If you use a pointer type variable to call the method of the value type receiver, the Go language compiler will automatically dereference the call for us to meet the requirements of the value type receiver.

In short, the caller of the method can be either a value or a pointer. Don't pay too much attention to these. The Go language will help us automatically escape, which greatly improves development efficiency and avoids accidental bugs.

Regardless of whether you are using a value type receiver or a pointer type receiver, you must first determine your needs: when you operate on the type, do you want to change the value of the current receiver, or create a new value to return? These can decide which receiver to use.

Personal blog address:

http://www.zhouzhaodong.xyz/


周兆东
107 声望21 粉丝

一个java小白的成长之路。。。


引用和评论

0 条评论