Golang 函数function
函数function
- Go函数不支持嵌套、重载和默认参数
- 但支持以下特性:
- 无需声明原型
- 不定长度变参
- 多返回值
- 命名返回值参数
- 匿名函数
- 闭包
- 定义函数使用关键字func,且左大括号不能另起一行
- 函数也可以作为一种类型使用
返回值及参数说明
func A(a int, b string) (int, string, int) { //第一个小括号当中是你的参数列表,第二个小括号是你的返回值列表
}
func A(a, b, c int) (int, string, int) {
//如果abc都是int型的话,可以按照这种方法进行简写,同样的方法也适用于返回值当中
}
func A() (a, b, c int) { //1:如果这样写的话就必须要命名返回值
//命名返回值和不命名返回值得区别
}
func A() (int, int, int) { //
//命名返回值和不命名返回值得区别
a, b, c := 1,2,3
return a,b,c
//如果此时没有命名返回值的时候,那么在返回值得时候就必须写上return a,b,c
//当然为了代码的可读性,这里我们规定必须return 的时候加上返回值名
}
不定长变参
package main
import "fmt"
func main() {
A(1,2,3,4,5,6,7)
}
func A(a ...int) {
// 这里采用的是不定长变参,不定长变参必须是参数的最后一个参数,后面不能再跟 b string这样的参数
fmt.Println(a)
}
package main
import "fmt"
func main() {
s1:= []int{1,2,3,4}
a,b :=1,2
A(a,b)
fmt.Println(a,b)
B(s1)
fmt.Println(s1)
}
func A(a ...int) {
//这里传进来的实际上是一个slice,引用类型
a[0] = 3
a[1] = 4
//尽管我们在函数A当中接收到的是一个slice,但是它得到的是一个值拷贝
//和直接传递一个slice的区别看函数B
fmt.Println(a)
}
func B(s []int) {
//这里并不是传递一个指针进去,而是对这个slice的内存地址进行了一个拷贝
//这里还可以看到像int型、string型进行常规的参数传进去的话,只是进行了个值拷贝,slice传进去虽然也是拷贝,但是它是内存地址的拷贝
s[0] = 4
s[1] = 5
s[2] = 6
s[3] = 7
fmt.Println(s)
//在这里 我们看到我们在函数B当中的修改,实际上影响到了我们main函数当中的变量s1
//如果直接传递一个slice,它的修改就会影响到这个slice的本身
}
PS:值类型和引用类型进行函数传参拷贝是不一样的,一个是拷贝值,一个是拷贝地址
package main
import (
"fmt"
)
func main() {
a := 1
A(&a) //这里取出a的地址
fmt.Println(a)
}
func A(a *int) { //传递的是指针类型
*a = 2 //在操作的时候需要去它的值进行操作,这个时候函数A就可以改变原始a的值
fmt.Println(*a)
}
函数类型的使用
package main
import (
"fmt"
)
func main() {
a := A
a() //这个时候是将A的函数类型赋值给a,在go语言当中一切皆是类型啊
}
func A() {
fmt.Println("Func A")
}
匿名函数的使用
package main
import (
"fmt"
)
func main() {
a := func() {
//此时这个代码块就是一个匿名函数,这个函数本身没有名称,我们将她赋值给a,然后调用
fmt.Println("Func A")
}
a() //依然可以打印func A
}
GO语言当中的闭包
package main
import (
"fmt"
)
func main() {
f := closure(10)
res1 := f(1)
fmt.Println(res1)
res2 := f(2)
fmt.Println(res2)
}
func closure(x int) func(int) int {
fmt.Printf("%p \n", &x)
return func(y int) int {
fmt.Printf("%p \n", &x)
return x + y
}
}
//这里可以看出3次打印x的地址都是一样的
defer
defer的执行方式类似其它语言中的析构函数,在函数执行体结束后按照调用顺序的相反顺序逐个执行
即使函数发生严重错误也会执行
支持匿名函数的调用
通常用于资源清理、文件关闭、解锁以及记录时间等操作
通过与匿名函数配合可在return之后修改函数计算结果
如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址
GO没有异常机制,但有panic/recove模式来处理错误
Panic可以在任何地方引发,但recover只有在defer调用的函数中有效
package main
import (
"fmt"
)
func main() {
fmt.Println("A")
defer fmt.Println("B")
defer fmt.Println("C")
}
//PS:打印的结果就是A C B
package main
import (
"fmt"
)
func main() {
for i := 0; i < 3; i++ {
//defer fmt.Println(i)
defer func() {
fmt.Println(i)
}() //调用这个函数
}
}
//刚才直接打印的时候,是作为一个参数传递进去,运行到defer的时候是将这个i的值进行了一个拷贝,所以打印的是 2 1 0
//这种情况下i一直是一个地址的引用,i一直引用的是局部变量的i,在退出这个循环体的时候 i已经变成了3,在main函数return的时候,开始执行defer语句,defer语句的时候i已经变成了3
异常机制
package main
import (
"fmt"
)
func main() {
A()
B()
C()
}
func A() {
fmt.Println("Func A")
}
func B() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Recover in B")
}
}()
panic("Panic in B")
}
func C() {
fmt.Println("Func C")
}
package main
import (
"fmt"
)
func main() {
var fs = [4]func(){}
for i := 0; i < 4; i++ {
defer fmt.Println("defer i=", i) //这个i是传递进来的参数,所以是值得拷贝
defer func() {
fmt.Println("defer_closure i=", i) //这里的i是引用外部的i,所以循环结束后,i变成了4
}()
fs[i] = func() {
fmt.Println("closure i = ", i) //这里也是引用外部的i,所以循环结束后i变成了4
}
}
for _, f := range fs {
f()
}
}
Golang 函数function的更多相关文章
- electron/nodejs实现调用golang函数
https://www.jianshu.com/p/a3be0d206d4c 思路 golang 支持编译成c shared library, 也就是系统中常见的.so(windows下是dll)后缀 ...
- Javascript自执行匿名函数(function() { })()的原理分析
匿名函数指没有指定函数名或指针的函数,自执行匿名函数只是其中一种,下文中称这种函数为:自执行函数 下面是一个最常见的自执行函数: // 传统匿名函数 (function() { alert('hell ...
- JavaScript自运行函数(function(){})()的理解
今天打开JQuery源文件(jquery-1.8.3), 看到JQuery的初始化过程是这样的 (function( window, undefined ) { // .... })( window ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- javaScript的函数(Function)对象的声明(@包括函数声明和函数表达式)
写作缘由: 平时再用js写函数的时候,一般都是以惯例 function fn () {} 的方式来声明一个函数,在阅读一些优秀插件的时候又不免见到 var fn = function () {} 这种 ...
- 函数(Function)作用域 / 远程函数执行
函数跟变量一样也是有作用域的:Global.Script.Local.Private Global:作用于整个PowerShell会话,只要PowerShell会话不结束,被Global修饰的变量和函 ...
- Javascript自执行匿名函数(function() { })()的原理浅析
匿名函数就是没有函数名的函数.这篇文章主要介绍了Javascript自执行匿名函数(function() { })()的原理浅析的相关资料,需要的朋友可以参考下 函数是JavaScript中最灵活的一 ...
- Javascript学习之函数(function)
在JS中,Function(函数)类型实际上是对象;每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针. 一 函 ...
- js立即执行函数: (function ( ){...})( ) 与 (function ( ){...}( ))
( function(){…} )() ( function (){…} () ) 是两种javascript立即执行函数的常见写法,最初我以为是一个括号包裹匿名函数,再在后面加个括号调用函数,最后达 ...
随机推荐
- HDU2444 The Accomodation of Students
The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...
- 简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?
http://blog.csdn.net/zuoerjin/article/details/7858488http://blog.sina.com.cn/s/blog_bf9843bf0101j5px ...
- 《A computer-aided healthcare system for cataract classification and grading based on fundus image analysis》学习笔记
Abstract This paper presents a fundus image analysis based computer aided system for automatic class ...
- 使用PerfView监测.NET程序性能(一):Event Trace for Windows
前言: 在日常项目开发中,我们时不时会遇到程序占用了很高CPU的情况,可能是程序里某些未经优化的代码或者Bug,或者是程序运行压力太大.无论是什么原因,我们总希望能看到到底是哪个方法占用了如此高的CP ...
- Sql Server Report 导出到EXCEL 指定行高
在SQL SERVER REPORT 2005做报表的时候,发现在report中指定的行高没有用.google了一下,找到了解决方法. Make both CanGrow and CanShrink ...
- ScintillaNET的应用
出于工作需要,需要制作一个嵌入在桌面应用中的C语言编辑器,经过一系列调研,目前ScintillaNET应该是最合适的了,开源.轻便.功能丰富,但是踩得坑也很多,接下面一一说道. 目前Scintilla ...
- ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下
先简单了解一这个几个 名词的意思. 控制反转(IOC) 依赖注入(DI) 并不是某种技术. 而是一种思想.一种面向对象编程法则 什么是控制反转(IOC)? 什么是依赖注入(DI) 可以点击下面链接 ...
- boost bind及function的简单实现
前面在做 http server 的时候,需要做一个回调的接口,要求能够绑定类的函数以及普通的函数到这个回调里,对于这种应用要求,选择 boost 的 bind 和 function 是最合适不过了, ...
- Git-遇到的问题以及解决方法
1.将本地内容推送到远程仓库后,远程仓库里的文件夹不可点击 原因:在本地添加文件夹A时,又在A里使用了git init命令 解决:删除文件夹A,再重新添加过 2.其他人推送不了内容到远程仓库 原因:权 ...
- Javascript如何避免连续调用中取到不存在的属性而导致报TypeError错?
背景: 在最近的 NODEJS 项目中,涉及到数据库的查询,回调函数里返回了查询结果,我这样做处理然后返回给前端: return results.collect_coupon[0].count 但是这 ...