三分钟学Go语言——函数深度解析(上)

简介: 三分钟学Go语言——函数深度解析(上)

基本原理


函数,几乎是每种编程语言的必备语法,通过函数把一系列的动作汇总起来,在不同的地方重复使用。


我们在数学中曾经就使用过函数,他的形式类似于y=f(x),这就是一个完整的调用过程,y就是函数计算后得到的值,x就是传入的变量。


怎么用?


相信在看这个教程的人肯定已经接触过其他的编程语言,我就不多废话了,就是干。


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS9jb2RpbmczbWluLzIwMjAtMDQtMjUtMTUyMzI1LmpwZw.png


go语言中最基本的函数是这样的,以func为关键字标记函数


func functionParam(num int) {
}


当然了,可以有多个形参,类型相同时可以省略,如下


//多个参数的函数
func functionParams(a, b int, c string) {
}



上面说过的函数都没有返回值,一般的函数都有返回值,没有返回值的函数要么是引用传递,可以直接改变参数内容,要么就是用于单元测试或者打印输出等。

aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS9jb2RpbmczbWluLzIwMjAtMDQtMjUtMTUxMDEyLmpwZw.png


没有返回值的函数就像一个不完整的男人,只能接受不能输出,来看看这个男人有一个输出的情况。


返回值标记在函数第一个括号后面,由于go语言是强类型语言,但又和python不同,要写出返回值类型。

//一个返回值
func funcReturnOne() int {
  return 1
}

如果说是有多个返回值,要用打括号括起来。

//多个返回值
func funReturnMany() (int, int) {
  return 1, 2
}



上面的返回值全部都是匿名的,可以赐他一个名字,函数中不用定义返回值,可以省略几行代码。


//返回值有名称
func funReturnName() (res int) {
  //var res  int  省掉了
  res = 1 + 1
  return
}


用返回就有接收,函数外部用这种方式接收

//接收多个返回值
  a, b := funReturnMany()



值传递,引用传递


刚刚有说到函数没有返回值的时候,要么是只需要打印结果,要么是只做单元测试,除了这两种情况,没有返回值的函数就是做了很多事情的你没有和老板汇报一样,没有任何意义!


引用传递和c++类似,先举个值传递的例子。

//值传递
func noChange(a, b int) {
  tmp := a
  a = b
  b = tmp
}

调用打印结果看看


a, b := 1, 2
  fmt.Printf("原值 a:%v,b:%v \n", a, b)
  noChange(a, b)
  //值传递,并没有修改原值
  fmt.Printf("值传递后 a:%v,b:%v \n", a, b)


看!像不像任劳任怨的你,忙活半天被老板喜欢的小张抢了功劳。


原值 a:1,b:2 
值传递后 a:1,b:2


下面来看看引用传递的例子。在类型前加一个星号代表该参数是一个指针


// 引用传递,参数加*号代表指针
func change(a,b *int){
  tmp := *a
  *a = *b
  *b = tmp
}


学过c++再来学go简直是如虎添翼,c++中有一个指针的概念go语言里也有。

//引用传递,&就是c中的取地址
  change(&a,&b)
  fmt.Printf("引用传递后 a:%v,b:%v \n", a, b)


输出结果,可以看到值被调换了。引用传递需要加&符号,术语叫取地址。函数里的对他做的任何操作都会改变原来的变量内容。

引用传递后 a:2,b:1


上面的例子传入的是指针,还有一种叫引用类型,和指针的区别是不需要星号和&,对他的修改会直接改动到原有变量的值。


ps:go语言中只有三种引用类型,slice(切片)、map(字典)、channel(管道)


函数进阶


上面说的东西都很简单了,基本学过任何一门语言的人都能瞬间看懂,和pythonc++javascript一样,go中也有把函数打作参数传递的语法。

像这样,functionValue函数的形参里有一个名为do的函数,需要提前指定do函数有什么参数和返回值。


func functionValue(a, b int, do func(int, int) int) {
  fmt.Println(do(a, b))
}

然后do(a,b)是在functionValue内部调用的。这种特性有什么用呢?定义两个参数为int,返回为int的函数。

func add(a, b int) int {
  return a + b
}
func sub(a, b int) int {
  return a - b
}

因为规则符合do函数的规则,两个都可以传递过去,看!这就不用修改函数内部而出现了两种效果。

