func b(fun func(int, int) int, ...){...}
type myInt int
type myFun func(..)(..)
sum, sub := cal(3, 2)
func cal(n1 int, n2 int)(sum int, sub int){
sum = n1 + n2
sub = n1 - n2
return
}
sum, _ := cal(3, 2)
func sum(args... int)( sum int) {
for i := 0; i < len(args); i++ {
sum += args[i]
}
return
}
// args 是切片, 通过args[index]可以访问各参数
每个源文件都可以包函一个 init 函数, 该函数会在 main 函数之前执行
如果某个函数只希望执行一次, 那么可以使用匿名函数, 匿名函数也可以实现多次调用
使用方式:
res := func (n1 int, n2 int) int{
return n1 + n2
}(1, 2)
fmt.Println(res)
sum := func (n1 int, n2 int) int{
return n1 + n2
}
fmt.Println(sum(2, 3))
fmt.Println(sum(2, 4))
一个函数与其相关引用环境组合而成的一个整体
简单而言,闭包与普通函数的区别就在于它有了自己的上下文环境;
其实 java 对象的方法就是一种闭包
func addUpper() func(int) int{
n := 10
return func(i int) int{
n += i
return n
}
}
func main(){
f := addUpper()
fmt.Println(f(1)); //11
fmt.Println(f(2)); //13
fmt.Println(f(3)); //16
}
函数执行完毕后, 及时释放资源
当执行到 defer 语句时, 暂时将其压入 defer 栈中; 当程序执行完毕, 再从 defer 栈中以先进后出的原则进行执行
当 defer 语句入栈时, 会将相关的值进行拷贝同时入栈
func test(){
file := openfile(文件名)
defer file.close
}
无论值传递还是引用传递, 其本质都是值的副本传递, 不同的是:
值传递时, 是将值进行拷贝然后传递(基本类型的 int系列, float 系列, bool, string, 数组, 结构体)
引用传递, 是将地址进行拷然后传递(指针, 切片, map, 管道, interface)
1. fmt.Printf("%d-%d-%d %d:%d:%d", now.Year(), now.Month()....)
2. str := Sprintf("%d-%d-%d %d:%d:%d", now.Year(), now.Month()....)
3. now.Format("2006/01/02 15:04:05") //数字固定只能这样写
4. now.Format("2006/01/02") //数字固定只能这样写
5. now.Format("15:04:05") //数字固定只能这样写
1. 5 纳秒: 5*time.Namosecond
2. 5 毫秒: 5*time.Millisecond
....
func testErr(){
defer func(){
err := recover()
if err != nil{
fmt.Println(err)
}
}()
a, b := 1, 0
c := a/b
fmt.Println(c)
}
func testCustomErr(){
err := customErr("init.conf1")
if err != nil {
panic(err)
}
fmt.Println("其它代码......")
}
func customErr(fileName string)(err error){
if fileName == "init.conf" {
fmt.Println("读取配置文件")
return nil
}else{
return errors.New("不能读取配置文件")
}
}
1. var arr [3]int
2. var arr [3]int = [3]int {1, 2, 3}
3. var arr = [3]int {1, 2, 3}
4. var arr = [...]int{1, 2, 3}
5. var arr = [3]string{0:"tom", 1:"jack"}
func testForRange(){
arr := [...]string{"111", "222", "333"}
for index, value := range arr {
// 1. index 是数组下标
// 2. value 是该下标的值
// 3. range 是关键字
// 4. arr 是数组变量名
fmt.Println(index, value)
}
}
切片是长度可以变化的数组
切片是数组的一个引用, 传递时遵守引用传递
定义: var 切片名 []类型; 如: var arr []int
切片内存结构
使用方式
func testSlice(){
arr := [...]string{"111", "222", "333"}
//包含下标为1,2两个元素
slice := arr[1:3]
fmt.Println("slice = ", slice)
fmt.Println("sliece len = ", len(slice))
fmt.Println("slice cap = ", cap(slice))
}
2. 通过 make 来创建
var 切片名 []type = make([]type, len, [cap])
3. 通过直接定义并赋值
var slice []type = []type{}
func testMakeSlice(){
slice := make([]int, 2, 2)
slice[0], slice[1] = 1, 2
fmt.Println(&slice[0])
slice = append(slice, 3)
fmt.Println(&slice[0])
}
//切片追加一个切片
slice = append(slice, slice...)
func testStringSlice(){
str := "hello 世界"
bytes := []byte(str)
bytes[5] = '-'
fmt.Println(str)
fmt.Println(string(bytes))
//处理含有中文的字符串
bytes2 := []rune(str)
fmt.Println(len(bytes2)) //8
bytes2[6] = '中'
bytes2[7] = '国'
fmt.Println(string(bytes2))
}
func testMap(){
// 定义1
var map1 map[string]string
map1 = make(map[string]string, 2)
map1["111"] = "111"
map1["222"] = "222"
map1["333"] = "333"
// 定义2
var map2 = make(map[string]string, 2)
map2["111"] = "111"
map2["222"] = "222"
map2["333"] = "333"
// 定义3
var map3 = map[string]string{
"111":"1111",
}
map3["222"] = "222"
fmt.Println(map1)
fmt.Println(map2)
fmt.Println(map3)
}
func testMapForRange(){
userMap := map[string]string{
"01": "宋江",
"02": "卢俊义",
"03": "吴用",
}
for key, value := range userMap {
fmt.Printf("key = %v\tvalue = %v\n", key, value)
}
}
1. 先将 map 的 key 放入到切片中
2. 对切片排序: sort.Ints(slice)
3. 遍历切片, 然后按照 key 来输出 map 值