Go语言函数相关
1.函数的声明定义
//func关键字 //getStudent函数名 //(id int, classId int) 参数列表 //(name string,age int) 返回值列表 func getStudent(id int, classId int)(name string,age int) { //函数体 if id==&&classId=={ name = "BigOrange" age = } //返回值 return name, age // 支持多重返回值 }
有意思的是Go语言的返回值可以有多个,并且放在了参数列表后面,而C#等都是在函数名之前,也没有关键字。
2.函数的调用
import "fmt" //调用fmt包中的Println方法。 fmt.Println("Name:", std.Name, "Age:",std.Age)
3.函数编写的原则
很好奇为什么没有public private等关键字,那函数怎么才能定义为公用和私有呢?
Go语言有这样的规则:小写字母开头的函数只在本包内可见,大写字母开头的函数才
能被其他包使用。这个规则也适用于类型和变量的可见性。
4.不定参数问题
不定参数是指函数传入的参数个数为不定数量。
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
函数myfunc()接受不定数量的参数,这些参数的类型全部是int
※形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数。
它是一个语法糖(syntactic sugar),即这种语法对语言的功能并没有影响,但是更方便程序员使用。
从内部实现机理上来说,类型...type本质上是一个数组切片,也就是[]type,这也是为
什么上面的参数args可以用for循环来获得每个传入的参数。
不定参数的传递
myfunc3(args ...int)
对应上面的这个函数,传递参数可以为下面两种
// 按原样传递
myfunc3(args...)
// 传递片段,实际上任意的int slice都可以传进去
myfunc3(args[:]...)
任意类型的不定参数
可以看到 fmt.Println()方法接受了不定参数,但它是 ...interface{}
用interface{}传递任意类型数据是Go语言的惯例用法。
5.多返回值
Go语言函数可以返回多个返回值
如果调用方调用了一个具有多返回值的方法,但是却不想关心其中的某个返回值,可以简单
地用一个下划线“_”来跳过这个返回值
6.匿名函数
Go语言支持随时在代码里定义匿名函数。
匿名函数由一个不带函数名的函数声明和函数体组成
func(a, b int, z float64) bool {
return a*b <int(z)
}
匿名函数可以直接赋值给一个变量或者直接执行:(有点像js哈)
f := func(x, y int) int {
return x + y
}
func(ch chan int) {
ch <- ACK
} (reply_chan) // 花括号后直接跟参数列表表示函数调用
7.闭包
package main
import (
"fmt"
)
func main() {
var j int = 5
a := func()(func()) {
var i int = 10
return func() {
fmt.Printf("i, j: %d, %d\n", i, j)
}
}()
a()
j *= 2
a()
}
结果:
i, j: ,
i, j: ,
分析:
1---"...func()(func()) {....."
表明此匿名函数返回值的类型是func(), 即此匿名函数返回一个函数指针(此处引用一下c 的概念);
2---"...return func() {
fmt.Printf("i, j: %d, %d\n", i, j)
}..."
表明返回的函数指针指向一个打印 i, j: %d, %d\n 的函数;
3---"...a := func()(func()) {
...
}()..."
末尾的括号表明匿名函数被调用,并将返回的函数指针赋给变量a ;
综合来看:
"...a := func()(func()) {
var i int = 10
return func() {
fmt.Printf("i, j: %d, %d\n", i, j)
}
}()..."
此代码片段的意思"等价于"
a := func() {
fmt.Printf("i, j: %d, %d\n", i, j)
}
至于为何要用匿名函数如此的转一圈,是因为要引用闭包的概念,此概念省略不表,多写点代码试试就能体会了。
补充:传值和传引用
2018/08/22 补充
1.type 定义一个类型,有两种方式
①配合struct,创建一个新的结构,类似C#里面的Class
②配合既存的类型(int64...),创建一个新的类型,类似C++里面的 typedef
2.Struct的如果不进行赋值,会使用0值进行初始化。
3.type使用既存类型定义新结构,和既存类型不是同一个类型,不能进行转换,例如
package main type Integer int64
func main() {
var srcInt Integer
srcInt = int64()
}
结果:
4.方法和函数的区别
方法能给用户定义的类型添加新的行为。方法实际上也是函数,只是在声明时,在关键字func 和方法名之间增加了一个参数
例如:
这是函数,它的调用就是直接在使用的时候 传入参数获取返回值就行
func getStudentName(student Student)(name string) {
//返回值
return student.Name
}
这是方法
package main import (
"fmt"
) type Student struct
{
Name string
Age int
} //Student类的方法 使用值接收者实现了一个方法
func (student Student) getStudentName()(string){
return student.Name
} //Student类的方法 使用指针接收者实现了一个方法
func (student *Student) changeStudentName(name string){
student.Name = name
fmt.Println("方法执行之后name",student.Name) } //Student类的方法 使用指针接收者实现了一个方法
func (student Student) changeStudentNameByValue(name string){
student.Name = name
fmt.Println("方法执行之后name",student.Name)
} func main() {
bigOrange:=Student{
Name:"BigOrange",Age:,
} bigApple:=Student{
Name:"BigApple",Age:,
} //使用函数获取学生名称
name1 := getStudentName(bigOrange)
name2 := getStudentName(bigApple) fmt.Println("========通过传地址ChangeName之后==========")
fmt.Println("方法执行之前name",name1)
bigOrange.changeStudentName("BigBanana")
name1 = bigOrange.getStudentName()
fmt.Println("方法返回之后Name",name1) fmt.Println("========通过传值ChangeName之后===========")
fmt.Println("方法执行之前name",name2)
bigApple.changeStudentNameByValue("BigPear")
name2 = bigApple.getStudentName()
fmt.Println("方法返回之后Name",name2)
}
结果:
========通过传地址ChangeName之后==========
方法执行之前name BigOrange
方法执行之后name BigBanana
方法返回之后Name BigBanana
========通过传值ChangeName之后===========
方法执行之前name BigApple
方法执行之后name BigPear
方法返回之后Name BigApple
上面的例子中
分别使用了函数和方法进行获取学生姓名
分别使用了传值和传地址的方式对学生名称进行修正
综上
① Go语言中的方法,相比于函数,多了一个接收者参数
② Go 语言里有两种类型的接收者:值接收者和指针接收者
方法如果使用 值接收者,那么调用者可以是值接收者类型、也可以是它的指针类型,请看下面的例子(补充上例):
fmt.Println("========使用指针来调用值类型声明的接收者方法===========")
bigGrape := &Student{ Name:"bigGrape",Age:} //取地址!!!!
name3 := bigGrape.getStudentName();
fmt.Println("========通过传值ChangeName之后===========")
fmt.Println("方法执行之前name",name3)
bigGrape.changeStudentNameByValue("BigXXXX")
name3 = bigGrape.getStudentName()
fmt.Println("方法返回之后Name",name3)
结果:
========使用指针来调用值类型声明的接收者方法===========
name bigGrape
========通过传值ChangeName之后===========
方法执行之前name bigGrape
方法执行之后name BigXXXX
方法返回之后Name bigGrape
如上代码 使用了&获取地址,所以bigGrape是一个student类型的指针。下面的代码和上例一样,直接使用了【变量.方法】的方式调用方法,结果也和值类型调用的一样。
为什么?
【Go 在代码背后的执行动作】
name4:=(*bigGrape).getStudentName()
Go 编译器为了支持这种方法调用背后做的事情。【指针被解引用为值】,这样就符合了值接收者的要求。再强调一次,getStudentName 操作的是一个副本,只不过这次操作的是从bigGrape指针指向的值的副本。
同理还记得上面的,这句代码吗?对bigOrange这个变量修改了名称
bigOrange.changeStudentName("BigBanana")
bigOrange和bigApple明显是值类型,但是 changeStudentName 接收者是一个指针类型,为什么能调用,也是基于Go代码背后的执行动作,将值类型取了地址。
(&bigOrange).changeStudentName("BigOrange")
所以对于Go语言调用方法的类型,使用值或者指针都是可以的,不用拘泥于类型。
Go语言函数相关的更多相关文章
- Python语言十分钟快速入门
Python(蟒蛇)是一种动态解释型的编程语言.Python可以在Windows.UNIX.MAC等多种操作系统上使用,也可以在Java..NET开发平台上使用. AD:[51CTO技术沙龙]移动时代 ...
- Python语言快速入门
Python的主提示符(>>>):是解释器告诉你它正在等待你输入的下一个语句 Python的次提示符(...):告诉你解释器正在等待你输入当前语句的其他部分 [简介] Python( ...
- linux 操作系统下c语言编程入门
2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理 ...
- C++ 语言特性的性能分析
转载:http://www.cnblogs.com/rollenholt/archive/2012/05/07/2487244.html 大多数开发人员通常都有这个观点,即汇编语言和 C 语 ...
- 全国计算机等级考试二级教程-C语言程序设计_第8章_地址和指针
面试: unsigned int *p1 = # int *p2 = # #define _CRT_SECURE_NO_WARNINGS #include<std ...
- C语言--第3次作业
1.本章学习总结 1.1思维导图 1.2 本章学习体会及代码量学习体会 1.2.1学习体会 我眼中的函数 这一章接触到了新的知识--函数,不同于之前所学的编程,函数具有很清楚的分工性,且可以用来多次调 ...
- go语言之行--接口(interface)、反射(reflect)详解
一.interface简介 interface(接口)是golang最重要的特性之一,Interface类型可以定义一组方法,但是这些不需要实现.并且interface不能包含任何变量. 简单的说: ...
- 文件基本操作 (C语言)
一切皆文件 ---Linux 头文件 <stdio.h> 中定义了文件的相关操作 #include <stdio.h> 文件操作基本流程: 打开:fopen 相关操作 关闭:f ...
- golang语言基础(一)
0.项目的组织结构: GOPATH路径下是src文件夹---->src文件夹下是项目名称---->项目名称下是该项目的各个包名---->各包名下是.go文件(一个包下,无论有多少个. ...
随机推荐
- APM实践目录
长路漫漫,如果不能作出一款可用开源的东西出来,那是对时光的浪费. 这是我的学习分布式调用链的实践之路! 思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统? 理论篇: http:// ...
- Oracle 一个用户将表权限赋给另一个用户
原文地址:https://blog.csdn.net/u012129031/article/details/76218764 1.将用户user1的表权限赋给用户user2 select 'gra ...
- MYSQL中SUM (IF())
今天一个朋友突然给我发过来一个sql语句,一下子问住我了. 我想,这种语法木有见过呀.我就查了查,才明白什么意思,原来是mysql里面的用法. SUM(IF(`hosts`.state = 0, 1, ...
- H5 66-清除浮动方式二
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C. Polycarp Restores Permutation
链接 [https://codeforces.com/contest/1141/problem/C] 题意 qi=pi+1−pi.给你qi让你恢复pi 每个pi都不一样 分析 就是数学吧 a1 +(a ...
- PS调出春夏外景婚纱照
效果图 先来看看原图和夏季的效果图 先看看原图 教程终于来咯 原图暗部太深,需要将暗部提亮.可以把暗部选区选出来.为了精确选择暗部选区,我利用计算命令如上图所示.最后得到暗部的选区. 上图得到了暗部选 ...
- iOS--LaunchImage启动页设置及问题解决
在Assets.xcassets中使用LaunchImage来设置启动图: 一.根据不同屏幕尺寸的需求设置不同的图片,可以参照下图: 1.点击Image.xcassets 进入图片管理,然后右击, ...
- Python之发邮件
使用模块yagmail(使用收藏的yagmail,现在的第三方模块不能解决中文乱码问题) import yagmail user='xxx@126.com' password='xxxxxx' #使用 ...
- vue 开发依赖安装
安装element-ui yarn add element-ui --save 使用element-ui main.js import Vue from 'vue'; import ElementUI ...
- 【转】linux下查看磁盘分区的文件系统格式
https://www.cnblogs.com/youbiyoufang/p/7607174.html