Effective Go summary

ninetyhe

格式

程序统⼀使⽤ ”gofmt“ 进行格式化;如果使用的IDE是Goland可以按照如下进行配置:PrePerences -> Tools -> FileWatcher(如果没有在plugins安装) :添加 go fmt;

推荐一并添加:golangci-lint 和 goimports。这样就可以进⾏语法检查和⾃动处理导入和删除包注释

// ⾏注释⽅式,⽤于简单的方法和字段注释

/* */ 块注释方式,本书推荐在每一个包前面注释,说明该包的主要作用

  /*

  function: do xxx

  */

  package regexp

名字

Go语⾔言的命名⼤小写,决定了该方法或者该类是否公有还是私有,本书推荐如果⽅法不对外调用,首字⺟建议小写,如果需要跨包调⽤则⾸字⺟需要大写;

包的命名统一使⽤用小写,并且不应该使⽤下划线或者驼峰。(这点表示有点别扭,如果名字真的过长的话,可读性会很差) Get/Set:Go不提供对Get和Set支持,但是推荐⾃己实现,但是对于Get建议直接⽤⾸字母代替,例如:如果你有一个域叫做owner(⼩写,不被导出),则Get方法应该叫做 Owner (大写,被导出),⽽不是 GetOwner (个人觉得有点反人类,⽽且protobuf generate 的pb文件的字段也是是 Getxx )。这里联想到⽬前我们⾃⼰用的gRPC,看到很多同学的字段命名都是大驼峰的,开始还以为gRPC有特殊不同的规范,后来查阅了官网更加肯定,对象的属性要⼩驼峰,字段的访问需要通过Get和Set来访问!⽅法命名:单个方法的接⼝口使⽤方法名加上“er”后缀来命名,或者类似的修改来构造⼀个施动者名词

分号

Go语⾔省略分号; {} 中的左 { 不能换行;条件语句省略 ()

控制结构

Go中的循环结构只用 for 语句,主要分为以下三种:

// 传统的for写法 for init; condition; post { }

// 对应其他语言中 while for condition { }

//⼀直循环 for { }

函数

⽀持多返回值,Go语⾔支持函数返回多个返回值,本书推荐也给返回值命名,这样对于以下int值对应哪

个就值就⼀⽬了然 例例如:

func (file *File) Write(b []byte) (n int, m int, err error)

延时执行defer;这是一种不不寻常但又很有效的方法,⽤于处理类似于不管函数通过哪个执行路径返回,

资源都必须要被释放的情况。经常⽤用于链接断开,释放锁或者关闭IO如果需要将⼀些值初始化,或者在代码执行前调⽤,可以在 init 函数实现,该函数会优先被执⾏;

数据

Go语⾔言使⽤new和make分配原语; new ⽤于给T类型的分配内存,但是并不会初始化内存,只是将其置为0; make 不同于 new ,它用于创建 silence , map 和 channel ,并返回一个初始化(⽽不是置0),类型给T的值。如果需要获得一个显式的指针,就必须只⽤用 new 分配。

构造器 :本书推荐结构体的属性值尽量不要有空或者空,通过构造器对其初始化;

数组 :在Go中:数组是值。将⼀个数组赋值给另一个,会拷⻉所有的元素;特别是,如果你给函数传递⼀个数组,其将收到一个数组的拷贝,⽽不是它的指针;组的大小是其类型的一部分。类型

[10]int 和 [20]int 是不同的。

切片 :切⽚持有对底层数组的引用,如果你将⼀个切⽚赋值给另⼀个,⼆者都将引用同⼀个数组,或你将切片的值进行修改,则原数组的内容也将发⽣改变

字典 :同切片一样,map持有对底层数据结构的引用。如果将map传递给函数,其对map的内容做了改变,则这些改变对于调⽤者是可⻅的。如果像判断Map释放包含该元素,需要使用 :

//感觉好蠢,并没有像Java那样有contains key或者contains value,//如果像⽅便使⽤且避免代码写成一坨,建议⾃⼰实现一个⽅法收敛该逻辑if value,ok := map[key];ok{

// if exist do some

}

//⽽不建议使⽤以下⽅式:value, ret := map1["key"]

if ret == true{

fmt.Print("map1[\"key\"]存在,值为:", i)

} else {

fmt.Print("map1[\"key\"],不存在\n")

}

初始化

常量 在编译的时候就被创建,并且只能是数字,字符(附文),字符串或者布尔类型。由于编译限制,

