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

科普 python 注释 #

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

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

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

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

重复定义是错误的,个人代码里有不少重复定义,只是为了写出来,你 copy 过去用的时候记得把重复定义删掉github

函数高级

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

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

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

在 go 语言中没有像 python 中的装饰器语法糖,但能够本身实现相似功能flask

// 内层函数
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长的数组中