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"来进行 ...
随机推荐
- AtomineerUtils使用说明
AtomineerUtils使用说明 VS2015PluginCrackAtomineer 介绍 AtomineerUtils 是国外的一款用于生成源代码注释的一款 VS 插件工具. 这款插件,支持 ...
- JDK 14的新特性:更加好用的NullPointerExceptions
JDK 14的新特性:更加好用的NullPointerExceptions 让99%的java程序员都头痛的异常就是NullPointerExceptions了.NullPointerExceptio ...
- Linux运维基础阶段部分复习概要
[jj@oldboy ~]$ hostnamectl set-hostname zj 主机名只有root用户才有权限修改,普通用户想要修改要知道root密码,sudo提权,重启虚拟机或者打开新的窗口新 ...
- FastJson踩坑:@JsonField在反序列化时失效
问题描述 一个对象(某个字段为枚举类型,为了不采用默认的序列化过程,用@JSONField指定了序列化器和反序列器,过程见旧博文),将其放到JSONArray中再序列化JSONArray对象,用得到的 ...
- JavaScript面向对象那些东西-继承
继承 父类里有些属性方法 子类想把父类中的这些属性方法 继承过来给子类自己的实例也用用 ( ps: →_→ 能不能专业点 没文化真可怕 ) 一.原型链继承 // 原型链继承:把子类的原型作为父类的实例 ...
- WebStorm 2019 3.3 安装及破解教程附汉化教程
WebStorm2019 3.3 安装及破解教程附加汉化教程 安装包及破解补丁 链接: https://pan.baidu.com/s/19ATTAW3Tsm0huIJSqYChTw 提取码:1ei7 ...
- vue做商品选择如何保持样式
是这样的情况:我知道,在vue里,实现点击高亮,可以使用诸如: <div class="static" v-bind:class="{defaultClass ,a ...
- ACM周记
放假一周了,虽然知识都学完了,但是使用和会用还是很难,不能在按着这个情形发展下去,这样的话肯定完成不了自己的任务,所以必须要改变自己的学习方法和学习态度,学习态度,一个星期也睡够放松够了,也玩够了,该 ...
- .Net Core中使用Dapper构建泛型仓储
前言:Dapper是.NET的简单对象映射器,在速度方面拥有ORM之王的称号,与使用原始ADO.NET读取数据一样快.ORM是对象关系映射器,它负责数据库和编程语言之间的映射. 仓储主要是用来解耦业务 ...
- 关于2020.04.26【MySQL导出数据到文件中的方法】的补充
之前导出的数据文件中没有表的列名,感觉不够完整,摸索一下发现带表列名导出也是可以的,只试了导出txt和csv两种文件类型的方法. 1.导出数据到txt文件中(包含数据表列名)的方法:先选择 ...