1. := 与var定义
在函数中,:=
简洁赋值语句在明确类型的地方,可以用于替代 var 定义。
函数外的每个语句都必须以关键字开始(var
、func
、等等),:=
结构不能使用在函数外。
常量用const
定义
slice
channle
map
必须使用make函数来定义
new 分配内存后置零,返回指针
make 分配内存后初始化, 返回对象
在满足下列条件时,已被声明的变量 v 可出现在:= 声明中:
- 本次声明与已声明的 v 处于同一作用域中,(若 v 已在外层作用域中声明过,则此次声明会创建一个新的变量v)
- 在初始化中与其类型相应的值才能赋予 v,且在此次声明中至少另有一个变量是新声明的。
2. 基本数据类型
bool |
单引号字符常量表示 Unicode Code Point,⽀支持 \uFFFF、\U7FFFFFFF、\xFF 格式。 对应 rune 类型,UCS-4。 |
3.Channel
channel 操作符 <- ,操作符只有这一个,这样就不会搞错位置了
发送者可以 close 一个 channel 来表示再没有值会被发送了。接收者可以通过赋值语句的第二参数来测试 channel 是否被关闭:当没有值可以接收并且 channel 已经被关闭,那么经过
v, ok := <-ch
之后 ok 会被设置为 false
。
循环 for i := range c
会不断从 channel 接收值,直到它被关闭。
注意: 只有发送者才能关闭 channel,而不是接收者。向一个已经关闭的 channel 发送数据会引起 panic。
还要注意: channel 与文件不同;通常情况下无需关闭它们。只有在需要告诉接收者没有更多的数据的时候才有必要进行关闭,例如中断一个 range
。
4.select
select
语句使得一个 goroutine 在多个通讯操作上等待。
select
会阻塞,直到条件分支中的某个可以继续执行,这时就会执行那个条件分支。当多个都准备好的时候,会随机选择一个。
当 select
中的其他条件分支都没有准备好的时候,default
分支会被执行。
为了非阻塞的发送或者接收,可使用 default 分支:
select { |
5.for range 遍历 range 会复制对象
for key, value := range oldMap { |
//若你只需要该遍历中的第一个项(键或下标),去掉第二个就行了:
for key := range m { |
6.Switch
switch 可以什么都不写 当多级if else使用 还可以当做判断类型使用 t.(type) 只能在switch使用
switch t := t.(type) |
7.Map
key不存在不会报错,会返回与map的value的类型对应的零值. 用if _,ok:=someMap[key];ok {}
来判断有没有值
8.Print
- 字符串函数(Sprintf 等)会返回一个字符串,而非填充给定的缓冲区。
- fmt.Fprint 一类的格式化打印函数可接受任何实现了
io.Writer
接口的对象作为第一个实参:如os.Stdout`
os.Stderr` - fmt.Printf
- %v(对应“值”)map中的键可能按任意顺序输出。
- 当打印结构体时,改进的格式 %+v 会为结构体的每个字段添上字段名,而另一种格式 %#v 将完全按照Go的语法打印值。
- 当遇到 string 或 []byte 值时, 可使用 %q 产生带引号的字符串;而格式 %#q 会尽可能使用反引号。
- %T 类型
- 若你想控制自定义类型的默认格式,只需为该类型定义一个具有 String() string 签名的方法。
9.append 中extend
x := []int{1,2,3} |
10.类型转换
要提取我们知道在该值中的字符串,可以这样:
str := value.(string)
但若它所转换的值中不包含字符串,该程序就会以运行时错误崩溃。为避免这种情况, 需使用“逗号, ok”惯用测试它能安全地判断该值是否为字符串:str, ok := value.(string)
if ok {
fmt.Printf("字符串值为 %q\n", str)
} else {
fmt.Printf("该值非字符串\n")
}
若类型断言失败,str 将继续存在且为字符串类型,但它将拥有零值,即空字符串。
11. x:=x
req := req
但在Go中这样做是合法且惯用的。你用相同的名字获得了该变量的一个新的版本, 以此来局部地刻意屏蔽循环变量,使它对每个Go程保持唯一。
比如gorm中
12.函数
变参 变参本质上就是 slice。只能有⼀一个,且必须是最后⼀一个。
func test(s string, n ...int) string { |
使⽤用 slice 对象做变参时,必须展开。func main() {
s := []int{1, 2, 3
}
println(test("sum: %d", s...)) }
匿名函数可赋值给变量,做为结构字段,或者在 channel ⾥里传送。
13.Defer
func add(x, y int) (z int) { |
多个 defer 注册,按 FILO 次序执⾏行。哪怕函数或某个延迟调⽤用发⽣生错误,这些调⽤用依旧 会被执⾏行。
func test(x int) { |
输出:c b a panic: runtime error: integer divide by zero
14. error
捕获函数 recover 只有在延迟调⽤用内直接调⽤用才会终⽌止错误,否则总是返回 nil。任何未捕获的错误都会沿调⽤用堆栈向外传递。
导致关键流程出现不可修复性错误的 使⽤用 panic,其他使⽤用 error。
15. 数组
a := [3]int{1, 2}// 未初始化元素值为 0。 |
16. slice
array
和slice
是不同的类型,不同长度的array类型不同 slice是[]int
array是[n]int
官方文档中说In Go, array is a fixed length of continuous memory with specified type, while slice is just a reference which points to an underlying array. Since they are different types, they can't assign value each other directly.