GO开发[四]:golang函数
函数
1.声明语法:func 函数名 (参数列表) [(返回值列表)] {}
2.golang函数特点:
a. 不支持重载,一个包不能有两个名字一样的函数
b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
c. 匿名函数
d. 多返回值
定义函数类型type:
package main
import "fmt"
type add_func func(int, int) int
func add(a, b int) int {
return a + b
}
func sub(a, b int) int {
return a - b
}
func operator(op add_func, a int, b int) int {
return op(a, b)
}
func main() {
c := add
fmt.Println(c)
sum := operator(c, 100, 200)
fmt.Println(sum)
var x add_func
x=sub
fmt.Println(x)
sub := operator(x, 100, 200)
fmt.Println(sub)
}
3.函数参数传递方式:
1). 值传递
2). 引用传递
注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。
引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
注意2:map、slice、chan、指针、interface默认以引用的方式传递
package main
import "fmt"
func modify(a *int) {
*a = 100
}
func main() {
a := 8
fmt.Println(a)
modify(&a)
fmt.Println(a)
}
参数类型省略:
func f(i, j, k int, s, t string)
func f(i int, j int, k int, s string, t string)
4.命名返回值的名字:
package main
import "fmt"
func split(sum int) (x, y int) {
x = sum / 10
y = sum % 10
return
}
func main() {
fmt.Println(split(17))
}
_标识符,用来忽略返回值
5.可变参数:
func add(arg …int) int {
}//0个或多个参数
func add(a int, arg …int) int {
}//1个或多个参数
func add(a int, b int, arg …int) int {
}//2个或多个参数
注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数
练习:写一个函数add,支持1个或多个int相加,并返回相加结果
练习:写一个函数concat,支持1个或多个string相拼接,并返回结果
defer
1.当函数返回时,执行defer语句。可以用来做资源清理
2.多个defer语句,按先进后出的方式执行,即最后一个defer语句将最先被执行
3.defer语句中的变量,在defer声明时就决定了。
在函数将要返回前执行:
package main
import "fmt"
func print() {
defer func() {
fmt.Println("defer")
}()
fmt.Println("hello")
}
func main() {
print()
}
多个defer语句:
package main
import "fmt"
func main() {
var i int =1
fmt.Println(i)
defer fmt.Println(i)
//不会立即执行,压到栈里面,函数执行结束后,再执行栈里的
defer fmt.Println("a")
i=10
fmt.Println(i)
}
用途:
1.关闭文件句柄
2.锁资源释放
3.数据库连接释放
内置函数
1.close:主要用来关闭channel
2.len:用来求长度,比如string、array、slice、map、channel
3.new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
package main
import "fmt"
func main() {
var i int
fmt.Println(i)
j := new(int)
fmt.Println(j)
fmt.Println(*j)
*j = 100
fmt.Println(*j)
}
4.make:用来分配内存,主要用来分配引用类型,比如chan、map、slice
new和make的区别:
package main
import "fmt"
func test() {
s1 := new([]int)
fmt.Println(s1)
s2 := make([]int, 10)
fmt.Println(s2)
*s1 = make([]int, 5)
(*s1)[0] = 100
s2[0] = 100
fmt.Println(s1)
fmt.Println(s2)
return
}
func main() {
test()
}
5.append:用来追加元素到数组、slice中
package main
import "fmt"
func main() {
var a []int
a = append(a,10,20,30)
a = append(a,a...)
fmt.Println(a)
}
错误处理error
Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:
type error interface {
Error() string
}
1.初始化失败,退出
2.重试,比如if err !=nil,重试3次
3.异常上抛
package main
import "fmt"
func print() {
var p *int
fmt.Println(*p)
}
func main() {
defer func() {
err := recover()
fmt.Println(err)
}()
panic("不想执行下去了")
//print()//1.空指针引用错误
//var n int
//fmt.Println(10 / n) //2.除数为0
/*
var i=3
var slice [3]int
fmt.Println(slice[i])//3.下标越界
*/
}
EOF error
recover.go:
Go语言引入了两个内置函数panic()和recover()以报告和处理运行时错误和程序中的错误场景:
当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误处理流程。
recover()函数用于终止错误处理流程。一般情况下, recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字) ,会导致该goroutine所属的进程打印异常信息后直接退出。
package main
import (
"fmt"
"time"
)
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
b:=0
a := 1/b
fmt.Println(a)
return
}
func main() {
for {
test()
time.Sleep(time.Second)
}
}
panic.go
package main
import (
"fmt"
"time"
"errors"
)
func initConfig() (err error) {
return errors.New("init config failed")
}
err := initConfig()
if err != nil {
panic(err)
}
return
}
func main() {
for {
test()
time.Sleep(time.Second)
}
}
递归
一个函数调用自己,就叫做递归。
package main
import (
"fmt"
"time"
)
func recusive(n int) {
fmt.Println("hello golang", n)
time.Sleep(time.Second)
if n > 10 {
return
}
recusive(n + 1)
}
func main() {
recusive(0)
}
递归实现阶乘和斐波那契数列:
package main
import (
"fmt"
"time"
)
func factor(n int) int {
if n == 1 {
return 1
}
return factor(n-1) * n
}
func fab(n int) int {
if n <= 1 {
return 1
}
return fab(n-1) + fab(n-2)
}
func main() {
fmt.Println(factor(5))
for i := 0; i < 10; i++ {
fmt.Println(fab(i))
}
}
函数类型
package main
import "fmt"
func print1(){
fmt.Println("print1")
}
func print2() {
fmt.Println("print2")
}
func func1(n int) int {
return n+1
}
func main() {
//变量是个筐,装这个变量类型的数据
//函数也是个筐,容器,装的函数
var f func()
f = print1
f()
f=print2
f()
var flist [3]func(int) int
flist[0]=func1
m:=flist[0](10)
fmt.Println(m)
fmt.Println(flist[0](10))
}
加减乘除:
package main
import (
"fmt"
"os"
"strconv"
)
func add(m, n int) int {
return m + n
}
func sub(m, n int) int {
return m - n
}
func comp(m,n int) int {
return m * n
}
func div(m,n int) int {
return m/n
}
func main() {
funcmap := map[string]func(int, int) int{
"+": add,
"-": sub,
"*":comp,
"/":div,
}
m, _ := strconv.Atoi(os.Args[1])
n, _ := strconv.Atoi(os.Args[3])
f := funcmap[os.Args[2]]
if f != nil {
fmt.Println(f(m, n))
}
}
匿名函数
匿名函数是指不需要定义函数名的一种函数实现方式
在Go里面,函数可以像普通变量一样被传递或使用,这与C语言的回调函数比较类似。不同的是, Go语言支持随时在代码里定义匿名函数。
package main
import (
"fmt"
"strings"
)
func toupper(s string) string {
return strings.Map(func(r rune) rune {
return r - ('a' - 'A')
}, s)
}
func main() {
f := func(x,y int) int {
return x + y
}
fmt.Println(f(1,2))
f1:=func(x,y int) int {
return x + y
}(1,3)
fmt.Println(f1)
fmt.Println(toupper("hello"))
}
闭包
闭包:一个函数和与其相关的引用环境组合而成的实体
package main
import (
"fmt"
)
func addn(n int) func(int) int {
return func(m int) int {
return m+n
}
}
func main() {
f := addn(3)
fmt.Println(f(12))
}
生成器:
package main
import "fmt"
func iter(s []int) func() int {
var i = 0
return func() int {
if i >= len(s) {
return 0
}
n := s[i]
i += 1
return n
}
}
func main() {
f := iter([]int{1, 2, 3})
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
}
GO开发[四]:golang函数的更多相关文章
- Javascript模式(第四章函数)------读书笔记
一 背景 js函数的两个特点:1 函数是第一类对象(first-class object):2 函数可以提供作用域 1 函数是对象: 1 函数可以在运行时动态创建,还可以在程序执行过程中创建 2 可以 ...
- php中strstr、strrchr、substr、stristr四个函数用法区别
php中strstr.strrchr.substr.stristr四个函数用法区别: php中strstr strrchr substr stristr这四个字符串操作函数特别让人容易混淆,常用的是s ...
- C#的百度地图开发(四)前端显示与定位
原文:C#的百度地图开发(四)前端显示与定位 有了这些定位信息,那要如何在前端的页面上显示出来呢?这需要用到百度地图的JavaScript的API.下面是示例代码. 前端代码 <%@ Page ...
- python全栈开发 生成器 :生成器函数,推导式及生成器表达式
python 全栈开发 1.生成器函数 2.推导式 3.生成器表达式 一.生成器函数 1.生成器: 生成器的本质就是迭代器 (1)生成器的特点和迭代器一样.取值方式和迭代器一样(__next__(), ...
- golang函数学习笔记
golang函数特点: a.不支持重载,一个包不能有两个名字一样的函数 b.函数是一等公民,函数也是一种类型,一个函数可以赋值给变量 c.匿名函数 d.多返回值 例子1 func add(a, b ...
- electron/nodejs实现调用golang函数
https://www.jianshu.com/p/a3be0d206d4c 思路 golang 支持编译成c shared library, 也就是系统中常见的.so(windows下是dll)后缀 ...
- STC8H开发(四): FwLib_STC8 封装库的介绍和注意事项
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- Oracle数据库中调用Java类开发存储过程、函数的方法
Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日 浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...
- iOS开发之----常用函数和常数
介绍一下Objective-c常用的函数,常数变量 算术函数 [算术函数] 函数名 说明 int rand() 随机数生成.(例)srand(time(nil)); //随机数初期化int val = ...
随机推荐
- ArcGIS API for JavaScript 4.2学习笔记[28] 可视域分析【使用Geoprocessor类】
想知道可视域分析是什么,就得知道可视域是什么 我们站在某个地方,原地不动转一圈能看到的所有事物就叫可视域.当然平地就没什么所谓的可视域. 如果在山区呢?可视范围就会被山体挡住了.这个分析对军事上有十分 ...
- 2018年的UX设计师薪酬预测,你能拿多少?
以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 一个经验丰富的设计师完全可以根据地区和专业来可以预期薪酬之间的差距,其中悬殊最高可达80K. 本 ...
- openstack ocata版本简化安装
Network Time Protocol (NTP) Controller Node apt install chrony Edit the /etc/chrony/chrony.conf 添加如下 ...
- LODOP打印控件示例
一.lodop打印预览效果图 LODOP.PRINT_SETUP();打印维护效果图 LODOP.PREVIEW();打印预览图 二.写在前面 最近项目用到了LODOP的套打,主要用到两个地方,一是物 ...
- Linq To EF
l简单查询:var result = from c in Entities.Customer select c; l条件查询: 普通linq写法: var result = from c in Ent ...
- js、jQuery、layer实现弹出层的打开、关闭
打开layer layer.open({ type: 2, title: '新增收货地址', shadeClose: true,//点击阴影关闭 shade: 0.8, area: ['900px', ...
- [编织消息框架][JAVA核心技术]动态代理应用12-总结
动态代理这篇比较长,是框架组成的重要基础 回顾下学到的应用技术 1.异常应用 2.annotation技术 3.数值与逻辑分享 4.jdk.cglib.javassist等动态代理技术 5.懒处理.预 ...
- cleanMyMac
想看外国网站可以找我,facebook.youtube.XX大片等,只要8元钱,无限制用到服务器关闭.看大片流畅不成问题 需要cleanMyMac的请加微信只要10或直接拍 http://a.p6ff ...
- iOS中的armv7,armv7s,arm64,i386,x86_64
前言 一般iOS中的armv7.armv7s.arm64.i386.x86_64这些都代表了什么?在Xcode中如何选择? 介绍 armv7.armv7s.arm64都是ARM处理器的指令集. i38 ...
- C#语言和SQL Server第八章笔记
一: ...