科普 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.
}
}
作业
- 写一个闭包函数
- 定义一个包,内部写一个test函数,只给包内部用,写一个Test1函数,给外部包用,在main包内调用
- 使用go语言打印99乘法表
- 定义一个长度为100的数组,初始化前5个值都为8,第66个值为66
- 通过两种方式循环打印出上面的数组
- 将上面的数组的数据倒序放在另一个100长的数组中