Golang面向过程编程-函数

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.什么是函数

  简单的说函数的作用就是把程序里多次调用的相同的代码部分定义成一份,然后起个名字,所有的调用都只用这个名字就可以了。修改代码时,只需要改变函数体内的代码即可。Go 语言最少有个 main() 函数。你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。函数声明告诉了编译器函数的名称,返回类型,和参数。Go语言标准库提供了多种可动用的内置的函数。

.函数的特点

1>.减少重复代码;

2>.使程序变得可扩展;

3>.使程序变得易维护;

.函数的返回值

  说简单点就是函数执行完毕之后,会用关键字return返回一个value,这个value就是返回值。案例如下:

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt" func Max(a, b int) int { //其中关键字“func”是声明一个叫Max的函数名,“a”和“b”是传递的参数,第一个int是指参数的类型,第二个int是指返回值的类型
if a > b {
return a //表示当“a”大于“b”时,返回函数“a”
}else {
return b //否则就返回“b”,其实这个else可以不用写,因为他们的执行结果是等效的。
}
} func main() { //定义一个主函数,一个go程序运行起来不能没有主函数,当主函数结束时,就意味着程序的结束。
res := Max(100,200) //调用函数,需要按照你自己定义的函数类型进行传参数,否则会编译报错哟!用变量res来接受函数的返回值。
fmt.Printf("相比之下,最大的数字是:【%d】\n",res)
} #以上代码执行结果如下:
相比之下,最大的数字是:【200】

.函数的传参姿势

函数定义时指出,函数定义时有参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。 但当调用函数,传递过来的变量就是函数的实参,函数可以通过两种方式来传递参数:

a>.值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

b>.引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

  在默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt"
/*
传递类型 描述
值传递 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递 引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
*/ func SwapName(a string, b string) (string, string) { //该函数主要的功能就是将字符串的位置发生了改变,前后颠倒了一下。\
return b ,a
} func Swap(p *string,q *string) { //这个函数就牛逼了,它是并每一交换字符串的位置,而是直接将变量名的值给调换了。
var temp string
temp = *p
*p = *q
*q = temp
} func main() {
Name_1 := "尹正杰"
Name_2 := "饼干"
x,y := SwapName(Name_1,Name_2)
fmt.Println(x,y) //只是将变量的位置交换了一下,我们成这种传参方式为值传参。
fmt.Printf("执行Swap函数之前Name_1=[%s],Name_2=[%s]\n",Name_1,Name_2)
Swap(&Name_1,&Name_2) //并没有交换变量的位置,而是交换了变量的value,我们成这种传参方式叫做引用传参。
fmt.Printf("执行Swap函数之后Name_1=[%s],Name_2=[%s]\n",Name_1,Name_2)
} #以上代码执行结果如下:
饼干 尹正杰
执行Swap函数之前Name_1=[尹正杰],Name_2=[饼干]
执行Swap函数之后Name_1=[饼干],Name_2=[尹正杰]

1.不定参数的传递

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"fmt"
"reflect"
) func SpecificTypes(args ...int) {
for _, arg := range args {
fmt.Printf("当前参数是【%v】,其类型是【%v】\n",arg,reflect.TypeOf(arg))
}
} func main() {
list_1 := []int{5,4,3,2,1}
for _,v := range list_1{
SpecificTypes(v) //传递了5个参数进去
}
Num_1 := 100
Num_2 := 200
SpecificTypes(Num_2,Num_1) //只传递了2个int类型的参数进去
} #以上代码执行结果如下:
当前参数是【5】,其类型是【int】
当前参数是【4】,其类型是【int】
当前参数是【3】,其类型是【int】
当前参数是【2】,其类型是【int】
当前参数是【1】,其类型是【int】
当前参数是【200】,其类型是【int】
当前参数是【100】,其类型是【int】

2.任意类型的不定参数

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"fmt"
"reflect"
) func AnyType(args ...interface{}) { //interface可谓大胃王,可以接受任何的数据类型。
fmt.Println(args)
for _,arg := range args{
fmt.Printf("当前参数是【%v】,其类型是【%v】\n",arg,reflect.TypeOf(arg))
}
} func main() {
ArrayInt := []int{100,200,300}
ArrayString := []string{"yin","zheng","jie"}
ArrayBytes := []byte{'a','b','c'}
AnyType(ArrayInt,ArrayString,ArrayBytes) //可以传递任意类型的数据。
} #以上代码执行结果如下:
[[100 200 300] [yin zheng jie] [97 98 99]]
当前参数是【[100 200 300]】,其类型是【[]int】
当前参数是【[yin zheng jie]】,其类型是【[]string】
当前参数是【[97 98 99]】,其类型是【[]uint8】

.匿名函数

匿名函数是指不需要定义函数名的一种函数实现方式。1958年LISP首先采用匿名函数。 在Go里面,函数可以像普通变量一样被传递或使用,Go语言支持随时在代码里定义匿名函数。 匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。

