【Go系列】 函数与方法

承上启下

        学习完了几种数据结构,以及条件语句和循环语句,按照一般高级语言的想法,应该是要开始介绍函数了。Go语言也不例外。在其他的OOP语言中,函数位于类中的就是这个类的方法,而Go语言并没有类这种对象,那么Go的方法是怎么定义的呢?

开始学习

一、函数(Function)

1. 函数声明

函数是Go语言中的一等公民,它是一段执行特定任务的代码块。以下是函数的基本语法:

func 函数名(参数列表) 返回值类型 {
    // 函数体
}
  • 函数可以接受零个或多个参数。
  • 函数可以返回零个或多个值。
  • 函数名首字母小写表示私有,首字母大写表示公有。
  • 函数可以作为值传递给其他函数。
package main

import "fmt"

// 计算两个整数之和
func add(a, b int) int {
    return a + b
}

func main() {
    result := add(1, 2)
    fmt.Println("1 + 2 =", result)
}

2. 匿名函数  

匿名函数是指没有名字的函数,它们可以赋值给变量或者直接在其他函数内部使用。匿名函数在Go语言中非常常见,尤其是在需要定义短小的、一次性的函数时。

  • 没有函数名,只有函数体。
  • 可以在定义时直接调用。
  • 可以赋值给变量,通过变量名调用。
  • 可以作为参数传递给其他函数。
package main

import "fmt"

func main() {
    // 定义一个匿名函数并赋值给变量
    add := func(a, b int) int {
        return a + b
    }
    
    // 通过变量调用匿名函数
    result := add(1, 2)
    fmt.Println("1 + 2 =", result)

    // 直接调用匿名函数
    func(message string) {
        fmt.Println(message)
    }("Hello, World!")
}

3. 闭包(Closure)

闭包是一个函数值,它引用了其函数体之外的变量。闭包可以使得这些变量的状态被保留下来,即使是在函数已经返回之后。在Go语言中,所有的匿名函数都是闭包。

  • 闭包可以捕获和存储定义它们时作用域中的变量。
  • 即使外部函数已经返回,闭包仍然可以引用和修改它捕获的变量。
  • 闭包是实现数据封装和隐藏的一种机制。
package main

import "fmt"

// 返回一个闭包
func adder() func(int) int {
    // 定义一个局部变量
    sum := 0
    // 返回一个匿名函数,它引用了局部变量sum
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    // 调用adder函数,得到一个闭包
    pos, neg := adder(), adder()
    
    // 使用闭包
    for i := 0; i < 10; i++ {
        fmt.Println(pos(i), neg(-2*i))
    }
}

在这个例子中,adder 函数返回了一个匿名函数,这个匿名函数引用了 adder 函数中的局部变量 sum。每次调用 pos 或 neg 时,它们都会更新并返回 sum 的值,但由于它们各自捕获了 sum 的不同实例,因此它们的状态是独立的。

二、方法(Method)

方法是带有接收者的函数。在Go语言中,方法是与特定类型关联的函数。以下是方法的基本语法:

func (接收者 接收者类型) 方法名(参数列表) 返回值类型 {
    // 方法体
}
  • 方法与函数类似,但方法有一个特殊的接收者参数。
  • 接收者可以是值类型或指针类型。
  • 方法可以修改接收者的状态。
package main

import "fmt"

// 定义一个结构体
type Person struct {
    Name string
    Age  int
}

// 为Person类型定义一个方法
func (p Person) SayHello() {
    fmt.Printf("大家好,我是%s,今年%d岁。\n", p.Name, p.Age)
}

func main() {
    person := Person{Name: "张三", Age: 18}
    person.SayHello()
}

在Go语言中,方法的接收者可以是值类型(即对象的一个副本)或者是指针类型(即对象的引用)。这取决于你如何定义方法。

1. 值接收者(Value Receiver)

如果方法的接收者是一个值类型(比如一个结构体的实例),那么这个方法实际上是对接收者副本的操作。这意味着在方法内部对接收者所做的任何修改都不会影响到原始对象。

type MyStruct struct {
    Field int
}

func (m MyStruct) SetValue(value int) {
    m.Field = value
}

func main() {
    obj := MyStruct{Field: 1}
    obj.SetValue(2) // 这将不会修改原始的obj
    fmt.Println(obj.Field) // 输出 1,obj未被修改
}

在上面的例子中,SetValue 方法的接收者 m 是 MyStruct 的一个副本,所以对 m.Field 的修改不会影响 obj

2. 指针接收者(Pointer Receiver)

如果方法的接收者是一个指针类型,那么这个方法实际上是对原始对象直接操作。在方法内部对接收者所做的任何修改都会反映到原始对象上。

type MyStruct struct {
    Field int
}

func (m *MyStruct) SetValue(value int) {
    m.Field = value
}

func main() {
    obj := MyStruct{Field: 1}
    obj.SetValue(2) // 这将修改原始的obj
    fmt.Println(obj.Field) // 输出 2,obj已被修改
}

在这个例子中,SetValue 方法的接收者 m 是指向 MyStruct 的指针,所以对 m.Field 的修改会影响到 obj

三、函数与方法的关系与区别

  • 关系:方法是一种特殊的函数,它有一个接收者参数。
  • 区别:
    • 函数可以独立存在,而方法必须与特定类型关联。
    • 函数可以调用方法,但方法不能调用函数。

通过以上介绍,相信大家对Go语言中的函数与方法有了更深入的了解。在实际编程中,灵活运用函数与方法,可以让我们更好地组织和复用代码。

相关推荐

  1. Go系列函数方法

    2024-07-13 11:48:01       21 阅读
  2. 深入理解使用go函数方法--使用

    2024-07-13 11:48:01       37 阅读
  3. go函数方法的区别go中关于面向对象理解

    2024-07-13 11:48:01       43 阅读
  4. 深入理解使用go函数方法--泛型及堆栈

    2024-07-13 11:48:01       35 阅读
  5. Go语言入门:Go语言的方法函数,接口】

    2024-07-13 11:48:01       54 阅读
  6. Go】匿名函数闭包

    2024-07-13 11:48:01       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 11:48:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 11:48:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 11:48:01       58 阅读
  4. Python语言-面向对象

    2024-07-13 11:48:01       69 阅读

热门阅读

  1. Mysql索引、执行计划、体系架构

    2024-07-13 11:48:01       25 阅读
  2. php计算两张照片的相似度,范围:0-100

    2024-07-13 11:48:01       24 阅读
  3. 打工人如何应对AI对工作岗位的风险

    2024-07-13 11:48:01       24 阅读
  4. AM243-IPC

    AM243-IPC

    2024-07-13 11:48:01      23 阅读
  5. 【2024暑期实习】接到新需求该如何做?

    2024-07-13 11:48:01       22 阅读
  6. MATLAB中Simulink.exportToTemplate用法

    2024-07-13 11:48:01       22 阅读
  7. C#面:中间件的使用场景有哪些?

    2024-07-13 11:48:01       21 阅读