表达式必须为能被编译器求值的常量表达式, 例如:// 常量表达式

1<<3

// ⾮常量表达式,在const不可使用math.Sin(math.Pi/4)

init函数 如果需要将一些值初始化,或者需要预先调⽤⽅法函数,可以在 int 函数中实现;例如:

func init() {

//需要初始化调用方法

initFunction(a interface{},b interface{})

// 初始化变量

initParam

}

接⼝

通过法与接口,Go语⾔定义了一种与java/C++等OOP语言截然不同的“继承”的形态。通过实现接口定

义的方法,便可将reciever的类型变量赋值给接⼝类型变量,通过接⼝类型变量来调用到reciever类型的

⽅法 例如:

//定义了一个接口geometry表示几何类型type thisIsInterface interface {

    funcA() int32

    funcB(bool)

}

//实现类实现两个方法type IntImpl struct {

A, B float64

}

//在Go中,实现接⼝,只需要实现该接口定义的所有方法即可

//A接口方法实现

  func (r * IntImpl) funcA(res float64) {

    A *= res

    B *= res

}

func (r * IntImpl) funcB() float64 {

    return r.A * r.B

}

//可以把rect和circle类型的变量量作为实参

//传递给geometry接口类型的变量

func measure (i thisIsInterface){

    fmt.Print("i 's area:",i.funcA(),"\n")

    i.funcB(2)

    fmt.Print("after funcB , funcA :",i.funcA(),"\n")

}

func main() {

    i := IntImpl{A: 10, B: 5}

    measure(&i)

}

并发

Gorutine 轻量级并发的函数执行线索,创建开销初始化栈空间⽐较⼩,会根据实际需要堆的空间分配或

者释放额外空间Gorutine与操作系统线程间采用“多对多”的映射⽅方式,其他Gorutines不会因为其中⼀一个Gorutines阻塞后

⽽阻塞

在函数前加 go 关键字就可以创建⼀个Gorutine并调⽤该函数⽅法。当该函数执行完成之后隐式推出(类似于Java中的 Thread )

Channel:于map类似,也是通过 make 进⾏行行分配,如果创建的时候指定⼤小,如果⾮零则即创建一个

缓冲区。如果是零,则是⽆无缓冲的channel或同步channel

例例如:

stringBuffer := make(chan string,10)

value := <- stringBuffer

并行实现方式:可以创建多个go func 并行执⾏多个函数,然后通过sync.WaitGroup来实现阻塞等并⾏的结果(类似于Java中的 CountDownlunch ),但是功能相当简陋陋,功能相差更更远

互斥: 通过sync.Mutex可以创建锁进行互斥,例例如:

import (

"sync"

"runtime"

"fmt"

)

var {

//共享变量

num int

wg sync.WaitGroup

//锁

lock sync.Mutex

}

func Add(){

    defer wg.Done()

    for count := 0;ciunt < 2; count++{

        // lock

}

}

lock.Lock()

{

    value := num

    value++

    num = value

}

// release lock

lock.Unlock()

func main{

    wg.Add(2)

    go Add()

    go Add()

    wg.Wait()

    fmt.Printf("result is : %d\n", num)

}

结果如下:

result is : 4

类型断⾔

Go⾥面对类型判断有两种: value,ok := element.(T) 当然也可以直接这样用 (不推

荐) value:=element.(T) 这样的话,⼀旦出错就会产⽣运⾏错误,不推荐使用;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 在之前的课程中,我们已经学习了进程相关的知识。进程是计算机程序被执行的一个实例(instance),一个进程可能由...
    夏威夷的芒果阅读 895评论 0 2
  • 数组 和C语言一样,Go语言中也有数组的概念, Go语言中的数组也是用于保存一组相同类型的数据 和C语言一样,Go...
    极客江南阅读 1,199评论 0 2
  • 一、数据类型转换 https://studygolang.com/articles/10838 package m...
    蓓蓓的万能男友阅读 1,052评论 0 1
  • Golang是我最喜欢的一门语言,它简洁、高效、易学习、开发效率高、还可以编译成机器码… 虽然它一出世,就饱受关注...
    盘木阅读 3,540评论 0 7
  • Go语言数据类型 Go语言本质是用C语言编写的一套高级开发语言, 所以Go语言中的数据类型大部分都是由C语言演变而...
    极客江南阅读 914评论 0 6