1>.匿名函数案例一,求某个数字的平方根。

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"fmt"
"math"
) func main() {
GetSqrt := func(num float64)float64 { //定义一个名称叫做GetSqrt的匿名函数,特点是用func关键字定义时没有函数名,只有函数形参和返回值类型。
return math.Sqrt(num) //代码的结构体可以直接使用形参里面的参数,并将结果传给GetSqrt变量。
}
fmt.Println(GetSqrt(100)) //计算100的平方根。
fmt.Println(GetSqrt(64))
fmt.Println(GetSqrt(25))
} #以上代码执行结果如下:
10
8
5

2>.匿名函数案例二,对数字进行排序;

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"sort"
"fmt"
) func main() {
num := []int{2,400,1,5,3,9,700,6} //定义一个无序的切片;
sort.Slice(num, func(i, j int) bool { //利用sort包给字符串排序
return num[i] > num[j]
})
fmt.Println(num)
} #以上代码执行结果如下:
[700 400 9 6 5 3 2 1]

3>.匿名函数案例三,对字母进行排序;

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"sort"
"fmt"
) type student struct { //定义一个机构体;
id int
name string
} func main() {
str := []student{} //声明一个结构体
str = append(str,student{
name:"EEEEE",
id:1,
}) str = append(str,student{
name:"CCCC",
id:2,
}) str = append(str,student{
name:"DDDDDD",
id:3,
}) sort.Slice(str, func(i, j int) bool {
return str[i].name < str[j].name //按照字母排序
})
fmt.Println(str) sort.Slice(str, func(i, j int) bool {
return str[i].id < str[j].id //按照数字排序
})
fmt.Println(str)
} #以上代码执行结果如下:
[{2 CCCC} {3 DDDDDD} {1 EEEEE}]
[{1 EEEEE} {2 CCCC} {3 DDDDDD}]

.递归函数

简单的说递归函数就是自己调用自己,但是你需要一定一个结束条件。那么有的小伙伴会问了,为什么要指定结束条件呢?因为调用递归函数的时候都会在系统内存中重新开辟出一块内存,如果你一直调用它不去给它一个终止点的话,物理内存很快就会被撑爆的。

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt" func FibonacciSequence(n int64) int64 { //这是定义斐波拉契数列的递归函数,其中数字n表示结束位置。
if n == 1 || n == 2 {
return 1
}
return FibonacciSequence(n-1) + FibonacciSequence(n-2) //指定结束条件
} func main() {
fmt.Println(FibonacciSequence(40)) //第40个数字所对应的值。
} #以上代码执行结果如下:
102334155

七.嵌套函数

  嵌套函数,就是指在某些情况下,您可能需要将某函数作为另一函数的参数使用。

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"strings"
"fmt"
) func Toupper(s string) string { //还函数是讲字母从小写转换成大写。
return strings.Map(func(r rune) rune { //类似python中的嵌套函数.即在函数里在定义了一个匿名函数。
return r - 32
},s)
} func main() {
fmt.Println(Toupper("yinzhengjie"))
} #以上代码执行结果如下:
YINZHENGJIE

八.闭包函数

      闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。 “官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

  我们知道return可以返回一个字符串或是一个整数型当然也是可以返回一个函数,我们利用它可以返回函数的特性,可以在调用该函数的时候拿到返回的函数,再去执行返回的函数,最终得到我们想要的结果,要注意的是这个返回的函数的是可以获取到定义它的函数的环境变量。拥有这种定义方式和调用方法的函数,我们称之为比包函数。

1>.利用闭包函数求和;

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt" func SummationOperation(n int64) func(int64) int64 { //定义一个函数,并且返回值应该是个函数。
return func(m int64) int64 { //返回一个匿名函数
return m + n //该匿名函数只有“m”形参,但是它可以获取到它的SummationOperation的一个形参“n”的值。
}
} func main() {
sum := SummationOperation(100) //调用函数SummationOperation函数,由于它返需要返回一个匿名函数,因此我们需要用一个变量去接收。
fmt.Println(sum(20)) //由于匿名函数需要传入一个“int64”的数据类型进行相加操作,因此我们在调用的时候需要传入一个整形。
fmt.Println(sum(100))
} #以上代码执行结果如下:
120
200

2>.闭包函数挖坑(你会发现该函数存取的值总是最后一位的。)

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt" func main() {
var list []func()
for i :=0;i < 3 ; i++ {
list = append(list, func() {
fmt.Println(i)
//fmt.Println(&i)
})
}
for _,f := range list{
f()
}
} #以上代码执行结果如下:
3
3
3

