草庐IT

go语言入门-一文带你掌握go语言函数

我是沐风晓月 2023-11-04 原文

前言

本文go语言入门-掌握go语言函数收录于《go语言学习专栏》专栏,此专栏带你从零开始学习go语言。

文章目录

一. go语言函数介绍

1.1 函数的介绍

在每一种编程语言中都有函数的概念,函数是基本的代码快,用于执行一个任务。

我们之前写的函数代码中,都包含一个main函数:


这个main就是一个函数的定义,包含了以下几部分:

  • 关键字func
  • 函数名字funcName
  • 函数的参数params,用来定义形参的变量名和类型,可以有一个参数,也可以有多个,也可以没有
  • result用于定义返回值的类型,如果没有返回值,省略即可,也可以有多个返回值
  • body是函数体,可以在这里写函数的代码逻辑。

1.2 函数的特点

golang函数特点:

支持:

  • 无需声明原型;
  • 支持不定 变参;
  • 支持多返回值;
  • 支持命名返回参数;
  • 支持匿名函数和闭包;
  • 函数也是一种类型,一个函数可以赋值给变量。

不支持:

  • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
  • 不支持 重载 (overload)
  • 不支持 默认参数 (default parameter)。

二. 函数的语法

2.1 函数的表达式

函数的语法格式:

func name( [parameter list] ) [return_types] {
   函数体
}

在这个语法格式中:

  1. 函数的声明包含了一个函数名字,参数列表,返回值列表和函数体四个部分;

  2. func 是声明函数的关键字,类似于我们声明变量要用var

  3. name在这里是函数名字

  4. parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。
    参数列表中指定了参数的类型,顺序以及参数的个数。

  5. return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型,比如(string ,string)表示返回两个字符串。当然并不是所有的函数都需要返回值。

    注意: 如果有多个返回值,需要用括号。

  6. 函数体: 代码集合(一般是为了实现一个功能)

2.2 函数表达式案例

2.2.1 案例一 :利用函数求最大值

package main

import "fmt"

func max(num1, num2 int) int {

	var result int

	if num1 > num2 {

		result = num1
	} else if num1 < num2 {
		result = num2
	} else {
		result = 0
	}
	return result

}

func main() {
	ret := max(1, 2)
	fmt.Println(ret)

}



2.2.2 案例二: 不需要参数也不需要返回值的函数

函数的参数和返回值都是可选的,我们可以实现一个既不需要参数也没有返回值的函数:

package main

import "fmt"
# 创建一个不需要参数也不需要返回值的函数
func sayhi() {
	fmt.Println("hi,沐风晓月")
}

#函数的调用
func main() {
	sayhi()
}

二. 函数的调用

定义了函数之后,我们可以通过函数名()的方式调用函数:

在上面的例子中,我们调用了sayhi()函数

#函数的调用
func main() {
	sayhi()
}

在main函数中进行函数的调用,根据函数的类型来赋值。

函数名的定义要求:
在避免冲突的情况下,函数命名要本着精简短小、见文知意的原则:

  • 避免不必要的缩写,printError 要比 printEr 更好一些。
  • 避免使用类型关键字,比如 buildUserStruct 看上去会很别扭。
  • 避免歧义,不能有多种用途的解释造成误解。
  • 避免只能通过大小写区分的同名函数。
  • 避免与内置函数同名,这会导致误用。
  • 避免使用数字,除非是特定专有名词,例如UTF8。
  • 使用习惯用语,比如 init 表示初始化,is/has 返回布尔值结果。
  • 使用反义词组命名行为相反的函数,比如 get/set、min/max 等。

三. 函数的参数

Go 对参数的处理比较保守,不支持有默认值的可选参数,不支持命名实参,调用时必须按照签名顺序传递指定类型和数量的实参,就算以_命名的参数也不能忽略。

形参: 函数定义中的参数
实参: 函数调用时所传递的参数

3.1 类型简写

函数的参数中如果相邻变量的类型相同,则可以省略类型,例如:
func test(x,y int ,string,_book)*int{}

package main

func intsum(x, y int) int {
	return x + y
}

func main() {
	ret := intsum(5, 6)
	print(ret)

}

在上面的函数 intsum中,x和y都是int类型,所以 写的是x,y 只加y后面的一个int,x位置的int省略。 在intsum(x,y) int此处的第二个int,是函数返回值类型.

3.2 可变参数

可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加...来标识。

这里需要主要的是,可变参数通常要作为函数的最后一个参数。

# 此处是可变参数
func intsum(x int, y ...int) int {
	fmt.Println(x, y)
	sum := x
	#函数的可变参数是通过切片来实现的
	for _, v := range y {

		sum = sum + v

	}
	return sum
}

func main() {
	ret := intsum(5, 6)
	ret1 := intsum(100)
	ret2 := intsum(100, 10, 20)
	fmt.Println(ret, ret1, ret2)

}

输出结果:

5 [6]
100 []     
100 [10 20]

11 100 130 

四. 返回值

Go语言中通过return关键字向外输出返回值。

4.1 多返回值

Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值包裹起来。

