GO 奇技淫巧

执行顺序

import --> const --> var --> init()
image.png

开发速度快

  • 编译快,因为只关注被直接引入的库
  • 强类型,省略了许多心力检查类型错误。

并行而非并发

大多数语言线程是并发,即在某一时间段来看,是多个任务一起执行,但在某一时间点,其实只执行了一个。
并行是在同一时间点一同执行的多个任务(利用了多核)。

数据类型注意

  • 字符串可以用数组下标方式取值,但不能赋值,会报编译型错误。
  • 数组的赋值是 传递,作为参数是一次复制操作。
  • 数组与切片的区别,指定元素个数的是数组,没指定的是切片
  • 切片取值是取的下标前闭后开的(myArray[2, 4])。
  • 切片的赋值是引用传递,若要值传递,用 copy(dst, src)

“nil != nil” 的问题

  • 同为 nil 的两个不同类型的 error 类型,它们不相等,
type Aerr struct{}

func (*Aerr) Error() string {
    return "got an A error"
}

func getAErr() *Aerr {
    return nil
}

func getCommongErr() error {
    return getAErr()
}

func main() {
    err := getCommongErr()
    println(err == nil) // false
    return
}

其他细节

  • defer 是栈式的调用原则。
  • goroutine 可以充分利用多核 cpu(runtime.GOMAXPROCS(n) 可以设置),是协程,类似线程,但比线程更轻量,占资源更少。像 java 也用了多核,但开启和关闭一个线程开销很大。
  • go 使用了组合设计模式,只需简单将一个类型嵌入到另一个类型,就能复用所有功能。
  • go 使用了行为建模,意思是实现了这些行为(方法),就是继承了这个接口。
  • go 的垃圾回收机制是交给了编译器来做,虽然会有一些额外开销,但降低了开发难度。
  • import _ <package> 引入了包并执行了它的 init() 函数。
  • go 的找包过程是找 go 的安装目录 /usr/local/go 下和 $GOPATH 下找的,所以如果 go get 安装不成功,可以按包名与目录名的对应关系将包 copy 到对应目录下,也可以改一下 GOPROXY参考
  • go clean main.go 可以删除 go build main.go 生成的 main 可执行文件。
  • go build ./package/path/... 三个点表示匹配所有字符串,即本级目录及以下所有的包。
  • go build . 表示以当前包名作为名称生成当前的可执行文件。
  • go doc [<package>|<builtin directive>] 生成文档,用于命令行查看
  • godoc -http=:8088 可生成本地所有包的文档,并映射到 http8088 端口,用于浏览器查看
  • 在项目中用 doc.go 写上包名,相当于一个空文件,可以添加注释用于注释专用文档,不过记得包内要写上包名。
  • Golang 中 time.Time 类型的零值对应的时间戳是个负值,表示的是 0001年01月01日;而 mongoDB中 date 的零值对应的时间戳是0,表示的是 1970年01月01日。因此这点要注意引起的 bug。
  • Golang 的 cast 包中,string 转换为 int 的方法,会将 “08”开头的字符串当做8进制处理,因而得到结果 0 或对应的8进制数据。
  • Golang 的数组是值类型的,而不是指针类型,所以 arr2 = arr1 后,更新 arr1 中的一个元素,arr2对应的元素不改变。PHP 中也是不变的,但 javascript 不一样,js中的 array 是引用类型。
  • 找代码库。golang 在 github 上建立了一个镜像库,如 https://github.com/golang/net 即是 https://golang.org/x/net 的镜像库,所以可以在 $GOPATH/src/golang.org/xgit clone https://github.com/golang/net.git。其他包一样。
  • := 引发的作用域问题。赋值时,若用 := 那左边就最好 都是 未曾定义过的变量;否则,就考虑用 =。因为可能会引发变量的作用域问题:
package main
func main() {
    var a int
    if a, b := 2, 5; b == 5 {
        println(a) // output: 2
    }
    println(a) // output: 0
}
  • forgoroutine。在 for 内定义的变量,在 goroutine func 中直接使用可避免传入值错误的问题:
    for _, item := range items {
        val := item
        go func() {
            fmt.Println("----------------- item:", val) // 直接用 item 非预期
        }()
    }
  • 浮点数比较不能用 == ,用 math.Fdim() 函数
  • for...range... 可自动辨别中文,即用 rune 类型
  • 切片是指向数组的指针。改动切片中某一个值,源数组的对应值会变。,只有当容量占满再 append 时,才会新建一个底层数组。
  • 接口:非侵入性,实现了接口定义的方法,就是实现了接口。接口组合,也是这个特性,可以随意组合(两个接口放在组合接口中)。
  • 通道:无缓冲、有缓冲。
  • 有缓冲和无缓冲的差别:无缓冲就相当于手传手地递东西;有缓冲就相当于暂时放在缓冲池的空位里等待对方来取。
  • 防并发,就是避免竞争,主要三种方式:
    • 原子方法:atomic 包对于基本数据的原子操作,另外还有 sync.once() 方法让全局只执行一次。
    • 加锁:暴力锁和委婉锁。
    • 通道,交换数据。
  • 通道的“有缓冲”和“无缓冲”这样理解:无缓冲就是双方手递手地传递物品,有缓冲时就可以临时放在缓冲区,满时放阻塞,空时取阻塞。
  • 关闭通道,但通道中还有数据怎么办?关闭通道后,不能再放数据,但依然可以取用。所以 val, ok := <-chans 这句中 若 ok 为 false 即表示了没值,也表示通道被关闭了。因为没被关闭的话,会在阻塞状态。
  • time.After() 函数常用于 timeout,它返回的一个 <-chan time.Time,当过时了后才返回值,不过时不返回。
  • “继承”的等效:嵌入类型。可以实现:
    • 增加新属性,新方法
    • “继承”方法
    • “复写”方法
  • 但嵌入类型没有接口中重载概念的等效
  • 方法的接受者。用 值 类型定义的方法,可以值和引用调,但用 引用 类型定义的方法,只能用 引用类型 调用。因为有些值类型没有引用的地址。比如 Duration(6)
  • golang 中, json 转 map,里面的数字是 float64 类型。
  • 可以这样来取命令行输入
r := bufio.NewReader(os.Stadin)
...
b, _, _ := r.ReadLine()
line := string(b)
  • 使用 map 时要注意 空映射nil映射,他们不同
  • os 包中这样定义 Stdin, Stdout, Stderr,这其实是 linux 的基础知识了,/dev/stdin 就是输入设备,就是键盘,/dev/stdout 就是标准输出设备,就是命令行
Stdin := NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout := NewFile(uintptr(syscall.Stdin), "/dev/stdout")
Stderr := NewFile(uintptr(syscall.Stdin), "/dev/stderr")
  • json.Unmarshal() 会根据一个约定的顺序查找目标结构对应的字段。顺序如下:
    • 包含 Foo 标签的字段
    • 名为 Foo 的字段
    • 首字母后面不区分大小写的 Foo 字段
  • append 不是线程安全的,当并发时可能导致数据丢失
  • 0 / 0 结果为 NaN1 / 0 结果为 +Inf
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容