6.1Go方法
第六章 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方法的更多相关文章
- javaSE27天复习总结
JAVA学习总结 2 第一天 2 1:计算机概述(了解) 2 (1)计算机 2 (2)计算机硬件 2 (3)计算机软件 2 (4)软件开发(理解) 2 (5) ...
- EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态
本文目录 查看实体当前.原始和数据库值:DbEntityEntry 查看实体的某个属性值:GetValue<TValue>方法 拷贝DbPropertyValues到实体:ToObject ...
- mapreduce多文件输出的两方法
mapreduce多文件输出的两方法 package duogemap; import java.io.IOException; import org.apache.hadoop.conf ...
- 【.net 深呼吸】细说CodeDom(6):方法参数
本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...
- IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法
直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- [C#] C# 基础回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
- ArcGIS 10.0紧凑型切片读写方法
首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...
- [BOT] 一种android中实现“圆角矩形”的方法
内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...
随机推荐
- 2019-2020-1 20199308《Linux内核原理与分析》第九周作业
<Linux内核分析> 第八章 可执行程序工作原理进程的切换和系统的一般执行过程 8.1 知识点 进程调度的时机 ntel定义的中断类型主要有以下几种 硬中断(Interrupt) 软中断 ...
- java中CompletionService的使用
java中CompletionService的使用 之前的文章中我们讲到了ExecutorService,通过ExecutorService我们可以提交一个个的task,并且返回Future,然后通过 ...
- css之Grid Layout详解
css之Grid Layout详解 CSS Grid Layout擅长将页面划分为主要区域,或者在从HTML基元构建的控件的各个部分之间定义大小,位置和图层之间的关系. 与表格一样,网格布局使作者能够 ...
- Vue-cli3.0下的雪碧图插件webpack-spritesmith配置方法
在前端项目中,为了减少对图片的请求次数,一般而言需要进行雪碧图的配置.即将多张小图标合并成一张图片,这样页面中的小图标都在一张图片上,只需请求一张图片,就可以通过CSS设置各个小图标的显示,利于节省带 ...
- 算法竞赛进阶指南--在单调递增序列a中查找小于等于x的数中最大的一个(即x或x的前驱)
在单调递增序列a中查找<=x的数中最大的一个(即x或x的前驱) while (l < r) { int mid = (l + r + 1) / 2; if (a[mid] <= x) ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 B so easy
题目链接:https://nanti.jisuanke.com/t/41384 这题暴力能过,我用的是并查集的思想,这个题的数据是为暴力设置的,所以暴力挺快的,但是当他转移的点多了之后,我觉得还是我这 ...
- P2542 【[AHOI2005]航线规划】
P2542 [[AHOI2005]航线规划] 一个无向图,m个操作 删去一条边 给定两个点,求有多少边使得如果这条边不存在,给定的两个点不连通 一般这种删边的题目,考虑逆序加边处理 在删完的图中,任意 ...
- python(os 模块)
1.os.name 输出字符串指示正在使用的平台.如果是window 则用'nt'表示,对于Linux/Unix用户,它是'posix' import os print(os.name) #结果如下 ...
- Pika源码学习--pika的通信和线程模型
pika的线程模型有官方的wiki介绍https://github.com/Qihoo360/pika/wiki/pika-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B,这 ...
- 分治思想--快速排序解决TopK问题
----前言 最近一直研究算法,上个星期刷leetcode遇到从两个数组中找TopK问题,因此写下此篇,在一个数组中如何利用快速排序解决TopK问题. 先理清一个逻辑解决TopK问题→快速排序→递 ...