[go学习笔记.第十章.面向对象编程] 6.方法和函数的区别,面向对象应用实例

本文详细介绍了Go语言中函数与方法的区别,包括调用方式、参数传递的差异,并通过示例说明了值类型和指针类型作为接收者时的不同。此外,还提供了两个面向对象编程的应用实例,展示了如何定义结构体、编写结构体方法以及如何使用这些方法。文章强调了在调用方法时,是否进行值拷贝或地址拷贝取决于方法与哪种类型绑定。
摘要由CSDN通过智能技术生成

1.方法和函数的区别

(1).调用方式不一样

        函数的调用方式: 函数名(实参列表)

        方法的调用方式:变量.方法名(实参列表)

(2).对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然

(3).对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变变量调用方法,反过来同样也可以

package main

import(
    "fmt"
)

type Person struct {
    Name string
}

//函数
//对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
func test(p Person) {
    fmt.Println(p.Name)
}
func test1(p *Person) {
    fmt.Println(p.Name)
}


//对于方法(struct)
//接受者为值类型时,可以直接用指针类型的变量调用方法,反过来同样可以
func (p Person) test2(){
    p.Name = "Jack"
    fmt.Println("test2 = ", p.Name) // jack
}
func (p *Person) test3(){
    p.Name = "Mary"
    fmt.Println("test3 = ", p.Name) // Mary
}
func main()  {
    p := Person{"tom"}
    test(p)//tom
    test1(&p)//tom

    p.test2()//tom
    fmt.Println("main() p.Name =", p.Name) //tom
    (&p).test2()    //Jack,从形式上看是传入地址,但是本质仍然是值拷贝
    fmt.Println("main() p.Name =", p.Name) //tom

    (&p).test3()//Mary
    fmt.Println("main() p.Name =", p.Name) //Mary

    p.test3()//(&p).test3 等价p.test3  Mary;从形式上看是值,但是本质仍然是地址拷贝
    fmt.Println("main() p.Name =", p.Name) //Mary
}

总结:

(1).不管调用形式如何,真正决定是值拷贝还是地址拷贝的,是要看这个方法是和哪个类型绑定

(2).如果是值类型,比如:(p Person)是值拷贝,如果是指针类型,比如:(p *Person)则是地址拷贝

2.面向对象编程应用实例

步骤:

        (1).声明(定义)结构体,确定结构体名

        (2).编写结构体的字段

        (3).编写结构体的方法 

案例1: 

package main

import(
    "fmt"
)

//1.编写一个Student结构体,包含name,gender,age,id,score字段,类型分别为:string,string,int,int,float64
//2.结构体中声明一个方法say,返回string类型,方法返回信息中包含所有字段值
//3.在main方法中,创建Student结构体实例(变量),并访问say,并将结果打印输出
type Student struct {
    name string
    gender string
    age int
    id int
    score float64
}

func (stu *Student) say() string {
    res := fmt.Sprintf("name=%v,gengder=%v,age=%v,id=%v,score=%v",
    stu.name,stu.gender,stu.age,stu.id,stu.score)
    return res
}
func main(){
    stu := Student{
        name:"张三",
        gender:"男",
        age:12,
        id:1,
        score:99.1,
    }
    result := stu.say()
    fmt.Println(result)
}

案例2:

package main

import(
    "fmt"
)

//景区门票案例
//一个景区根据游客的年龄收取不同的门票,年龄大于18小于60,20元,年龄小于18大于10,10,年龄小于10或者大于60,不让玩
//编写结构体Visitor,根据年龄判断门票价格并输出,当输入姓名为n时退出
type Visitor struct{
    Name string
    Age int
}
func (v *Visitor) ShowPrice() {
    if v.Age < 10 || v.Age > 80 {
        fmt.Println("考虑到安全,年龄应该在10~80之间")
        return
    }
    if v.Age >= 18 && v.Age <= 60 {
        fmt.Printf("姓名:%v票价为:20\n", v.Name)
    } else if (v.Age < 18 && v.Age >= 10) || (v.Age > 60 && v.Age <= 80) {
        fmt.Printf("姓名:%v票价为:10\n", v.Name)
    }
}
func main(){
    //定义一个结构体
    var v Visitor
    for {
        fmt.Println("请输入姓名:")
        fmt.Scanln(&v.Name)
        if v.Name == "n" {
            break
        }
        fmt.Println("请输入年龄:")
        fmt.Scanln(&v.Age)
        v.ShowPrice()
    }
}

在创建结构体变量时,就直接给指定字段赋值 

package main

import(
    "fmt"
)

type Student struct{
    Name string
    Age int
}
func main(){
    //方式一
    //在创建结构体变量时,就直接给指定字段赋值
    var stu = Student{"tom", 12}    //stu ==> 结构体数据空间
    stu1 := Student{"tom", 12}
    fmt.Println(stu)//{tom 12}
    fmt.Println(stu1)//{tom 12}
    //在创建结构体变量时,把字段名和字段值写在一起,这种写法不依赖字段的定义顺序,更稳健
    var stu3 = Student{
        Age: 12,
        Name: "tom",//顺序可以变化    
    }
    stu4 := Student{
        Name:"tom", 
        Age:12,
    }
    fmt.Println(stu3)//{tom 12}
    fmt.Println(stu4)//{tom 12}

    //方式二: 返回结构体的指针类型
    var stu5 = &Student{"Jack", 14} //返回的是一个指针: stu5 ==> 地址 ===> 结构体数据空间[Name:xxx,Age:xxx]
    //也可以这样
    var stu5_1 *Student = &Student{"Jack", 14}
    stu6 := &Student{"Jack", 14}
    //在创建结构体指针变量时,把字段名和字段值写在一起,这种写法不依赖字段的定义顺序
    var stu7 = &Student{
        Name: "tom7",
        Age: 12,
    }
    stu8 := &Student{
        Name:"tom8", 
        Age:12,
    }
    fmt.Println(stu5)//&{Jack 14}
    fmt.Println(stu5_1)//&{Jack 14}
    fmt.Println(stu6)//&{Jack 14}
    fmt.Println(stu7)//&{Jack 14}
    fmt.Println(stu8)//&{Jack 14}
    fmt.Println(*stu8)//{Jack 14}
}

[上一节][go学习笔记.第十章.面向对象编程] 5.方法的练习

[下一节][go学习笔记.第十章.面向对象编程] 7.工厂模式 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值