• Golang学习之路4-函数/导入包/命令行参数/defer等


    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


    一、函数

    函数声明以func关键字开头,函数即代码块能够输入已经输出,格式:

    func name(parameter) (result-list){
        //body
    }
    
    • 1
    • 2
    • 3

    1.定义函数

    1.1单返回值函数

    // 单返回值函数,返回值定义可以不需要括号
    func add(a, b int) int{
    	return a + b
    }
    
    • 1
    • 2
    • 3
    • 4

    1.2多返回值函数

    func ppl(a int, b int) (int, bool) {
    	c := a + b
    	isBool := false
    	if a*2 > c {
    		isBool = true
    	}
    	return c, isBool
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.3指定返回值变量名称函数,可直接return

    func ppl1(a int, b int) (number int, isBool bool) {
    	number = a + b
    	if a*2 > number {
    		isBool = true
    	}
    	return
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.4参数可变函数

    // 参数可变函数
    func ppl3(nums ...int)int{
    	fmt.Println("len of nums is : ", len(nums))
    	sum := 0
    	for _, v := range nums{
    		sum += v
    	}
    	return sum
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    完整代码:

    package main
    
    import "fmt"
    
    func main() {
    	a := 2
    	b := 2
    	fmt.Println(ppl(a, b))
    	fmt.Println(ppl1(a, b))
    	fmt.Println(ppl2(a, b))
    	fmt.Println(ppl3(a, b))
    }
    // 单返回值函数,返回值定义可以不需要括号
    func ppl2(a int, b int) bool {
    	number := a + b
    	if a*2 > number {
    		return true
    	}
    	return false
    }
    // 可多个形参,多个返回值需要定义使用括号,逗号分隔
    func ppl(a int, b int) (int, bool) {
    	c := a + b
    	isBool := false
    	if a*2 > c {
    		isBool = true
    	}
    	return c, isBool
    }
    // 当返回值有定义变量名称时,可以直接return
    func ppl1(a int, b int) (number int, isBool bool) {
    	number = a + b
    	if a*2 > number {
    		isBool = true
    	}
    	return
    }
    // 参数可变函数
    func ppl3(nums ...int)int{
    	fmt.Println("len of nums is : ", len(nums))
    	sum := 0
    	for _, v := range nums{
    		sum += v
    	}
    	return sum
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    2.匿名函数

    匿名函数,既没有函数名称直接调用

    // 匿名函数
    func() {
    	fmt.Println("匿名函数...")
    }()
    
    • 1
    • 2
    • 3
    • 4

    3.init函数

    • init函数没有参数和返回值
    • init函数不允许用户显式调用
    • init函数一般用作初始化
    package main
    
    import (
    	"fmt"
    	_ "ppl-golang/1-base/01/9-import/sub" // 仅会调用包的init函数
    )
    
    /*
    1.init函数没有参数和返回值
    2.init函数不允许用户显式调用
    3.init函数一般用作初始化
    */
    func init() {
    	fmt.Println("this is my init 111111")
    }
    
    func init() {
    	fmt.Println("this is my init 222222")
    }
    func main() {
    	//init()	不能这样调用
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    二、导入包import

    1.导入包使用关键字:import

    但是包又是什么呢?可以理解为某个功能模块

    • 公有:对外开放调用(pubic)包函数使用大写字母开头,否则无法调用;
    • 私有:不对外开放调用(private仅对同包名下的)包函数使用 小写字母开头;
    // 包
    package sub
    
    // 公有
    func Sub(a, b int) int {
    	return a - b
    }
    // 私有
    func low()  {
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.引用包

    package main
    
    import (
    	"fmt"
    	// . 表示包名下所有函数不推荐直接用,容易出现重复函数名冲突
    	. "ppl-golang/1-base/9-import/add"
    	// 导入包可在前面空格+重命名,如下:ppl
    	ppl "ppl-golang/1-base/9-import/sub"
    )
    func main() {
    	// 调用:包名.函数名
    	sum := Add(10, 5)
    	sub1 := ppl.Sub(sum, 2)
    	fmt.Println(sub1)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    三、命令行参数

    1.os.Args获取命令行参数

    os.Args,第一个参数是当前执行的程序,如Windows是xx.exe
    所以从第二个参数才是自定义的参数,切片为1,如下代码cmds[1]

    package main
    
    import (
    	"fmt"
    	"os"
    )
    func main() {
    	// 命令行参数
    	cmds := os.Args
    	fmt.Println("cmds个数=", len(cmds), "(需要>=2)")
    	if len(cmds) < 2 {
    		return
    	}
    	for k, cmd := range cmds {
    		fmt.Println("key:", k, " cmd:", cmd)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.初试命令行参数

    switch判断值相等,默认会加了 break,如果想继续穿透加上关键字:fallthrough

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	// 命令行参数
    	cmds := os.Args
    	fmt.Println("cmds个数=", len(cmds), "(需要>=2)")
    	if len(cmds) < 2 {
    		return
    	}
    
    	switch cmds[1] {
    	case "hello":
    		fmt.Println("cmds[1] is hello")
    	case "word":
    		// 如果值相等,默认会加了 break,如果想继续穿透加上关键字:fallthrough
    		fmt.Println("cmds[1] is word")
    		fallthrough
    	default:
    		fmt.Println("cmds[1] is default")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述


    四、标签

    用得较少,仅了解一下

    package main
    
    import "fmt"
    
    func main() {
    	// 标签名称是自定义
    LABEL1:
    	for i := 0; i < 2; i++ {
    		for j := 0; j < 5; j++ {
    			if j == 3 {
    				/*
    					goto LABEL1:i每次进入此标签被重置值
    					continue LABEL1:i每次进入此标签会记录上次的值(状态)
    					break LABEL1:直接结束指定位置的循环
    				*/
    				//goto LABEL1
    				//continue LABEL1
    				break LABEL1
    			}
    			fmt.Println(i, j)
    		}
    	}
    	fmt.Println("over!")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    五、const iota枚举

    const iota枚举

    package main
    
    import "fmt"
    
    const (
    	/*
    		1.iota是常量组计数器
    		2.iota从0计数,每行递增1,同一行多个只算一次
    		3.每隔常量组是独立的,如果再定义一个const会重iota新计数,不想被重新计数+1
    	*/
    	name         = iota
    	age          = iota
    	work         = iota
    	single                    // 未赋值,默认与上一个常量值相同
    	work1, work2 = iota, iota // iota计数同一行多个只算一次
    )
    
    func main() {
    	fmt.Println(name)
    	fmt.Println(age)
    	fmt.Println(work)
    	fmt.Println(single)
    	fmt.Println(work1)
    	fmt.Println(work2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述


    六、defer (延迟)

    defer 关键字,用于修饰语句、函数,确保这条语句在当前栈退出时执行,
    与init函数正好相反,init函数前置执行,defer后置执行,类似python读取文件 with open()。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	/*
    		defer 延迟用于修饰语句、函数,确保这条语句在当前栈退出时执行
    		一般用于清理工作,解锁、关闭文件操作,类似python读取文件 with open()
    	*/
    	fineName := "1-base/02/4-defer延迟.go"
    	redFine(fineName)
    }
    
    func redFine(fileName string) string {
    	f, err := os.Open(fileName)
    	defer f.Close()	// 在当前栈退出时执行关闭文件
    	if err != nil {
    		fmt.Println("打开文件失败:", fileName)
    	}
    	buf := make([]byte, 1024)
    	f.Read(buf)
    	fmt.Println(string(buf))
    
    	// 多个defer,执行顺序为倒序
    	defer fmt.Println(1111111)
    	defer fmt.Println(2222222)
    
    	// 匿名函数
    	defer func() {
    		f.Close()
    		fmt.Println("匿名函数关闭文件...")
    	}()
    	defer fmt.Println(33333333)
    	return string(buf)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    在这里插入图片描述
    End

  • 相关阅读:
    nacos 与 seata 的整合
    【云原生 | 从零开始学Kubernetes】十九、Kubernetes核心技术Service实战 下
    妙手ERP功能更新:Shopee认领配置中的主货号支持按后缀自动递增、Ozon采集箱支持批量编辑【颜色样本图】、TikTok Shop......
    串口子系统
    json字符串属性名与实体类字段名转换
    Python sorted函数及用法
    Java基础之数组、堆栈、变量、重载、权限修饰符、JavaBean、string、stringbuilder、ArrayList、泛型、单例设计模式
    JetBrains IDE中GPU进程(JCEF)重启问题(Too many restarts of GPU-process)解决方案
    Java设计模式七大原则-迪米特法则
    基于 Redisson 和 Kafka 的延迟队列设计方案
  • 原文地址:https://blog.csdn.net/qq_42675140/article/details/127594092