• Go-函数高级使用-条件分支-包管理-for循环-switch语句-数组及切片-与或非逻辑符


    科普 python 注释 #

    为什么几乎就 python 中的注释是 # ?

    • 起初 python 在 linux 中用的最多,linux 中大量的配置、shell 脚本等都是 # 作为注释的,所以 python 的注释也就沿用了 #

    代码几乎都要写在 main 函数里执行(本文写的都是伪代码)

    本文仅是跟着视频学习做的笔记,并未花时间去校对,如有错误,别太当真

    重复定义是错误的,我的代码里有很多重复定义,只是为了写出来,你 copy 过去用的时候记得把重复定义删掉

    函数高级

    内层函数:定义在函数内部的函数

    闭包函数:定义在函数内部,对外部作用域有引用(闭包函数本质也是内层函数)

    • go 中函数内部定义的函数是不能有名的,需要定义匿名函数:没有名字

    在 go 语言中没有像 python 中的装饰器语法糖,但可以自己实现类似功能

    // 内层函数
    func test(a int) (func()) {
        // var c int = 100
        b := func() {
            fmt.println("我是内层函数(定义在了函数内部,但没有引用外部作用域)")
    	}
    }
    
    // 闭包函数
    func test(a int) (func()) {
        // var c int = 100
        b := func() {
            fmt.println(a)  // 是闭包函数,本身也是内层函数
    	}
    }
    
    
    // 模仿 python 装饰器的写法
    // 定义一个函数,传入函数,返回函数
    func test(a func()) func()  {
    	b:= func() {
    		fmt.Println("我先执行")
    		a()
    		fmt.Println("函数执行完了")
    	}
    	return b
    }
    
    func test2()  {
    	fmt.Println("xxxx")
    }
    
    func main() {
    	a := test2
    	a = test(a)
    	a()
    	//我先执行
    	//xxxx
    	//函数执行完了
    }
    
    

    给类型取别名 type MyFunc func(a, b int) func()

    取了别名之后,用了别名的变量和原来的类型不是同一个类型了

    // 给类型命别名
    func main() {
        type MyInt int
        var a MyInt = 10
        var b int = 90
        // a = b  // 会报错,类型不匹配
        a = MyInt(b)  // 强转成一个类型
    	fmt.Println(a)
    	// 90
    }
    
    
    // 用在函数上面来简化写法
    type MyFunc func(a int,b int) func()
    
    type MyInt int
    func test() (MyFunc)  {
    	c:= func(a int,b int) func(){
    		return func() {
                
    		}
    	}
    	return c
    }
    func main() {
    	var a MyInt=10
    	var b int =90
    	a=MyInt(b)
    	fmt.Println(a)
    	// 90
    }
    

    if else if else

    跟 js 的写法差不多

    • if 条件 { 三个之间不能有换行(所有语言每一句结束都应该有一个 ;,很多语言都做了封装),如果加了换行,go 会自动在条件后面加上 ;,那么语义就错了

    • 在条件中可以定义变量,但是它的作用域范围只在 if 判断内部使用

    package main
    
    import "fmt"
    
    func main() {
    	if a := 90; a > 90 {
    		fmt.Println("a>90")
    	} else if a > 70 {
    		fmt.Println("a>70")
    	} else {
    		fmt.Println(a)
    	}
    }
    //a>70
    

    包管理

    go 的包管理一直被人所诟病(go 还是一门比较年轻的语言,需要时间来成长)

    1)通常情况下,包名就是文件夹,在同一个文件夹下的 go 文件,文件里的包名必须一致

    2)同一个包下定义的东西(变量、常量、函数)不能重名

    • 下面的两个文件同在 mypackage 包下(里面写的 package),所以第二次写 test 函数时,goland 编辑器就直接报错了

    3)在包内定义的函数如果是小写字母开头,表示只能在包内使用(外部无法引用)

    • 要想在外部使用,必须首字母大写(函数定义的时候)

      package main
      import "fmt"
      import "mypackage"
      
      func main() {
      	mypackage.Test1()
      	fmt.Println("xxx")
      }
      

    4)go 里导包只能导到包名那一层,不能说导里面的方法属性这些(import 包名

    5)所有的包都必须在 gopath 路径下的 src 文件夹下

    • 目前 go 的包管理还不是很成熟,如果依赖了第三方包的不同版本,会不能兼容(只能有一个版本)

      如果非要兼容两个版本,开发的时候可以暂时先把 gopath 改一下,这样就可以放另一个版本了

    Go 语言架构

    GOPATH 的工作区包含 bin、src 和 pkg(没有这三个文件夹时需要自己创建)

    • src ------- 源码(包含第三方的和自己项目的)
    • bin ------- 编译生成的可执行程序
    • pkg ------ 编译时生成的对象文件

    下载第三方包

    go 是一个开源的社区语言,所以并没有 python 那样一个专门的 pipy 来下载模块镜像,都是去各个地方下载

    go get github.com/astaxie/beego(地址)

    比较热门的框架

    • beego 是中国人写的,所以官网文档也是中文的
    • gin 是外国人写的

    go 的优点之一

    • go 写小接口很快,也很简单,部署也非常方便(微服务可能比 flask 写起来还要快)

    可以了解一下 Supervisord(beego 官网文档里有)

    • 是一个用python写的进程管理工具
    • 由于 beego 的作者之一是 Python 的忠实拥护者之一,所以 orm 设计沿用了 django 的 orm

    for 循环

    for 循环的几种写法

    // 不能重复定义,这里面的代码只是案例
    package main
    
    import "fmt"
    
    func main() {
    	// 基础写法
    	for i := 0; i < 10; i++ {
    		fmt.Println(i)
    	}
    
    	// 三部分都可以省略
    	i := 0
    	for ; i < 10; i++ {
    		fmt.Println(i)
    	}
    
    	i := 0
    	// for ;i<10; {  // 或
    	for i < 10 { // 等同于 python 里的 while 循环 --> while True ==》 for True
    		fmt.Println(i)
    		i++
    	}
    
    	// 死循环
    	// for ;; {  // 或
    	for {
    		fmt.Println("xxx")
    	}
    
    	// 注意下作用域范围(循环里定义的变量只能在循环里用)
    
    	// --------中断或跳过本次循环--------
    	// 用的是 break 和 continue,和其他语言的用法是一样的
    
    	for i := 0; i < 10; i++ {
    		if i == 5 {
    			break
    		}
    		fmt.Println(i)
    	}
    	for i := 0; i < 10; i++ {
    		if i == 5 {
    			continue
    		}
    		fmt.Println(i)
    	}
    
    }
    
    

    switch 语句

    package main
    
    import "fmt"
    
    func main() {
    	//a := 10
    	//switch a {
    	//case 1:
    	//	fmt.Println("1")
    	//case 2, 3, 4:
    	//	fmt.Println("2-4")
    	//	fallthrough // 只要读到这个,会无条件执行下面一个 case 内容
    	//case 5:
    	//	fmt.Println("5,a 是 2-4时顺带执行我")
    	//default: // 都不匹配,会执行这个
    	//	fmt.Println("都不是")
    	//}
    	////都不是
    
    	// 无表达式的 switch
    	a := 10
    	switch {
    	case a > 10:
    		fmt.Println("a大于10")
    	case a < 10:
    		fmt.Println("a小于10")
    	default:
    		fmt.Println("a等于10")
    	}
    	// a等于10
    }
    
    

    数组及数组切片

    • 数组是同一类型元素的集合
    • 在定义阶段,长度和类型就固定了,以后不能更改(这和 python 的列表有很大的区别)
    • 数组不支持负数索引
    // 不能重复定义,这里面的代码只是案例
    package main
    import "fmt"
    
    func main() {
    	var a [5] int // 定义了一个长度为5的 int 类型数组
    	fmt.Println(a)
    	// [0 0 0 0 0]
    
    	a[1] = 100 // 索引是从 0 开始的
    	fmt.Println(a)
    	// [0 100 0 0 0]
    
    	// 定义并赋初值
    	var a [6]int = [6]int{1,2,3,4,5,6}
    	var a = [6]int{1,2,3}  // int 类型省略的几个自动用 0 填充
    	
    	a := [100]int{98:99} // 把第99个(索引是98)设置成99
    	a := [100]int{1,2,3,98:99,87:88}
    	// 不支持负数索引
        
    	var a = [...]int{}  // 不是数组不定长
    	fmt.Println(a)
    	// []
    
    	var a = [...]int{1,2,4}
    	fmt.Println(a)
    	// [1 2 4]
    
    }
    
    • 数组是值类型,所有函数传参都是 copy 传递(即 python 中的不可变类型)
    package main
    import "fmt"
    
    func main() {
    	a := [4]int{1,2,3}
    	test7(a)
    	fmt.Println(a)
    }
    
    func test7(b [4]int)  {
    	b[0]=100
    	fmt.Println(b)
    }
    
    // [100 2 3 0]
    // [1 2 3 0]
    

    go 1.5版本之前都是用C写的,但后面就开始用go语言写了

    • 数组的大小也是类型的一部分
    // a 和 b 不是同一个类型
    var a [4]int
    var b [5]int
    // 不同类型无法直接赋值,也无法直接做大小比较
    

    数组迭代

    package main
    import "fmt"
    
    func main() {
    	var a [4]int = [4]int{1,2,}
    	for i:=0;i<len(a);i++{  // len 可以获取数组长度
    		fmt.Println(a[i])
    	}
    	//1
    	//2
    	//0
    	//0
    
    	// 通过 range 迭代(range是一个关键字)
    	for i, v := range a {  // for 索引,值 range 可迭代对象
    		fmt.Println("-----", i)  // 索引
    		fmt.Println(v)  // 值
    	}
    	//----- 0
    	//1
    	//----- 1
    	//2
    	//----- 2
    	//0
    	//----- 3
    	//0
    
    	for i := range a {  // 一个值就是索引
    		fmt.Println("-----", i)
    	}
    	//----- 0
    	//----- 1
    	//----- 2
    	//----- 3
    }
    
    

    多维数组

    package main
    import "fmt"
    
    func main() {
        var a [7][2]int
        fmt.Println(a)
        // [[0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]
    
        a[0][1]=100
        fmt.Println(a)
        // [[0 100] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0]]]
    }
    

    与或非 && || !

    package main
    import "fmt"
    func main() {
    	a := 13
    	if !(a < 1 && a > 0 || a == 6) {
    		fmt.Println("success.")
            // success.
    	}
    }
    

    作业

    1. 写一个闭包函数
    2. 定义一个包,内部写一个test函数,只给包内部用,写一个Test1函数,给外部包用,在main包内调用
    3. 使用go语言打印99乘法表
    4. 定义一个长度为100的数组,初始化前5个值都为8,第66个值为66
    5. 通过两种方式循环打印出上面的数组
    6. 将上面的数组的数据倒序放在另一个100长的数组中
  • 相关阅读:
    Git的使用---6. 分支管理
    Git的使用---5. 工作区、暂存区和仓库
    虚拟机中安装 win2012 r2 tools工具 提示需要安装kb2919355
    【实验】OSPF的基本配置
    【实验】 OSPF和BFD联动
    【实验】VRRP+链路跟踪+BFD联动
    【实验】基于接口和全局DHCP
    【实验】静态LACP的链路聚合
    【实验】手工负载分担链路聚合
    【实验】vxlan的静态配置
  • 原文地址:https://www.cnblogs.com/suwanbin/p/12017161.html
Copyright © 2020-2023  润新知