第六章 Go方法

第三章中讲解了struct,面向对象编程OOP已经是一个编程范式了,Go语言同样支持OOP开发。

一个对象就是一个变量,在这个对象中包含了一些方法,一个方法是一个和特殊类型关联的函数。

函数function,是一段具有独立功能的代码,可以反复被调用

方法method,是一个类的行为功能,只有该类的对象才可以调用

一个Person结构体,除了有基本的字段(姓名、年纪、性别…等等),Person结构体还应该有一些行为动作,如(吃饭、说话、跑步、学习等…),这些事需要定义方法去完成。

Go的方法是作用在指定的数据类型上的,与数据类型绑定,自定义类型都可以有方法,不仅仅是struct。隐式的将struct实例作为第一实参(receiver)。

可以为当前包内的任意类型定义方法。

package main
type X int
func (x *X)inc(){ //方法前的变量参数x称作 receiver,作用类似python的self
*x++
}
func main(){
var x X
x.inc()
println(x)
}

1.1. 方法的声明和调用

package main

import "fmt"

//定义一个结构体数据类型
type Person struct {
Username string
Age int
Sex string
} //表示给Person结构体,绑定添加test方法
func (p Person) test() {
fmt.Println("通过p变量,取出结构体类型中的Username值是:", p.Username)
} func main() {
p1 := &Person{
"狗子",
18,
"男",
}
p1.test()
}

总结method

1.test方法和Person结构体类型绑定
2.test方法只能通过Person结构体的实例调用

语法

一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。

所有给定类型的方法属于该类型的方法集。

方法定义:

func (recevier type) methodName(参数列表)(返回值列表){}

参数和返回值可以省略
package main type Test struct{} // 无参数、无返回值
func (t Test) method0() { } // 单参数、无返回值
func (t Test) method1(i int) { } // 多参数、无返回值
func (t Test) method2(x, y int) { } // 无参数、单返回值
func (t Test) method3() (i int) {
return
} // 多参数、多返回值
func (t Test) method4(x, y int) (z int, err error) {
return
} // 无参数、无返回值
func (t *Test) method5() { } // 单参数、无返回值
func (t *Test) method6(i int) { } // 多参数、无返回值
func (t *Test) method7(x, y int) { } // 无参数、单返回值
func (t *Test) method8() (i int) {
return
} // 多参数、多返回值
func (t *Test) method9(x, y int) (z int, err error) {
return
} func main() {}

自定义数据类型绑定方法

package main

import (
"fmt"
) type Integer int func (i Integer) Print() {
fmt.Println("i的值:", i)
} func main() {
var a Integer
a = 1000
a.Print() var b int = 200
a = Integer(b)
a.Print()
}

1.2. 方法实战

package main

import "fmt"

//定义一个结构体数据类型
type Person struct {
Username string
Age int
Sex string
} //此时这个(p Person)就是一个接受者
//Person结构体,人是可以说话的,添加speak方法
func (p Person) speak() {
fmt.Printf("大声的喊出了自己的名字:%v\n", p.Username)
} //人还可以蹦跳
func (p Person) jump() {
fmt.Printf("%v:跳起来一拳打在了姚明的膝盖上\n", p.Username)
} //人还可以进行算数
//方法的参数列表与返回值列表,与函数一致
func (p Person) getSum(n1, n2 int) int {
sum := n1 + n2
fmt.Printf("%v:飞快的计算出%d+%d的结果是%d\n", p.Username, n1, n2, sum)
return sum
}
func main() {
p1 := &Person{
"李二狗",
18,
"男",
}
p1.speak()
p1.jump()
res := p1.getSum(1, 2)
fmt.Printf("p1.getSum方法返回值是%d\n", res)
}

1.3. 方法使用细节

1)结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方式

2)如程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理

