GO中的函数
1、函数的声明与定义
func 函数名 (形参列表) (返回列表) {
执行语句
return 返回列表
}
2、几种函数操作
1)单返回值函数:返回列表只有一个返回值
示例:
import "fmt"
func plus(a, b int) (result int){
return a + b
}
2)多返回值函数:返回列表有多个返回值
示例:
import "fmt"
func test() (string, int){
return "Hello World", 666
}
3)命名返回值:可以从函数返回命名值。如果返回值被命名,则可以认为它在函数的第一行被声明为变量。
示例:
func namedReturnValue()(name string, height int){
name = "xiaoming"
height = 180
return
}
4)参数可变函数:
GO支持可变参数,示例例如下:
//支持0到多个参数
func sum(args... int) sum int{
}
//支持1到多个参数
func sum(n1 int, args... int) sum int{
}
func sum(nums ...int)int{
res := 0
for _, v := range nums{
res += v
}
return res
}
5)匿名函数:匿名函数是没有名字的函数,如果希望某个函数只使用一次,可以考虑使用匿名函数,当然匿名函数也可以多次调用。
func main(){
//这种方式只能使用一次
sum1 := func(a, b int) int {
return a + b
}(10, 20)
fmt.Println("sum1=", sum1)
//将匿名函数赋给变量,就可以多次调用匿名函数
sum2 := func(a, b int) int {
return a + b
}
result1 := sum2(10, 30)
result2 := sum2(90, 30)
}
如果将匿名函数赋值给一个全局变量,则这个匿名函数成为一个全局匿名函数。
var(
//定义全局变量fun1,并赋值一个匿名函数
Fun1 = func (a, b int) int{
return a + b
}
)
3、使用与注意事项
与其他语言函数使用类似,直接传递参数得到结果即可。
以下为一些使用时的注意事项。
1)函数的返回值列表可以是多个
2)函数的命名遵循标识符命名规范,见:GO学习笔记——变量与数据类型:已有其他语言(如C语言)基础-CSDN博客
3)函数内外对变量的操作和修改效果与原理、函数中参数和变量的使用调用等和其他语言一样。
4)GO不支持函数重载
5)函数也是一种数据类型,可以赋值给一个变量,也可以作为函数的参数调用
4、init函数
每个源文件都可以包含一个init函数,该函数会在main函数执行前,被Go运行框架调用,类似Java中类的初始化块。
示例如下:
import "fmt"
//init函数,通常可以在init函数中完成初始化工作
func init(){
fmt.Println("这是init函数")
}
func main(){
fmt.Println("这是main函数")
}
上面代码的执行结果为 :
一些关于执行顺序的注意事项和说明:
1)如果一个文件同时包含全局变量定义,init函数和main函数,则程序执行的顺序为
全局变量定义->init函数->main函数
2)如果当前main.go文件和调用的包文件(myPackage.go)中都有全局变量定义,init函数时,则程序执行的顺序为
myPackage.go的全局变量定义->myPackage.go的init函数->main.go的变量定义
->main.go的init函数->main.go的main函数
5、函数的闭包
闭包:指在函数内部定义的函数,并且该函数可以访问其外部作用域中的变量。闭包可以捕获并维持其所在函数外部的变量引用,即使其所在函数已经执行完毕,这些变量依然可以被闭包函数所使用。
示例如下:
package main
import "fmt"
func outFunc() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
f := outFunc()
for i := 0; i < 3; i++ {
fmt.Println(f())
}
}
上面代码的执行结果为 :
说明:在outFunc中定义的变量count在程序执行中只初始化了一次,在后续调用过程中,内部函数调用的是外部的count变量,所以会出现累加的情况。count和内部函数就成为了一个outFunc中的闭包。
6、函数的defer
defer用于延迟函数的执行,直到包含defer语句的函数执行完毕。无论函数是返回正常返回还是出现错误,defer语句都会在函数退出时执行。
defer通常用于确保一些资源的释放(比如文件关闭、数据库连接关闭、解锁等),或者在函数结束时执行一些清理工作,以确保程序的安全性和可维护性。
当使用defer时,语句会被放进一个类似于栈的结构(这意味着遵循先进后出(LIFO)的执行顺序)中,在函数结束时执行。
示例如下:
package main
import "fmt"
func myDefer() {
defer fmt.Println("inner 1")
defer fmt.Println("inner 2")
fmt.Println("inner 3")
}
func main() {
myDefer()
defer fmt.Println("outer 1")
defer fmt.Println("outer 2")
fmt.Println("outer 3")
}
执行结果如下:
7、一些内置函数和系统函数
1)字符串常用的系统函数
函数名 | 作用说明 |
---|---|
len(str string) | 统计字符串str的长度 |
[]rune(str string) | 将字符串str转换为rune数组,可用于遍历字符串 |
strconv.Atoi(str string) | 将字符串str转为整数,返回值列表为(int, error) |
strconv.Itoa(i int) | 将int整数i转为字符串,返回值为string |
[]byte(str string) | 将字符串转为[]byte |
string(bytes []byte) | 将[]byte转为字符串 |
strconv.FormatInt(i int64,base int) | 将int64型变量i转变为base进制数,结果为str。base>10时,超过十的数字用a-z表示。base的取值为2至36 |
strings.Contains(str string,substr string) | 查找字符串str中是否有字串substr,返回值为bool型 |
strings.Count(str string, substr string) | 统计一个字符串有几个指定的子串,返回值为int |
strings.EqualFold(a string, b string) | 不区分大小写的字符串比较(区分大小写的比较用==) |
strings.Index(str string, substr string) | 返回子串substr在字符串str第一次出现的index值,如果没有返回-1 |
strings.LastIndex(str string, substr string) | 返回子串substr在字符串str最后一次出现的index值,如果没有返回-1 |
strings.Replace(str string, substr string, restr string, n int) | 将字符串str中的n个子串substr依次替换为restr,如果n为-1,则为全部替换 |
strings.Split(str string,sep string) | 按照指定的字符串sep为分割标识,将字符串拆分为字符串数组 |
strings.ToLower(str string) strings.ToUpper(str string) | 将字符串字母的大小写转换 |
strings.TrimSpace(str string) | 将字符串左右两边的空格去掉 |
strings.Trim(str string, cut string) | 将字符串两边指定的字符串cut去掉 |
strings.TrimLeft(str string, cut string) strings.TrimRight(str string, cut string) | 将字符串左/右边指定的字符串cut去掉 |
strings.HasPrefix(str string, prestr string) | 判断字符串是否以指定的字符串开头 |
strings.HasSuffix(str string, sufstr string) | 判断字符串是否以指定的字符串结束 |
2)时间和日期相关函数
time.Time类型:用于表示时间
time.Duration:Golang内置的一些时间常量,在程序中可以用于获取指定时间单位的时间,如下所示:
常量名 | 表示时间 |
---|---|
Nanosecond | 1 //1ns |
Microsecond | 1000 * Nanosecond //1us |
Millisecond | 1000 * Microsecond // 1ms |
Second | 1000 * Millisecond // 1s |
Minute | 60 * Second // 1min |
Hour | 60 * Minute // 1h |
以下为一些常用的函数及其作用说明
函数名 | 作用说明 |
---|---|
time.Now() | 获取当前时间 |
对于time.Time类型变量mytime,有: mytime.Month() mytime.Day() mytime.Hour() mytime.Minute() mytime.Second() | 分别用于获取time.Time变量的年、月日、时、分、秒 |
对于time.Time类型变量mytime,有: mytime.Unix() mytime.UnixNano() | Unix用于表示从1970年1月1日 00:00到时间点mytime所经过的秒数,而UnixNano表示从1970年1月1日 00:00到时间点mytime所经过的纳秒数 |
time.sleep(time.Duration * a) | 用于表示休眠time.Duration * a时间后程序再进行 |
tips:格式化日期时间
将日期格式化并输出有两种常用方式:
方式1:
import{
"fmt"
"time"
}
func main(){
mytime := time.Now()
fmt.Printf("当前时间:%d-%d-%d %d:%d:%d \n", mytime.Year(), mytime.Month(),
mytime.Day(), mytime.Hour(), mytime.Munite(), mytime.second())
dateStr := Sprintf("当前时间:%d-%d-%d %d:%d:%d \n", mytime.Year(), mytime.Month(),
mytime.Day(), mytime.Hour(), mytime.Munite(), mytime.second())
}
方式2:用time.Format()方法来实现
fmt.Printf(mytime.Format("2006-01-02 15:04:05"))
fmt.Println()
fmt.Printf(mytime.Format("2006-01-02"))
fmt.Println()
fmt.Printf(mytime.Format("15:04:05"))
fmt.Println()
需要注意的是,Format()中传入的字符串参数必须如上面所示,是固定的,不可变动,输出为与传入字符串格式相同的字符串。
3)Go的内置函数
a.len: 用于求长度,比如string、array、slice、map、channel类型都能使用该函数
b.new: 用于分配值类型内存,返回的是指针
c.make: 用于分配引用类型内存。
其它内置函数可以在Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国中的builtin包里查阅。