案例一:

package main

import "fmt"

func mufeng(x, y int) (int, int) {
	sum := x + y
	sub := x - y
	return sum, sub

}

func main() {
# 多返回值需要用两个变量来接受
	k, v := mufeng(40, 50)

	fmt.Println(mufeng(20, 10))
	fmt.Println(k, v)
}

执行结果:

30 10
90 -10

案例二:

package main

import "fmt"

func multi() (string, int) {
	return "沐风晓月", 19
}

func main() {
	name, age := multi()
	fmt.Println("name:", name, "age:", age)
}

4.2 返回值命名

函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。
在之前的函数中,我们都是只指定类型,比如 int,实际上我们除了指定类型之外,还可以直接返回值名称。

package main

import "fmt"

func mufeng(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
	// 对两个返回值进行了命名,一个是,一个是sub,这时候return后的返回值就可以不写。

}
## 函数值接收
func main() {

	fmt.Println(mufeng(20, 10))
	// 30 10

}

虽然Go语言支持函数返回值命名,但这并不是太常用,可以根据自己的需求情况,酌情选择是否对函数返回值命名。

4.3 返回值补充

当我们的一个函数返回值类型为slice时,nil可以看做是一个有效的slice,没必要显示返回一个长度为0的切片。

package main

import "fmt"

func mufeng(x string) []byte {

	if x == "" {
		return nil  
		// 此处没有必要返回一个[]byte{}

	}

	return []byte(x)

}
func main() {

	arr := mufeng("it")
	a := mufeng("")
	fmt.Println(arr)
	fmt.Println(a)
}

五. 函数进阶

5.1 全局变量

全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。

package main

import "fmt"
// 定义全局变量

var num int32 = 100

func mufeng() {
// 在函数中打印全局变量
	fmt.Println(num)

}

func main() {
	mufeng()
}

5.2 局部变量

局部变量分两种:

  • 函数内定义的变量无法在该函数外使用
  • 如果局部变量和全局变量重名,优先访问局部变量
  1. 先来看第一种:函数内定义的变量无法在该函数外使用

  1. 再来看第二种:

如果局部变量和全局变量重名,优先访问局部变量。

package main

import "fmt"

var num int64 = 100

func mufeng() {

	num := 10
	fmt.Println(num)
}

func main() {
	mufeng()
     // 最终结果是10
}

可以看到,一开始全局变量是100,局部变量是10,但两个重名,所以最终结果是10,优先访问局部变量。

  1. 各种语快中定义变量也遵循上面的原则:
package main

import "fmt"

func mufeng(x, y int) {
	fmt.Println(x, y)
	//函数的参数也是只在本函数中生效
	if x > 0 {
		z := 100
		//变量z只在if语句块生效
		fmt.Println(z)

	}
	//fmt.Println("看看能否打印", z)
	//此处无法使用变量z

}
func main() {
	mufeng(3, 5)
}

在这个代码中可以看到,在if语句快外面就无法打印变量z了。

六 . 匿名函数和闭包

匿名函数就是没有名字的函数,也就是没有定义名字符号的函数,这是它与正常函数的主要区别。

而且匿名函数可以直接调用,保存到变量,作为参数和返回值。

我们来看一个案例:

package main

import "fmt"

func main() {
//匿名函数复制给了变量sum2
	sum2 := func(a, b int) int {
		return a + b
	}
	fmt.Println(sum2(2, 3))
}

这这里变量sum2所对应的值就是一个匿名函数。需要注意的是,这里的sum2只是一个函数类型的变量,并不是函数的名字。

有了匿名函数,就可以在函数中再定义函数(函数嵌套),定义的这个匿名函数也可以被称为内部函数。更重要的是,在函数内定义的内部函数,可以使用外部函数的变量等,这种方式也称为闭包。

举个例子:

package main

import "fmt"

func main() {
	c1 := colsure()
	fmt.Println(c1())
	fmt.Println(c1())
	fmt.Println(c1())

}
func colsure() func() int {
	i := 0
	return func() int {
		i++
		return i
	}

}

在这里,我们自定义的函数 colsure可以返回一个匿名函数,并且这个匿名函数持有外部函数colsure的变量i.因而在main函数中,每调用一次cl(),i的值都会加1。

闭包时函数和引用环境的组合。

总结

go语言学习的资料很多,但符合小白入门的其实比较少,不知道你在学习的过程中有没有这种感觉, 一起加油,冲破壁垒。

💕 好啦,这就是今天要分享给大家的全部内容了,我们下期再见!
💕 本文由沐风晓月原创,首发于CSDN博客, 博客主页:mufeng.blog.csdn.net
💕 每一次学习都很枯燥,单调,孤独,甚至看不到未来,每一次遇到问题都让人疑惑,焦虑,怀疑,甚至想要放弃。 但坚定的走下来,会收获很多。收获的不单单是技术的成长还有一颗强大的心。
💕 喜欢的话记得点赞收藏哦

有关go语言入门-一文带你掌握go语言函数的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  4. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  7. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  8. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  9. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  10. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

随机推荐