首页 > 编程笔记 > Go语言笔记 阅读:14

Go语言中的结构体方法(非常详细)

传统面向对象语言的方法是定义在类中,而结构体的方法是定义在结构体之外的。通过将结构体和结构体方法分离,Go 语言的代码更加灵活。

和函数一样,结构体方法也使用 func 关键字定义。结构体方法和函数的最大区别是结构体方法需要在func关键字和方法名之间使用小括号声明一个变量作为方法的接收者。

根据变量的类型,结构体的方法分为两种形式:值接收者方法和指针接收者方法,下面分别进行介绍。

Go语言值接收者方法

定义值接收者方法的语法格式如下:
func (变量 结构体名称) 方法名([参数 1, 参数 2, ...]) (返回类型) {
    方法体
    return
}
在上述语法格式中,结构体名称前的变量表示定义的结构体实例。参数列表和返回类型可以为空。在返回类型为空时,可以省略 return 语句。

结构体方法只能由创建的结构体实例化变量进行调用。代码如下:
package main

import (
    "fmt"
    "strconv"
)

//定义结构体
type profile struct {
    name string
    age  int
}

//定义结构体方法
func (p profile) get_info(subject string, score int) string {
    info := "姓名:" + p.name + "\n年龄:" + strconv.Itoa(p.age)
    info += "\n考试科目:" + subject + "\n考试分数:" + strconv.Itoa(score)
    return info
}

func main() {
    //实例化结构体
    p := profile{name: "张三", age: 20}
    //调用结构体方法
    result := p.get_info("综合知识", 76)
    fmt.Print(result)
}
运行结果如下:

姓名:张三
年龄:20
考试科目:综合知识
考试分数:76

上述代码定义结构体方法 get_info(),参数 p 是该方法的接收者,用于传递定义的结构体实例名。在调用 get_info() 方法时,由创建的结构体实例 p 进行调用。

Go语言指针接收者方法

在某些情况下,要使用指针类型的变量作为方法的接收者。一种是在调用方法时需要修改变量值,还有一种是结构体成员较多,占用内存较大。

定义指针接收者方法的语法格式如下:
func (变量 *结构体名称) 方法名([参数1, 参数2,…]) (返回类型) {
    方法体
    return
}

例如,修改前面的示例代码,在 profile 结构体中添加两个成员,在定义结构体方法时声明结构体方法的指针接收者,代码如下:
package main

import (
    "fmt"
    "strconv"
)

//定义结构体
type profile struct {
    name     string
    age      int
    interest []string
    evaluate string
}

//定义指针接收者方法
func (p *profile) get_info(subject string, score int) string {
    info := "姓名:" + p.name + "\n年龄:" + strconv.Itoa(p.age)
    var hobby string
    for _, v := range p.interest {
        hobby += v + " "
    }
    info += "\n兴趣爱好:" + hobby + "\n自我评价:" + p.evaluate
    info += "\n考试科目:" + subject + "\n考试分数:" + strconv.Itoa(score)
    return info
}

func main() {
    //实例化结构体
    p := &profile{
        name:     "张三",
        age:      20,
        interest: []string{"看电影", "弹琴", "唱歌"},
        evaluate: "谦虚谨慎,自信乐观",
    }
    //调用结构体方法
    result := p.get_info("综合知识", 76)
    fmt.Printf(result)
}
运行结果如下:

姓名:张三
年龄:20
兴趣爱好:看电影 弹琴 唱歌
自我评价:谦虚谨慎,自信乐观
考试科目:综合知识
考试分数:76

上述代码使用结构体的指针变量作为结构体方法的接收者。如果要修改结构体成员的原始数据,那么就要使用指针类型的接收者。因为值接收者是通过数据拷贝的方式传递,所以在方法中修改结构体成员的值不改变成员的原有值。

无论结构体方法采用值接收者还是指针接收者,结构体方法的调用方式都是一样的。

【实例】计算商品总价。定义表示商品信息的结构体,包括商品名称、商品单价和商品数量,分别通过结构体方法初始化结构体、获取商品信息和计算商品总价。代码如下:
package main

import (
    "fmt"
    "strconv"
)

//定义结构体
type goods struct {
    name   []string
    price  []int
    num    []int
}

//定义结构体方法,获取商品信息
func (g *goods) show() string {
    var info string
    for k, v := range g.name {
        info += "商品名称:" + v
        info += " 商品单价:" + strconv.Itoa(g.price[k]) + "元"
        info += " 商品数量:" + strconv.Itoa(g.num[k]) + "\n"
    }
    return info
}

//定义结构体方法,计算商品总价
func (g *goods) count() int {
    var total int //商品总价
    for k, v := range g.price {
        total += v * g.num[k]
    }
    return total
}

//定义结构体方法
func (g *goods) init(name []string, price []int, num []int) {
    //初始化结构体成员
    g.name = name
    g.price = price
    g.num = num
}

func main() {
    //实例化结构体
    g := &goods{}
    //调用结构体方法,初始化结构体成员值
    g.init([]string{"品牌手机", "品牌计算机"}, []int{1699, 2399}, []int{2, 3})
    info := g.show() //调用结构体方法,获取商品信息
    result := g.count() //调用结构体方法,计算商品总价
    fmt.Print(info)
    fmt.Printf("商品总价:%v 元\n", result)
}
运行结果如下:

商品名称:品牌手机 商品单价:1699元 商品数量:2
商品名称:品牌计算机 商品单价:2399元 商品数量:3
商品总价:10595元

相关文章