为完成某一功能的程序指令(语句)的集合,称为函数。
在 Go 中,函数分为: 自定义函数、系统函数(查看 Go 编程手册)
包的本质实际上就是创建不同的文件夹,来存放程序文件。 画图说明一下包的原理
说明:go 的每一个文件都是属于一个包的,也就是说 go 是以包的形式来管理文件和项目目录结构的
打包基本语法
package 包名
引入包的基本语法
import “包的路径”
包快速入门-Go 相互调用函数,我们将 func Cal 定义到文件 utils.go , 将 utils.go 放到一个包中,当 其它文件需要使用到 utils.go 的方法时,可以 import 该包,就可以使用了. 【为演示:新建项目目录结 构】
在给一个文件打包时,该包对应一个文件夹,比如这里的 utils 文件夹对应的包名就是 utils,
文件的包名通常和文件所在的文件夹名一致,一般为小写字母。
当一个文件要使用其它包函数或变量时,需要先引入对应的包
引入方式 1:import "包名"
引入方式 2:
import (
"包名"
"包名"
)
package 指令在 文件第一行,然后是 import 指令。
在 import 包时,路径从 $GOPATH 的 src 下开始,不用带 src , 编译器会自动从 src 下开始引入
为了让其它包的文件,可以访问到本包的函数,则该函数名的首字母需要大写,类似其它语言 的 public ,这样才能跨包访问。比如 utils.go 的
如果包名较长,Go 支持给包取别名, 注意细节:取别名后,原来的包名就不能使用了
说明: 如果给包取了别名,则需要使用别名来访问该包的函数和变量。
在同一包下,不能有相同的函数名(也不能有相同的全局变量名),否则报重复定义
如果你要编译成一个可执行程序文件,就需要将这个包声明为 main , 即 package main .这个就 是一个语法规范,如果你是写一个库 ,包名可以自定义
介绍:为了让大家更好的理解函数调用过程, 看两个案例,并画出示意图,这个很重要
传入一个数+1
对上图说明
(1) 在调用一个函数时,会给该函数分配一个新的空间,编译器会通过自身的处理让这个新的空间 和其它的栈的空间区分开来
(2) 在每个函数对应的栈中,数据空间是独立的,不会混淆
(3) 当一个函数调用完毕(执行完毕)后,程序会销毁这个函数对应的栈空间。
基本语法和说明
案例演示 1
请编写要给函数,可以计算两个数的和和差,并返回结果。
案例演示 2
一个细节说明: 希望忽略某个返回值,则使用 _ 符号表示占位忽略
函数递归需要遵守的重要原则:
函数的形参列表可以是多个,返回值列表也可以是多个。
形参列表和返回值列表的数据类型可以是值类型和引用类型。
函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写该函数可以被本包文件和其 它包文件使用,类似 public , 首字母小写,只能被本包文件使用,其它包文件不能使用,类似 privat
如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传 入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用 。
为了简化数据类型定义,Go 支持自定义数据类型
基本语法:type 自定义数据类型名 数据类型 // 理解: 相当于一个别名 案例:type myInt int // 这时 myInt 就等价 int 来使用了.
案例:type mySum func (int, int) int // 这时 mySum 就等价 一个 函数类型 func (int, int) int
每一个源文件都可以包含一个 init 函数,该函数会在 main 函数执行前,被 Go 运行框架调用,也 就是说 init 会在 main 函数前被调用。
Go 支持匿名函数,匿名函数就是没有名字的函数,如果我们某个函数只是希望使用一次,可以考 虑使用匿名函数,匿名函数也可以实现多次调用。
匿名函数使用方式 1
在定义匿名函数时就直接调用,这种方式匿名函数只能调用一次。 【案例演示】
匿名函数使用方式 2
将匿名函数赋给一个变量(函数变量),再通过该变量来调用匿名函数 【案例演示】
如果将匿名函数赋给一个全局变量,那么这个匿名函数,就成为一个全局匿名函数,可以在程序 有效。
基本介绍:闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)
案例演示:
//累加器
func AddUpper() func (int) int {
var n int = 10
return func (x int) int {
n = n + x
return n
}
}
func main() {
f := AddUpper()
fmt.Println(f(1))//11
fmt.Println(f(2))//13
fmt.Println(f(3))//16
}
对上面代码的说明和总结
var n int = 10
return func (x int) int {
n = n + x
return n
}
返回的是一个匿名函数, 但是这个匿名函数引用到函数外的 n ,因此这个匿名函数就和 n 形成一 个整体,构成闭包。
请编写一个程序,具体要求如下
func makeSuffix(suiffix string) func (string) string {
return func ( name string) string{
if !strings.HasSuffix(name,suiffix) {
return name + suiffix
} else {
return name
}
}
}
func main() {
//返回一个闭包
f := makeSuffix(".jpg")
fmt.Println(f("winter"))
}
上面代码的总结和说明:
在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等) ,为了在函数执行完 毕后,及时的释放资源,Go 的设计者提供 defer (延时机制)。
快速入门案例
执行后,输出的结果:
defer 的注意事项和细节
defer 最主要的价值是在,当函数执行完毕后,可以及时的释放函数创建的资源。看下模拟代码。。
说明
我们在讲解函数注意事项和使用细节时,已经讲过值类型和引用类型了,这里我们再系统总结一 下,因为这是重难点,值类型参数默认就是值传递,而引用类型参数默认就是引用传递。
两种传递方式
值类型和引用类型
1)值类型:基本数据类型 int 系列, float 系列, bool, string 、数组和结构体 struct
2) 引用类型:指针、slice 切片、map、管道 chan、interface 等都是引用类型
值传递和引用传递使用特点
3) 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操 作变量。从效果上看类似引用 。这个案例在前面详解函数使用注意事项的
输出的结果是: tom tom jack tom
说明:字符串在我们程序开发中,使用的是非常多的,常用的函数需要同学们掌握[带看手册或者 官方编程指南]:
10 进制转 2, 8, 16 进制: str = strconv.FormatInt(123, 2) // 2-> 8 , 16
不区分大小写的字符串比 较(== 是区分字母大小写的 ): fmt.Println(strings.EqualFold(“abc”, “Abc”)) // true
返回子串在字符串第一次出现的 index 值,如果没有返回-1 : strings.Index(“NLT_abc”, “abc”) // 4
返回子串在字符串最后一次出现的 index,如没有返回-1 : strings.LastIndex(“go golang”, “go”)
将指定的子串替换成 另外一个子串: strings.Replace(“go go hello”, “go”, “go 语言”, n) n 可以指 定你希望替换几个,如果 n=-1 表示全部替换
按 照 指 定 的 某 个 字 符 , 为 分 割 标 识 , 将 一 个 字 符 串 拆 分 成 生成的所有片段组成的切片
:strings.Split(“hello,wrold,ok”, “,”)
将字符串的字母进行大小写的转换: strings.ToLower(“Go”) // go strings.ToUpper(“Go”) // GO
将字符串左右两边指定的字符去掉 : strings.Trim("! hello! “, " !”) // [“hello”] //将左右两边 !
和 " "去掉
将字符串左边指定的字符去掉 : strings.TrimLeft("! hello! “, " !”) // [“hello”] //将左边 ! 和 " "去掉
将字符串右边指定的字符去掉 : strings.TrimRight("! hello! “, " !”) // [“hello”] //将右边 ! 和 " "去掉
判断字符串是否以指定的字符串开头: strings.HasPrefix(“ftp://192.168.10.1”, “ftp”) // true
判断字符串是否以指定的字符串结束: strings.HasSuffix(“NLT_abc.jpg”, “abc”) //false
说明:在编程中,程序员会经常使用到日期相关的函数,比如:统计某段代码执行花费的时间等 等。
格式化日期时间
方式 1: 就是使用 Printf 或者 SPrintf
方式二: 使用 time.Format() 方法完成:
对上面代码的说明:
“2006/01/02 15:04:05” 这个字符串的各个数字是固定的,必须是这样写。
“2006/01/02 15:04:05” 这个字符串各个数字可以自由的组合,这样可以按程序需求来返回时间 和日期
时间的常量
const (
Nanosecond Duration = 1 //纳秒
Microsecond = 1000 * Nanosecond //微秒
Millisecond = 1000 * Microsecond //毫秒 Second = 1000 * Millisecond //秒
Minute = 60 * Second //分钟
Hour = 60 * Minute //小时
)
常量的作用:在程序中可用于获取指定时间单位的时间,比如想得到 100 毫秒
100 * time. Millisecond
Golang 设计者为了编程方便,提供了一些函数,这些函数可以直接使用,我们称为 Go 的内置函 数。文档:https://studygolang.com/pkgdoc -> builtin