为完成某一功能的程序指令(语句)的集合 称为函数
在Go 中 函数分为:自定义函数 系统函数
func函数名(形参列表)(返回值列表){
执行语句…
return返回值列表
}
1)形参列表:表示函数的输入
2)函数中的语句:表示为了实现某一功能代码块3)函数可以有返回值,也可以没有
package main
import "fmt"
func main() {
// 编写一个简单的计算器
f := jisuan(1, 1, '/')
fmt.Println(f)
}
func jisuan(n1 float64, n2 float64, fuhao byte) float64 {
var res float64
switch fuhao {
case '+':
res = n1 + n2
case '-':
res = n1 - n2
case '*':
res = n1 * n2
case '/':
res = n1 / n2
}
return res
}
1)在实际的开发中,我们往往需要在不同的文件中,去调用其它文件的定义的函数,比如main.go中,去使用utils.go文件中的函数,如何实现?-》包
2)现在有两个程序员共同开发一个Go项目,程序员xiaoming希望定义函数Cal ,程序员xiaoqiang也,想定义函数也叫Cal。两个程序员为此还吵了起来怎么办?-》包
1)区分相同名字的函数、变量等标识符
2)当程序文件很多时,可以很好的管理项目
3)控制函数、变量等访问范围,即作用域
1)在给一个文件打包时,该包对应一个文件夹,
比如这里的utils文件夹对应的向名计是utilc· coomcr文件的包名通常和文件所在的立杜屯夕·wc—般为小写字母。
2)当一个文件要使用其它包函数或变量时,需要先引入对应的包1)引入方式1: import “包名”
2)引入方式2:
package mainimaport (
import (
“fmt-
“包名”
“go_codc/ projcct/utils””
“包名”
3) package指令在文件第一行,然后是import指令。
4)在import包时,路径从$GOPATH的 src下开始,不用带src ,编译器会自动从src下开始引入
func main() {
编写一个简单的计算器
//f := util.Jisuan(1, 1, '/')
fmt.Println(f)
//getsum := Getsum(1, 1)
//fmt.Println(getsum)
test(4)
}
// 递归
func test(n1 int) {
if n1 > 2 {
n1--
test(n1)
}
fmt.Println("n1=", n1)
}
1)执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)2)函数的局部变量是独立的,不会相互影响
3)递归必须向退出递归的条件逼近,否则就是无限递归,死龟了:)
4)当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回
给谁。同时该函数执行完毕之后或者返回时 也会被销毁
请使用递归的方式,求出斐波那契数1,1,2,3,5,8,13…给你一个整数n,求出它的斐波那契数是多少?
// 请使用递归的方式,求出斐波那契数1,1,2,3,5,8,13...给你一个整数n,求出它的斐波那契数是多少?
func fb(n1 int) int {
if n1 == 1 || n1 == 2 {
return 1
} else {
return fb(n1-1) + fb(n1-2)
}
}
1)函数的形参列表可以是多个,返回值列表也可以是多个。2)形参列表和返回值列表的数据类型可以是值类型和引用类型。
3)函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写该函数可以被本包文件和其它包文件使用,类似public,首字母小写,只能被本包文件使用,其它包文件不能使用,类似privat
4)函数中的变量是局部的,函数外不生效
5)基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影
响到原来的值
6)如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以
指针的方式操作变量。从效果上看类似引用
7)Go函数不支持重载。
每一个源文件都可以包含一个init函数,该函数会在main函数执行前,被Go运行框架调用,也就是说init会在main函数前被调用。
package main
import "fmt"
func init() {
fmt.Println("init()...")
}
func main() {
fmt.Println("main().....")
}
D:\ruanjian\go\go1.19.1.windows-amd64\go\bin\go.exe build -o C:\Users\86152\AppData\Local\Temp\GoLand\___go_build_gopl_Demo_initdemo.exe gopl/Demo/initdemo #gosetup
C:\Users\86152\AppData\Local\Temp\GoLand\___go_build_gopl_Demo_initdemo.exe
init()...
main().....
当有全局变量跟main函数 init 函数 同时出现的时候 执行的顺序是 全局函数==》init函数==》main函数
package main
import "fmt"
var age = test()
func test() int {
n1 := 90
fmt.Println("全局变量。。。")
return n1
}
func init() {
fmt.Println("init()...")
}
func main() {
fmt.Println("main().....", age)
}
D:\ruanjian\go\go1.19.1.windows-amd64\go\bin\go.exe build -o C:\Users\86152\AppData\Local\Temp\GoLand\___go_build_gopl_Demo_initdemo.exe gopl/Demo/initdemo #gosetup
C:\Users\86152\AppData\Local\Temp\GoLand\___go_build_gopl_Demo_initdemo.exe
全局变量。。。
init()...
main()..... 90
如果在main.go文件中引入了其他的文件的 两个文件中都有init函数跟全局变量 那么执行的顺序是什么?
Go支持匿名函数,如果我们某个函数只是希望使用一次,可以考虑使用匿名函数,匿名函数也可以实现多次调用。
func main() {
res := func(n1 int, n2 int) int {
return n1 + n2
}(10, 20)
fmt.Println(res)
}
基本介绍:闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)
在函数中 经常用于创建资源(比如 数据库的链接 文件句柄 锁 等)为了在函数执行完毕后 及时的释放资源 Go 设计者提供 defer (延时机制)
package main
import "fmt"
// 测试 defer
func sum(n1 int, n2 int) int {
// defer 会在函数执行完成之后 执行 写了 defer 后 默认进入一个单独的栈中 最后先入后出
defer fmt.Println("n1=", n1)
defer fmt.Println("n2=", n2)
res := n1 + n2
fmt.Println(res)
return res
}
func main() {
i := sum(10, 20)
fmt.Println(i)
}
1,当执行到一个defer时 不会立即执行defer 后的语句 而是将defer 后的语句压入到一个栈中 然后继续执行 先入后出
2,在defer 将语句放入到栈时 也会将相关拷贝同时入栈
代码
package main
import "fmt"
// 测试 defer
func sum(n1 int, n2 int) int {
// defer 会在函数执行完成之后 执行 写了 defer 后 默认进入一个单独的栈中 最后先入后出
defer fmt.Println("n1=", n1)
defer fmt.Println("n2=", n2)
// 这里加加的时候 此时 n1 的值是 11 n2 是 21 但是当我们输出的时候
n1++
n2++
res := n1 + n2
fmt.Println(res)
return res
}
func main() {
i := sum(10, 20)
fmt.Println(i)
}
在链接数据库或者其他的时候用来释放资源、
值类型参数默认就是值传递 而引用类型参数默认就是引用传递
1》值传递
2》引用传递
不管是值传递还是引用传递 传递给函数的都是变量的副本 不同的是 值传递的是值得拷贝 引用传递的是地址的拷贝 一般来说地址拷贝效率高 因为数据量小 而值拷贝决定的数据大小 数据越大 效率越低。
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// 字符串长度
str := "冯娇娇是美女"
fmt.Println(len(str))
// 遍历字符串
str1 := "hahahhaha娇娇"
r := []rune(str1)
for i := 0; i < len(r); i++ {
fmt.Printf("i=%c\n", r[i])
}
// 字符串转换 整数
str2 := "111"
atoi, _ := strconv.Atoi(str2)
fmt.Printf("atoi 的类型 %T\n", atoi)
// 整数转换字符串
age := 19
itoa := strconv.Itoa(age)
fmt.Printf("itoa 的类型 %T \n", itoa)
// 字符串转换 byte
bytes := []byte("fengjiaojiao")
fmt.Printf("bytes 的类型 %T \n", bytes)
// byte 转换字符串
str = string([]byte{11, 55, 99})
fmt.Printf("str 的类型 %T \n", str)
// 查找子串在不在字符串中
contains := strings.Contains("fengjiaojiao", "f")
fmt.Printf("contains %v \n", contains)
// 查看出现的次数
count := strings.Count("jiaojiao", "j")
fmt.Printf("count %v \n", count)
// 比较不区分大小写的 字符串 (== 是区分大小写的)
fold := strings.EqualFold("abc", "ABC")
fmt.Printf("fold=%v \n", fold)
// index 第一次出现 index 的时候的值
index := strings.Index("kiko", "k")
fmt.Printf("index= %v \n", index)
// 最后一次出现的位置
index1 := strings.LastIndex("kiko", "o")
fmt.Printf("index1= %v \n", index1)
// 将指定的子串替换成 另外一个子串 最后一个-1 表示全部替换的意思
replace := strings.Replace("goland", "go", "kiko", -1)
fmt.Printf("replace= %v \n", replace)
// 按照指定的某个字符 分割 拆成字符串数组
split := strings.Split("f e n g j i a o j i a o", " ")
for i := range split {
fmt.Println(split[i])
}
// 大小写字母的转换
strings.ToLower("Go")
strings.ToUpper("kiO")
// 将字符串左右俩边的空格去掉
strings.TrimSpace(" kiko ")
// 将字符串左右两边指定的字符去掉
strings.TrimLeft("!bbb", "!")
strings.TrimRight("!bbb", "!")
// 判断字符串是否以指定的字符串开头或结束
strings.HasPrefix("http", "h")
strings.HasSuffix("http", "h")
}
package main
import (
"fmt"
"time"
)
func main() {
// 获取当前时间
now := time.Now()
fmt.Printf("now=%v now type=%T", now, now)
// 通过 time 获取 年月日时分秒
fmt.Printf("%v \n", time.Now().Year())
fmt.Printf("%v \n", int(time.Now().Month()))
fmt.Printf("%v \n", time.Now().Day())
fmt.Printf("%v \n", time.Now().Hour())
fmt.Printf("%v \n", time.Now().Minute())
fmt.Printf("%v \n", time.Now().Second())
// 格式化时期和时间 2006/01/02 15:04:05 时间是开发者定的
fmt.Printf("%v \n", now.Format("2006/01/02 15:04:05"))
// 时间的常量类
for i := 0; i < 10; i++ {
fmt.Print(i)
time.Sleep(time.Second)
}
}
1 len 用来求长度 比如 string array slice map channel
2 new 用来分配内存 主要用来分配值类型 比如 int float32 struct 返回的是指针
3 make 用来分配内存 主要用来分配引用类型 比如 chan map slice
基本说明
package main
import "fmt"
func main() {
test()
fmt.Println("ddddd")
}
func test() {
defer func() {
err := recover()
if err != nil {
fmt.Println(err)
}
}()
num := 10
num1 := 0
res := num / num1
fmt.Println(res)
}
func readConf(name string)(err error) {
if name=="fff" {
// 这里就是读取...
return nil
} else {
return errors.New("读取失败")
}
}