3>.闭包函数填坑

 /*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import "fmt" func main() {
var list []func()
for i :=0;i < 3 ; i++ {
i := i //给i变量重新赋值,
list = append(list, func() {
fmt.Println(i)
//fmt.Println(&i)
})
}
for _,f := range list{
f()
}
} #以上代码执行结果如下:
0
1
2

 九.常用内置函数介绍

  

  未完待续。。。。

Golang面向过程编程-函数的更多相关文章

  1. Python开发基础-Day10生成器表达式形式、面向过程编程、内置函数部分

    生成器表达式形式 直接上代码 # yield的表达式形式 def foo(): print('starting') while True: x=yield #默认返回为空,实际上为x=yield No ...

  2. python基础之生成器表达式形式、面向过程编程、内置函数部分

    生成器表达式形式 直接上代码 1 # yield的表达式形式 2 def foo(): 3 print('starting') 4 while True: 5 x=yield #默认返回为空,实际上为 ...

  3. 1.面向过程编程 2.面向对象编程 3.类和对象 4.python 创建类和对象 如何使用对象 5.属性的查找顺序 6.初始化函数 7.绑定方法 与非绑定方法

    1.面向过程编程 面向过程:一种编程思想在编写代码时 要时刻想着过程这个两个字过程指的是什么? 解决问题的步骤 流程,即第一步干什么 第二步干什么,其目的是将一个复杂的问题,拆分为若干的小的问题,按照 ...

  4. Day4 闭包、装饰器decorator、迭代器与生成器、面向过程编程、三元表达式、列表解析与生成器表达式、序列化与反序列化

    一.装饰器 一.装饰器的知识储备 1.可变长参数  :*args和**kwargs def index(name,age): print(name,age) def wrapper(*args,**k ...

  5. Python基础(协程函数、内置函数、递归、模块和包)-day05

    写在前面 上课第五天,打卡: 凭着爱,再回首: 一.协程函数(生成器:yield的表达式形式) 1.yield 的语句形式: yield 1 - 这种方式在 Python基础(函数部分)-day04  ...

  6. 《Essential C++》读书笔记 之 面向过程编程风格

    <Essential C++>读书笔记 之 面向过程编程风格 2014-06-18 2.2 调用(invoking)一个函数 2.2.1 Pass by Reference语义 在函数sw ...

  7. python协程函数、递归、匿名函数与内置函数使用、模块与包

    目录: 协程函数(yield生成器用法二) 面向过程编程 递归 匿名函数与内置函数的使用 模块 包 常用标准模块之re(正则表达式) 一.协程函数(yield生成器用法二) 1.生成器的语句形式 a. ...

  8. python基础之协程函数、列表表达式、生成器表达式

    一.协程函数 协程函数的定义?如果在一个函数内部yield的使用方式是表达式形式的话,如x=yield,那么该函数称为协程函数 协程函数补充: def init(func): def wrapper( ...

  9. 面向过程编程(OPP) 和面向对象编程(OOP)的关系

    面向过程编程(OPP) 和面向对象编程(OOP)的关系 原文链接:http://blog.csdn.net/phphot/article/details/3985480 关于面向过程的编程(OPP)和 ...

随机推荐

  1. Linux内核分析:期中总结

    第一章:计算机是如何工作的 计算机大部分都是用冯诺依曼体系结构,即存储程序计算机. 两个层面: 1.硬件: cpu(IP寄存器:指针,指向内存的某块区域)——总线——内存(代码与数据) 2.程序员: ...

  2. WebAPI实例--第一个API

    今天终于做了第一个任务,学习API之后的第一个实例.销售设置开发API. 第一.层次结构 1.API各层 项目结构主要有五层,分别为API.BizModel.Data.DBModel.Logic. 2 ...

  3. 微信小程序动态数据跑马灯组件编写

    开发必备:熟悉微信小程序组件开发 开发思路:如果只有一条数据,直接用css3关键帧动画:如果有多条数据,则在当前动画运动到一定时间的时候,将其数据替换掉,使之在视觉效果上有一个从下到上播放的状态.数组 ...

  4. 转:为Docker容器设置固定IP实现网络联通(1)——通过Pipework为Docker容器设置

    https://blog.csdn.net/chinagissoft/article/details/51250839 1. 创建并启动一个容器: docker run --cap-add=NET_A ...

  5. Java代码安全

    https://www.owasp.org/index.php/Category:Java

  6. 测试 多线程 实现 callable 带返回值

    package threadTest; import java.util.ArrayList; import java.util.Date; import java.util.concurrent.C ...

  7. Delphi中的Sender:TObject对象解析

    Delphi中的Sender:TObject对象解析 procedure TForm1.Button1Click(Sender: TObject); begin end; 解析:Procedure是过 ...

  8. Lodop设置文本项行间距、字间距

    LODOP给文本项ADD_PRINT_TEXT设置字间距.行间距,可以在打印设计页面,右键属性里设置,然后在打印设计生成代码,也可以直接写代码.LineSpacing行间距.LetterSpacing ...

  9. Conjugate Function

    共轭函数 共轭函数的定义: 设函数f:Rn→R,定义函数f∗:Rn→R为: f∗(y)=sup(<y,x>−f(x))  x∈D 此函数称为函数f的共轭函数.即函数yx和函数f(x)之间差 ...

  10. python 从filelist.txt中拷贝文件到另一文件夹中

    #! python #coding:utf-8 ##!/usr/bin/python # Filename : fileCp.py import sys import os import shutil ...