go 奇技淫巧

1.go安装
设置GOPATH,GOROOT环境变量, GOPATH是工作目录,GOROOT为Go的安装目录
2. 导入默认包
如:import( . "fmt" ),调动时候可以写成Println("Hello World!"),而不是fmt.Println("Hello World!")。
3.从 GitHub 安装包
go get -u [仓库名]/[用户名]/[项目名] 如:go get -u github.com/o-ll-o/istio 使用时为 import "github.com/o-ll-o/istio"
4.go 编译不希望被看到源代码
go build -ldflags 命令,设置编译参数-ldflags "-w -s" 再编译后发布就行
4.1 操作符 "&" 取变量地址, "*" 通过指针访问目标对象
5.字符串通过反引号表示,转义字符会原样输出,如果想转移,反引号替换为双引号即可
str := Hello World! \n Hello Gopher! \n
6.数组可以指定索引进行初始化,感觉这种设计挺神奇的
var arrCount = [5]int{100, 2: 100} //指定索引位置初始化 {100,0,100,0,0}
7.不指定长度初始化数组
var arrPack = [...]int{10, 5: 100} //指定索引位置初始化,数组长度与此有关 {10,0,0,0,0,100}
8.数组元素类型支持”==,!=”操作符,那么数组也支持此操作,但如果数组类型不一样则不支持(需要长度和数据类型一致,否则编译不通过)
var arrRoom [20]int
var arrBed [20]int
println(arrRoom == arrBed) //true

9.数组是值类型传递,不过可以通过&取变量地址,而实现引用传递
var arr2 [5]int
newarr := arr2 //值传递
newarr2 := &arr2 //取变量地址而成为引用传递
arr2[2] = 100
fmt.Println(arr2[2], newarr[2], newarr2[2])
10.gopath 可以有多个,GOPATH可以有多个项目用";"分隔
11.a[low : high : max] max-low的结果表示容量,high-low的结果表示长度。
12.当我们在一个slice基础上重新划分一个slice时,新的slice会继续引用原有slice的数组。这样可能造成难以想象的内存使用,建议使用切片的内置函数copy; copy(res, raw[:3]) // 利用copy 函数复制,raw 可被GC释放
13.append 函数生成的切片,如果没有改变原有切片的容量,则还是原来的切片,如果切片的容量发生改变,则会变成一个新的切片。所以切片append操作会改变切片的内存地址。
14.在一个 nil 的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。
15.map 默认是无序的,不管是按照 key 还是按照 value 默认都不排序。如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序(使用 sort 包)。
16.switch case 匹配到case 后会执行case中的内容,并跳出,如果想强制执行后面的case代码用fallthrough,fallthrough不会判断下一条case的expr结果是否为true,会直接执行。
17. 在 switch 或 select 语句中,break 语句的作用结果是跳过整个代码块,执行后续的代码。
18.在Go语言中 panic 是一个内置函数,用来表示非常严重的不可恢复的错误。必须要先声明defer,否则不能捕获到panic异常。普通函数在执行的时候发生panic了,则开始运行defer(如有),defer处理完再返回,并且recover() 的调用仅当它在 defer 函数中被直接调用时才有效,recover 只能在 defer 修饰的函数中使用:用于取得 panic 调用中传递过来的错误值,如果是正常执行,调用 recover 会返回 nil,且没有其它效果。
19. 当defer被声明时,其参数就会被实时解析, 多个defer执行顺序为先进后出,其实就是从下往上执行。defer可以读取有名返回值,也就是可以改变有名返回参数的值
20.函数也可以作为函数类型被使用。函数类型也就是函数签名,函数类型表示具有相同参数和结果类型的所有函数的集合。函数类型的未初始化变量的值为nil,如果两个函数的参数列表和返回值列表的变量类型能一一对应,那么这两个函数就有相同的签名
21.内置函数中 new(T) 返回的是T的指针,而make函数返回的是T类型的值,对于传引用的函数,用new函数比较直接。
22.函数作为一等公民,需要语言支持。闭包的实现,就是把匿名函数做为一个变量,如果通过该函数重新声明,则其为另一个闭包。闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)
23.struct 创建表达式 new(Type) 和 &Type{} 是等价的。&struct1{a, b, c} 是一种简写,底层仍然会调用 new (),这里值的顺序必须按照字段顺序来写。
24.已经锁定的Mutex并不与特定的goroutine相关联,这样可以利用一个goroutine对其加锁,再利用其他goroutine对其解锁。
25.当一个指针被定义后没有分配到任何变量时,它的值为 nil。

一个指针变量通常缩写为 ptr。

符号 "" 可以放在一个指针前,如 “intP”,那么它将得到这个指针指向地址上所存储的值;这被称为反引用(或者内容或者间接引用)操作符;另一种说法是指针转移。

对于任何一个变量 var, 如下表达式都是正确的:var == (&var)
26.new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型
T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于 &T{}。
27.通过var m runtime.MemStats Mem(&m) runtime.ReadMemStats(m)查看内存的使用状态,通过runtime.GC()来做一次GC,不过GC的过程中会有一次短暂的性能下降。通过func SetFinalizer(obj interface{}, finalizer interface{})可以执行指定obj对象的释放,以及执行finalizer 回调函数,来做释放后的动作。
28.在Go中,Marshal()默认是设置escapeHTML = true的,会自动把 '<', '>', 以及 '&' 等转化为"\u003c" , "\u003e"以及 "\u0026",
序列化-对应编码:将对象转为内存中或持久化存储, 反序列化-解码:将内存中或持久化的数据转化为对象。
29.sturct 内容可以写到文件里面,或者从文件里面读取。
30.做系统的收尾工作可以用这段程序,比如系统在关闭是要将内存中的数据进行持久化,这是比较优雅的一个方法:

go signalListen()
func signalListen() {
    c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGUSR2)
    for {
        s := <-c
        //收到信号后的处理,这里只是输出信号内容,可以做一些更有意思的事
        fmt.Println("get signal:", s)
    }
}

31.Go 语言net包封装了系列API,在TCP连接中,服务端是一个标准的Listen + Accept的结构,而在客户端Go语言使用net.Dial或DialTimeout进行连接建立

posted @ 2021-10-25 09:41  O-ll-O  阅读(152)  评论(0编辑  收藏  举报