包
程序运行入口是 main 包
1 | package go |
导入
使用 import 导入包
1 | import ( |
可以一次导入多个包
导出
首字母大写是被导出的
1 | package main |
这里 PrintLn 和 Pi 首字母大写
函数
函数可以没有参数或者接受多个参数
1 | package main |
这里会做设定变量类型设定,类型在变量名之后, 在大括号前做返回类型设定
函数可以返回多个值,如果连续多个函数参数都是同种类型,则类型判定可以写在最后
1 | package main |
上面的 a,b:=xxxx
类似解构复制
命名返回值
在函数大括号前的返回类型设定可以直接命名返回值,并且若返回值类型相同,类型也可以写在最后
函数体内的 return 可以没有参数,此时会返回哥哥变量的当前值,此种方法被称为裸返回,返回
的变量的名称应当有一定意义。
1 | package main |
变量
使用 var 定义一个变量列表,类型在变量后面,var 可以写在包或者函数内
当定义变量时候没有初始化赋值,会赋值 零值
- 数值类型为 0
- 布尔类型为 false
- 字符串为 “” 空字符串
1 | package main |
初始化变量
定义变量时候可以包含初始值
1 | var i,j int=1,2 |
如果初始化变量时候使用表达式,则可以省略定义类型,变量直接从初始值中获取类型
短声明变量
函数中 :=
简介赋值语句在明确类型的地方可以代替 var
的定义,其不能用在函数外
1 | package main |
打包声明
同打包引入一样,变量也可以打包声明
1 | var ( |
基本类型
- bool
- string
- int
- int
- int8 (byte)
- int16
- int32 (rune)
- int64
- uint
- uint8
- uint16
- uint32
- uint64
- uintptr
- float32
- float63
- complex64
- complex128
当无特别理由时候,定义整数类型时,首选 int
类型转换
直接使用‘基本类型方法’转换即可,例如
1 | var i int=42 |
go 需要显式转换
或者使用 :=
1 | i:=42 |
1 | package main |
类型推导
在下面这个例子中,使用了类型推导
i:=42
这里i为int类型,当为浮点数时,这个类型推导取决于赋值的常量精度。此时使用 fmt.Printf
会返回变量类型
1 | package main |
上面这个 %T\n
会对返回的值做一次处理,不加上的话会返回
1 | type%!(EXTRA string=232eqw4)% |
常量
常量使用 const
定义
for循环
go只有一种循环。for 循环
1 | package main |
和js很像,只是没了 for 后面的条件语句的括号,并且
这个初始化语句和后置语句都是可选的。
1 | package main |
省略分号
当省略分号时候,for循环即变成了 “while”循环
1 | package main |
if语句
同for语句,if语句也不需要把条件用括号括起来。并且在条件语句中执行的简单语句
作用域在其花括号之内,也可以在其对应的else块中使用
switch语句
同if语句,其执行顺序是从上到下,当匹配成功时候停止执行,当switch没有设置条件时候
等同于设置了 switch true,然后可以在case里面写判断条件,类似于 if else if else
1 | package main |
defer语句
defer语句会延迟函数的执行,直到上层函数返回,
延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用
1 | package main |
defer 栈
延时调用的函数会被压入到一个栈中,当函数调用时,会按照后进先出顺序
1 | package main |
指针
& 符号会生成一个作用其对象的指针, * 符号表示指针指向其底层的值
1 | package main |
结构体
struct 就是一个字段的集合,和js的对象相似
1 | package main |
通过 . 来读取和写入
结构体指针
1 | package main |
这里go和js第对象处理不同,js对象是引用传递的(默认就是传指针)
数组
1 | package main |
数组slice
可以通过以下方式赋值
1 | package main |
这里的slice可以理解和数组的项,数组的slice也可以为一个slice,这样就可以是多维数组
对slice切片
1 | package main |
这里slice用法和js相同。
构造 slice
slice可以由函数 make 创建。会分配一个全是零值的数组并返回一个slice指向这个数组
1 | a:=make([]int,5) //len(a)=5 |
make函数接受三个参数,
1 | b:=make([]int,0,5) //len(b)=0 cap(b)=5 |
这里cap是内建函数 容量
nil slice
slice 的零值是 nil
一个nil 的slice的长度和容量是0
向slice末尾添加元素
使用内建函数 append,类似于js push
1 | package main |
range
for 循环的 range 格式可以对 slice 或者 map 进行迭代循环。
当使用 for 循环遍历一个slice时,没戏迭代range将返回两个值,一个是当前slice下标,一个是该
下标对应元素的一个拷贝。
1 | package main |
这里如果要忽略索引值可以把 i 换成 _ ,如果需要忽略value值,则把 v 和前面逗号删除即可。
map
map 映射键到值
map在使用之前必须用make来创建;值为 nil 的 map 是空的,并且不能对其赋值。
1 | package main |
map有点像对象数组
map 语法
map语法和结构体语法类似,不过必须有键名。
1 | package main |
这里看到 map 和js中的对象是非常类似的。
但是注意是每个 “键值对” 末尾都要有逗号,结构体也是
操作map
在 map m中插入或者修改一个元素
1 | m[key]=elem |
获取元素
1 | elem=m[key] |
删除元素,使用内建函数delete
1 | delete(m,key) |
通过双赋值检测某个键是否存在
1 | elem,ok = m[key] |
如果key在m中,则ok为 true,否则,ok为false,并且elem值是map这个元素类型的零值。
同样的,当从map中读取某个不存在的键是,结果是map的元素类型的零值。
函数的闭包
Go函数可以是一个闭包。闭包是一个函数值,他引用了函数体之外的变量。这个函数可以对这个引用的变量进行访问赋值。