functionValue(1, 1, add)
  functionValue(1, 1, sub)


在设计模式里,这种方式叫装饰器模式(Decorator Pattern):允许向一个现有的对象添加新的功能,同时又不改变其结构。


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS9jb2RpbmczbWluLzIwMjAtMDQtMjUtMTU1MzUxLmpwZw.png


当然,你也不必每次传递函数的时候都憨厚老实的定义一个新函数,因为有时候你定义的函数就只会在这里用到,只不过是把实现放在调用外部,而不修改原函数代码罢了。


  //匿名函数
  functionValue(1, 1, func(i1 int, i2 int) int {
    return i1 * i2
  })

上面这个例子多看几遍啊!!

实际的使用

你可以参考函数测速例子

定义一个测速函数。


func speedTime(handler func() (string), funcName string) {
  t := time.Now()
  handler()
  elapsed := time.Since(t)
  fmt.Println(funcName+"spend time:", elapsed)
}

传入不同的函数都可以测速度。


speedTime(appendStr, "appendStr")
speedTime(appendStrQuick, "appendStrQuick")



Tips


  • 还有你可以传filter函数做过滤,mapping做映射等实际的用法
  • 有时候也可以作为排序递增,递减的依据


b站


今天小熊在b站直播写文章了,虽然只有9个人在看,但是还有打赏,很开心!!!

12点了,终于写完了 ,晚安各位。


image.png



我的b站直播链接:https://live.bilibili.com/22043742

相关文章
|
23小时前
|
缓存 Go 调度
浅谈在go语言中的锁
【5月更文挑战第11天】本文评估了Go标准库`sync`中的`Mutex`和`RWMutex`性能。`Mutex`包含状态`state`和信号量`sema`,不应复制已使用的实例。`Mutex`适用于保护数据,而`RWMutex`在高并发读取场景下更优。测试显示,小并发时`Mutex`性能较好,但随着并发增加,其性能下降;`RWMutex`的读性能稳定,写性能在高并发时低于`Mutex`。
121 0
浅谈在go语言中的锁
|
1天前
|
存储 安全 编译器
go语言中进行不安全的类型操作
【5月更文挑战第10天】Go语言中的`unsafe`包提供了一种不安全但强大的方式来处理类型转换和底层内存操作。包含两个文档用途的类型和八个函数,本文也比较了不同变量和结构体的大小与对齐系数,强调了字段顺序对内存分配的影响。
50 8
go语言中进行不安全的类型操作
|
1天前
|
Go
配置go语言下载包 - 蓝易云
这个命令会将包下载到你的GOPATH目录下,并自动安装它。
26 1
|
2天前
|
安全 Go 调度
Go语言中的并发编程
Go语言自带了强大的并发编程能力,它的协程机制可以让程序轻松地实现高并发。本文将从并发编程的基础概念出发,介绍Go语言中的协程机制、通道和锁等相关知识点,帮助读者更好地理解并发编程在Go语言中的实践应用。
|
4天前
|
Ubuntu Unix Linux
【GO基础】1. Go语言环境搭建
【GO基础】1. Go语言环境搭建
|
5天前
|
JSON 前端开发 Go
lucky - go 语言实现的快速开发平台
go 语言实现的快速开发平台,自动生成crud代码,前端页面通过json配置,无需编写前端代码。
11 0
|
6天前
|
存储 Java Go
Go 语言切片如何扩容?(全面解析原理和过程)
Go 语言切片如何扩容?(全面解析原理和过程)
16 2
|
6天前
|
负载均衡 Go 调度
使用Go语言构建高性能的Web服务器:协程与Channel的深度解析
在追求高性能Web服务的今天,Go语言以其强大的并发性能和简洁的语法赢得了开发者的青睐。本文将深入探讨Go语言在构建高性能Web服务器方面的应用,特别是协程(goroutine)和通道(channel)这两个核心概念。我们将通过示例代码,展示如何利用协程处理并发请求,并通过通道实现协程间的通信和同步,从而构建出高效、稳定的Web服务器。
|
4天前
|
Linux 网络安全 Windows
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
|
5天前
HuggingFace Tranformers 源码解析(4)
HuggingFace Tranformers 源码解析
6 0

推荐镜像

更多