3)当接受者不是一个指针时,该方法操作对应接受者的值的副本(意思就是即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作。

package main

import "fmt"

type People struct {
Name string
Country string
} //此方法进行了值拷贝
func (p People) Print() {
fmt.Printf("我是谁:name=%s country=%s\n", p.Name, p.Country)
} //此方法进行了值拷贝,不会对p1进行修改
func (p People) Set(name string, country string) {
p.Name = name
p.Country = country
} //接收一个指针变量,可以修改原值
func (p *People) SetV2(name string, country string) {
p.Country = country
p.Name = name
} func main() {
var p1 People = People{
Name: "二狗子",
Country: "沙河",
} p1.Print()
//此处修改无效,并没有修改p1的原地址
p1.Set("二狗腿子", "日本")
p1.Print() //两者效果一样,是被编译器进行了优化
//(&p1).SetV2("people02", "english")
p1.SetV2("狗官", "日本")
p1.Print()
}

1.4. 方法和函数的区别

1.调用方式区别

函数调用:    函数名(参数列表)
方法调用: 变量名.方法名(参数列表)

2.对于普通函数,接受者为值类型时,不能将指针类型数据直接传递,传递时编译器就提示报错

package main

import "fmt"

func test(n1 int) int {
n1 = n1 + 10
return n1
} func test2(n1 *int) int {
*n1 = *n1 + 10
return *n1
} func main() {
var num = 10
//test函数接收的num有一个值拷贝的过程
res := test(num)
fmt.Println("值传递函数test结果:", res)
fmt.Println("值传递函数test修改num的结果:", num) //test2函数接收num变量的地址,因此修改的也是num的值
res1 := test2(&num)
fmt.Println("指针传递函数test2结果:", res1)
fmt.Println("值传递函数test2修改num的结果:", num)
}

3.对于方法(如struct的方法),接受者是值类型时,可以直接用指针类型变量调用方法,反之亦然。

package main

import "fmt"

type Person struct {
Name string
} func (p Person) test01() {
p.Name = "码云"
fmt.Printf("test01修改了name值:%v\n", p.Name)
} func (p *Person) test02() {
p.Name = "麻花藤"
fmt.Printf("test02修改了name值:%v\n", p.Name)
} func main() {
var p1 Person = Person{
"刘强东",
}
fmt.Println("p1默认值:", p1) //调用test01,由于值拷贝,并没有修改默认p1的Name值
//(&p1).test01() 即使传入地址,仍然进行了值拷贝
p1.test01()
fmt.Printf("此时main程序调用p1.test01,此时p1.Name值:%v\n", p1.Name) //传入地址
//可以简写p1.test02(),修改的是p1.Name原本内存地址
(&p1).test02()
fmt.Printf("main程序调用p1.test02,此时p1.Name值%v\n", p1.Name)
}

6.1Go方法的更多相关文章

  1. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  2. EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态

    本文目录 查看实体当前.原始和数据库值:DbEntityEntry 查看实体的某个属性值:GetValue<TValue>方法 拷贝DbPropertyValues到实体:ToObject ...

  3. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  4. 【.net 深呼吸】细说CodeDom(6):方法参数

    本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...

  5. IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法

    直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. [C#] C# 基础回顾 - 匿名方法

    C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...

  8. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  9. [BOT] 一种android中实现“圆角矩形”的方法

    内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...

随机推荐

  1. XSS Challenge(1)

    XSS Challenges http://xss-quiz.int21h.jp/ Stage #1 注入alert(document.domain),先试一试输入后会返回什么: 返回在标签中,直接尝 ...

  2. mysql-管理命令【创建用户、授权、修改密码、删除用户和授权、忘记root密码】

    一.创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 关键参数说明: username - 创建登录用户名, host ...

  3. 深度解析国内首个云原生数据库POLARDB的“王者荣耀”

    随着移动互联网.电子商务的高速发展,被使用最多的企业级开源数据系统MySQL面临着巨大挑战--为迎接"双11"的高并发要提前做好分库分表;用户不断激增要将读写分离才能应对每天上亿次 ...

  4. Netty(六):NioServerSocketChannel源码解析

    我们在Netty学习系列五的最后提出了一些问题还没得到回答,今天来通过学习NioServerSocketChannel的源码来帮我们找到之前问题的答案. 先看一下NioServerSocketChan ...

  5. Netty(四):AbstractChannel源码解析

    首先我们通过一张继承关系的图来认识下AbstractChannel在Netty中的位置. 除了Comaprable接口来自java自带的包,其他都是Netty包中提供的. Comparable接口定义 ...

  6. Oliver Twist

    对于济贫院那些绅士们而言,贫民好吃懒做.贪得无厌.他们消耗的食物即是对教区最大的威胁. 绅士们的利益得不到满足时,孤儿们只能被驱之而后快,甚至被"加价出售". 然而,眼泪这种东西根 ...

  7. Acmer 仅以此纪念最痛苦的一天

    今天打比赛,完全不在状态,看到别人又AK了,自己心里真TM不是个滋味,我为什么这么弱,菜鸡,每天都在水题,我的人生也是这么水?伪学习?没有学习能力,这不只是队伍的问题,是自己的问题,别人平均3题我们队 ...

  8. Codeforces Round #622 (Div. 2) 1313 C1

    C1. Skyscrapers (easy version) time limit per test1 second memory limit per test512 megabytes inputs ...

  9. Codeforce 1155D Beautiful Array(DP)

    D. Beautiful Array You are given an array aa consisting of nn integers. Beauty of array is the maxim ...

  10. 2019 ICPC 银川网络赛 H. Fight Against Monsters

    It is my great honour to introduce myself to you here. My name is Aloysius Benjy Cobweb Dartagnan Eg ...