go散记

246 阅读3分钟

golang从设计初就考虑实现跨平台,只需要改变编译参数就可以实现在Windows上编译在Linux可执行文件

golang 设计初就考虑网络和并发,所以标准库中很好的封装了关于网络和并发的包

golang设计以简洁为标准,要求每一行代码都能清楚的看到书写的目的,比如 fmt.printlIn(i++) 这样的代码就行不通,需要换两行书写 i++ fmt.printlin(i) 虽然写起来麻烦了,但是看起来优美简洁,没有歧义

go的主要战场

go的三大哲学 1.简洁 2.强大的自带标准库(很多项目只用标准库就可以实现) 3.向后兼容

语言比较

这里创建的时候用指针,不然每次作为参数传递的时候都要复制一份

使用这个把命令可以发现并发中竞争出错的具体代码,比如不同并发对同一个没有保护的数据读写

关闭的通道获取值不会panic,可以得到0

下面的示例中如果不加关闭通道,会造成13行死锁,因为for循环还在等待消息,但是不会有消息发送过来了,但是加上关闭通道,13行的for循环可以检测到,明白通道已经关闭,不再等待,跳出for循环

go mod tidy 可以检测出不需要的包,然后从go.mod里面移除出去

import 下划线(如:import _ hello/imp)的作用:当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。这个时候就可以使用 import _ 引用该包。即使用【import _ 包路径】只是引用该包,仅仅是为了调用init()函数,所以无法通过包名来调用包中的其他函数。

vendor包的作用 将引用的外部包的源代码放在当前工程的vendor目录下面,这样每次编译都能保证是同一个版本,如果每次go get不能保证版本是一样的,可能导致构建有问题

切片是建立在数组概念之上,是对数组的引用,切片存来不存储数据,只是指向数组的某个位置

append 是往一个切片里面复制值,对于 t1 = append(t1,t2...), t1.ptr ,t2.ptr并没有任何关系,只是把t2指向的数组的值复制给了t1,唯一可能有改变的是t1.ptr 如果t1.cap 不够大,会重新分配一片空间给t1,t1.ptr变成新的地址空间

切片a &a是a在内存中的地址,一般是固定的,不会随着切片的增删改查有变动,a是指a里面存储的值,是一个指针,指向第一个元素的地址,所以a 和 &a[0] 的值是一样的,如果底层数组有内存变动,地址改了,这个值会变的

线程和go routine对比

当前时间戳的获取

t,_ = time.ParseInLocation("2006-01-02 15:04:05",roomInfo.Ctime, time.Local)
timestamp := t.Unix()

直接使用 time.Parse 得到的时间会比中国时间多8小时

go get必须在一个module下面使用,否则报错 go get' is no longer supported outside a module.

所以创建项目之后,要go mod init 创建一个module才能用

设置mod之后go get 下载的文件都在pkg/mod文件夹下面

go get 的作用是

init 函数

1.在main方法执行之前会对引用的包的init初始化方法优先执行,而且成程序包依赖关系的顺序执行,比如main包里面依赖了a,但是a里面依赖了b,那么b的init方法也会启动时执行,如果b没有被任何包引用以来就不会执行,不过想不出有包独立存在没有依赖关系还不是废文件的场景?所以有用的包应该都会被执行吧?