0x0 Golang语法
Golang的语法看起来像C++和JavaScript和Python的融合体,学过其他语言上手Golang的话其实会觉得比较别扭。(比如经典的没有分号,for和if的expression没有括号) 这里提一些Golang特有的写法
指针也用.访问field
有C / C++经验的同学学习的时候可能会疑惑为什么指针类型不用取值后再用.访问结构体成员,因为Golang在编译的时候就自动转换好了,这样可以减少大家开发过程中的错误。(当然现代IDE的补全也不会让大家犯符号的错误)
// 参考下面的结构体
type foo struct {
x, y int
}
var f1 *foo = &foo{}
var f2 foo = foo{}
// 两者都是通过f1.x, f1.y; f2.x, f2.y;去访问x, y
fmt.Println(f1.x) // 0
fmt.Println(f2.x) // 0
// 都输出0是因为开辟新内存都是0
条件语句赋值语法糖:
if val, ok := dict[x]; ok {
}
但需要注意的是,这样的语法糖val只能在if结构体内使用
同理的还有for在expression里赋值
make和new
这两者在Golang中存在很大的区别,有C++或者Java的经验的同学应该会更熟悉new但是在Golang中我们更常见make,这并不是说我们用make去malloc一切,而是我们不需要malloc,Golang在编译后会帮我们把声明赋值好的变量自动开辟内存,例如:
f1 := &foo{}
// 等价于
f3 := new(foo)
更多底层细节可以参考掘金的好文
slice切片扩容
在数组中我们有添加元素的需要通常会使用slice,但是其底层实现数组是定长的,因此Golang标准语法中就有了append,作为slice添加元素同时数组扩容的实现。
append(slice []Type, elems ...Type) []Type
使用append如果触发扩容,则会生成新的数组副本,因此在函数中传递切片的并在函数触发扩容的时候就要注意了坑了。如果是希望传参的切片是在函数内更新的话,请传切片地址作为参数,这样就能保证修改的都是原切片
关于append的坑,掘金里也有一篇好文帮大家试错了
goroutine
Golang的最大特点之一,协程,使用方式:
var dfs func = func (i, j int) {}
go dfs
go func() {}
只需要简单的go加func即可使用协程并发执行函数,多数情况下是需要各协程直接相互协作的,则引出下面特殊类型
channel 通道
学习过操作系统的同学对pipe都不陌生,在Golang中可以使用channel让进程通信
c := make(chan int) // new一个非缓冲channel(即会阻塞)
// 等价于
c := make(chan int, 0) // capacity为0
c := make(chan int, 10) // new一个缓冲区capacity为10的int通道
c <- 2 // 2写入
num := <- c // num读出
关于如何并发控制,掘金上有一篇好文章
0x1 Golang常用标准库记录
| Package Name | 用途 |
|---|---|
| fmt | 标准输入输出 |
| log | 日志库(但是比较简陋) |
| strings | 字符串操作 |
| strconv | 字符串转换其他类型 |
| bufio | 流读写 |
| net | 网络库(Golang的优势之一) |
| sync | 同步库,操作系统级实现锁 |
| atomic | 原子操作,硬件级实现锁 |
| time | 时间库 |
| math | 数学运算,随机数rand也在该库内 |
| testing | 测试 |
| 更多库及方法示例待更新 To be continue... |