Go 函数方法
在 Go 语言中,函数和方法不太一样,有明确的概念区分。其他语言中,比如 PHP 函数就是方法,方法
就是函数,但在 Go 语言中,函数是不属于任何结构体、类型的方法,也就是说函数是没有接收者的;而方法
是有接收者的,我们所说的方法要么属于一个结构体的,要么属于一个新定义的类型的
函数
函数和方法,虽然概念不同,但是定义非常相似。函数的定义声明没有接收者,如下示例:
package main import "fmt" // 定义一个求两数之和的函数
func add(a,b int) int {
return a + b
} func main() {
sum := add(1,2)
fmt.Println(sum)
}
上面的例子中,我们定义了一个 add 函数,它的函数签名是 func add(a,b int) int ,没有接收者,直接定义在 go
的一个包之下,可以直接用,例子中的这个函数名是小写的 add,所以它的作用域只有当前包,不能被其他包使用,
如果我们把函数名以大写开头,可以被其他包调用,这也是 Go 中大小写的作用
方法
方法的声明和函数类似,她们的区别是:方法在定义的时候在 func 和 方法名之间有一个参数,这个参数就是方
法的接收者,这样我们定义的这个方法就和接收者绑定在一起了吧,称之为这个接收者的方法:
// 定义一个结构体
type person struct {
name string
} func (p person) String() string {
return "the person name is " + p.name
}
上面的这个例子中,func 和 方法名 String 之间的参数(p person) 就是接收者,现在我们说,类型 person 有了一个方法
String,现在看下如何使用:
func main() {
p := person{name : "张三"}
fmt.Println(p.String())
}
Go 语言中接收者分为两种类型,值接受者和指针接收者。我们上面的例子中,就是值类型接收者的示例
使用值类型接收者定义的方法,在调用的时候,使用的其实就是值接受者的一个副本,所以对该值的任何操作,不会影响
原来的值
package main
import "fmt"
type person struct {
name string
}
func (p person) String() string {
return "the person name is " + p.name
}
func (p person) modify() {
p.name = "李四"
}
func main() {
p := person{"张三"}
// 值类型接收者
p.modify()
fmt.Println(p.String())
}
上面的例子中,打印出来的值是 "张三",对其进行的修改无效。如果我们使用一个指针作为接收者,那么就会起作用了,
因为指针接收者传递的是一个指向原值指针的拷贝,指针的副本,指向的还是原来类型的值,所以修改时,同时也会影响原
来类型变量的值
package main
import "fmt"
type person struct {
name string
}
func (p person) String() string {
return "the person name is " + p.name
}
func (p *person) modify() {
p.name = "李四"
}
func main() {
p := person{"张三"}
// 值类型接收者
p.modify()
fmt.Println(p.String())
}
在调用方法的时候,传递的接收者本质上都是副本,只不过一个是值副本,另一个是指向这个值指针的副本。指针具有
指向原值的特性,所以修改了指针指向的值,也就修改了原有的值。我们可以简单的理解为值接收者使用的是值的副本来调用
方法,而指针接收者使用的是实际值调用方法
上面的例子中我们发现,在调用指针接收者方法的时候,使用的也是一个值的变量,并不是一个指针,修改如下:
p := person{"张三"}
(&p).modify()
这样也是可以的,如果我们没有强制使用指针进行调用,Go 编译器会帮我们取指针,同样的,如果是一个值接收者的方法
使用指针也可以调用,Go 编译器会自动解引,如下:
p := person{"张三"}
fmt.Println((&p).String())
所以,方法的调用既可以是值也可以是指针
多值返回
Go 语言支持函数方法的多值返回,也就是说我们定义的函数方法支持可以返回多个值,比如标准库里的很多方法,都是返回两
个值,第一个是函数需要返回的值,第二个是出错时返回的错误信息
package main import (
"fmt"
"log"
"os"
) func main() {
file , err := os.Open("/usr/tmp") if err != nil {
log.Fatal(err)
return
} fmt.Println(file)
}
如果返回的值,我们不想使用,可以使用 _ 进行忽略:
file , _ := os.Open("/usr/tmp/")
多个值返回的定义也非常简单,如下示例:
func add(a,b int) (int,error) {
return a + b, nil
}
函数方法声明定义的时候,采用逗号分隔,因为是多个返回,还要用括号扩起来,返回的值还是使用 return 关键字,以逗号分隔,和
声明的顺序一致
可变参数
函数方法的参数可以是任意多个,这种我们称之为可变参数,比如我们常用的 fmt.Println() 这类函数,可以接收可变参数
func main() {
fmt.Println("1","2","3","4")
}
自己定义一个可接收可变参数的函数,如果可变参数的类型是一样的则可以使用省略号 ... 代替:
func print(a ...interface{}) {
for _,v := range a{
fmt.Println(v)
}
}
可变参数本质上是一个数组,所以我们可以像数组一样使用它
Go 函数方法的更多相关文章
- 你真的会玩SQL吗?实用函数方法汇总
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- MS SQL Server中数据表、视图、函数/方法、存储过程是否存在判断及创建
前言 在操作数据库的时候经常会用到判断数据表.视图.函数/方法.存储过程是否存在,若存在,则需要删除后再重新创建.以下是MS SQL Server中的示例代码. 数据表(Table) 创建数据表的时候 ...
- 如何设计PHP业务模块(函数/方法)返回结果的结构?
如题:如何设计业务模块返回结果的结构? 一个业务函数/方法执行后,对外输出数据的结构通常有以下几种: 1.返回数字,如 成功时返回 0,失败时返回 -1,有的还会用一个全局变量输出错误信息: < ...
- paip.函数方法回调机制跟java php python c++的实现
paip.函数方法回调机制跟java php python c++的实现 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:// ...
- thinkphp模版调用函数方法
原文:thinkphp模版调用函数方法 {变量|函数1|函数2|函数3=参数1,参数2,参数3,###} ###为第4个参数,代表变量替换为第4个参数 举例: {$username|substr=0, ...
- jQuery中常用的函数方法
jQuery中常用的函数方法总结 Ajax处理 load(url,[data],[callback]) url (String) : 待装入 HTML 网页网址. data (Map) : (可选) ...
- JavaScript 函数(方法)的封装技巧要领及其重要性
作为一枚程序猿,想必没有人不知道函数封装吧.在一个完整的项目开发中,我们会在JS代码中对一些常用(多个地方调用)的操作进行一个函数的封装,这样便于我们调试和重复调用,以致于能够在一定程度上减少代码的冗 ...
- Kotlin——基础的函数/方法详解
对于Kotlin中的函数来说,和JavaScript或者Lua这些语言很像,它有着这些语言的特性.但是也与这些语言就着许多不同之处.或许你更了解Java语言,然而对于Java语言来说,它不是不是闭包这 ...
- PHP之取得当前时间函数方法
PHP之取得当前时间函数方法 PHP之取得当前时间函数方法文章提供了php的几种获取当前时间的函数,date,time等,同时告诉我如何解决时区问题.php教程取得当前时间函数文章提供了php的几种获 ...
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...
随机推荐
- 教师信息管理系统(方式一:数据库为oracle数据库;方式二:存储在文件中)
方式一: 运行截图 数据库的sql语句: /*Navicat Oracle Data TransferOracle Client Version : 12.1.0.2.0 Source Server ...
- JavaScript---设计模式总结
写了两篇设计模式的东西后,感觉不是很完美,决定闭关修炼,同时写下笔记 重申:设计模式很有用! 这里列一个设计模式的目录防止漏了某个东西(未完成的没有链接) 单例模式 策略模式 代理模式 迭代器模式 发 ...
- Codeforces 659 - A/B/C/D/E/F/G - (Undone)
链接:https://codeforces.com/contest/659 A - Round House - [取模] AC代码: #include<bits/stdc++.h> usi ...
- Cesium调用 WMS 、WMTS 服务
参考文章地址:Cesium调用 ArcGIS Sever 以及 GeoSever 发布的地图服务 cesium测试示例(包括官方的示例)中 arcgis服务都无法访问了 根据原文找到一个在线的可访 ...
- Filter and servlet
filter与servlet的区别与联系呢? 1. Filter 实现javax.servlet.Filter接口,在web.xml中配置与标签指定使用哪个Filter实现类过滤哪些URL链接. ...
- windows 控制台下运行cl命令
前提:确保已经安装vc6或者vs系列 我们可以再命令行直接编译c++程序, 在windows操作系统中,打开命令行,输入cl,若系统提示:'cl' 不是内部或外部命令,也不是可运行的程序或批处理文件. ...
- 解决HTML5提出的新的元素不被IE6-8识别的解决办法
解决HTML5提出的新的元素不被IE6-8识别的解决办法 <!--[if lt IE 9]> <script type="text/javascript" src ...
- 深入浅出Vue基于“依赖收集”的响应式原理(转)
add by zhj: 文章写的很通俗易懂,明白了Object.defineProperty的用法 原文:https://zhuanlan.zhihu.com/p/29318017 每当问到VueJS ...
- bootstrap 下拉菜单自动向上向下弹起
.别人的解决方案 2.别人的解决方案 3.我哒 div class="btn-group" style="margin-top:500px;" > < ...
- unity 安装破解提示partern not found和tutorials学习
1.破解安装问题:unity 安装破解提示partern not found 可能和安装了多个版本有关,删除了c下的unity目录也没有解决,试着重新安装也不能破解, 破解的软件的方式是生成lisen ...