区块链技术博客
www.b2bchain.cn

Go 代码整洁之道求职学习资料

本文介绍了Go 代码整洁之道求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

痛点:

  1. 工程刚开始非常整洁,随着时间的流逝,逐渐变得不太好维护了..
  2. 多人开发同一工程时,架构层次不清晰,重复造轮子?
  3. 接手了一个旧工程,如何快速理解架构与设计,从而快速上手做需求?

有规范的好处:

  1. 利于多人合作开发&理解同一模块/工程。
  2. 降低团队成员之间的代码沟通成本。
  3. 架构&代码规范明确,有效提高编码效率。

前言:

读这本书的时,第一个想到的问题就是:“什么是整洁的代码?”
书中列举了各位程序员鼻祖的名言,我整理总结了下,大概有下面几条:

  • 逻辑直截了当,令缺陷难以隐藏 。
  • 减少依赖关系,便于维护。
  • 合理分层,完善错误处理 。
  • 只做好一件事。没有重复代码。

代码是团队沟通的一种方式

工作的沟通,不只是每天lark拉群或者开会交流,代码也是我们很重要的沟通方式之一。

用代码写完需求,只是万里长征的第一步。我们要用代码表达自己的设计思想。如果我们团队大部分人都能按照一定规范、思路去写代码。那么,工作沟通成本会降低许多。
比如:某位同学之前负责的一个模块,被另一位同事接手了,或者随着业务的扩张,我们多个同学共同开发同一个工程/模块。如果我们的代码结构大同小异,分层清晰、注释合理,就会降低很多沟通成本。

因此,我们需要为团队创造整洁的代码。

一是降低团队内的代码沟通成本,二是便于今后项目需求的维护与迭代。

让营地比来时更整洁

随着需求的不断迭代,保持代码整洁、工程更易理解。

有时候,我们会维护一些老项目,或者交接过来的项目。代码可能不太美观,工程可能不太好理解。

一般我们会面临两种选择:

  1. 重构
  2. 优化迭代

重构的成本比较高,得先理解原有逻辑,再进行重新设计落地。代价大,周期长,短期看不到效果。

在人力有限的情况下。我们一般会先选择“优化迭代”。

这时候,我们每做一个新需求 / 修复一个bug时,我们要尽可能的去小范围“重构”。

每一次Merge,代码都比之前更干净,工程变得更好理解。那么,我们的工程就不会变的更糟。

清理不一定要花多少功夫。也许只是改一个更加容易理解的命名;抽象一个函数,消除一点重复/冗余代码;处理一下嵌套的 if / else 等等。

一、有意义的命名

名副其实:
起有意义的名字,让人一目了然。
一看这个变量,就能知道它存储的是什么对象。
一看这个方法,就能知道它处理的是什么事。
一看这个包名,就能知道它负责处理哪个模块。

看看反例:

var array []int64 var theList []int64 var num int64

看看正例:

var mrList []*MRInfo var buildNum int64

避免误导:
不要用太长或者很偏僻的单词来命名,也不要用拼音代替英文。
更不要用容易混淆的字母(字母+数字)。尤其是lO两个字母,和数字1和0太像了。

看看反例:

func getDiZhi() string {    // .. }  func modifyPassword(password1, password2 string) string {    // .. }

看看正例:

func getAddress() string {    // .. }  func modifyPassword(oldPassword, newPassword string) string {    // .. }

有意义的区分:
声明两个同类型的变量/函数,需要用有明确意义的命名加以区分。

看看反例:

var accountData []*Account var account []*Account  func Account(id int) *Account {     // ... }  func AccountData(id int) *Account {     // ... }

可读可搜索:
起可读的,可以被搜索的名字。

看看反例:

var ymdhms = "2021-08-04 01:55:55" var a = 1

看看正例:

var date = "2021-08-04 01:55:55" var buildNum = 1

命名规范(重点)

package

  • 同一项目下,不允许出现同名的package。
  • 只由小写字母组成。不包含大写字母和下划线等字符。
  • 简短并包含一定的上下文信息。例如timehttp等。
  • 不能是含义模糊的常用名,或者与标准库同名。例如不能使用util或者strings
  • 包名能够作为路径的 base name,在一些必要的时候,需要把不同功能拆分为子包。(例如应该使用encoding/base64而不是encoding_base64或者encodingbase64。)

以下规则按照先后顺序尽量满足

  • 不使用常用变量名作为包名。
  • 使用单数而不是复数。(关键字除外,例如consts
  • 谨慎地使用缩写,保证理解。

文件名

  • 文件名都使用小写字母,且使用单数形式,如需要可使用下划线分割。

函数和方法

Function 的命名应该遵循如下原则:

  • 对于可导出的函数使用大写字母开头,对于内部使用的函数使用小写字母开头。
  • 若函数或方法为判断类型(返回值主要为 bool 类型),则名称应以 has, is, can 等判断性动词开头。
// HasPrefix tests whether the string s begins with prefix. func HasPrefix(s, prefix string) bool {...
  • 函数采用驼峰命名,不能使用下划线,不能重复包名前缀。例如使用http.Server而不是http.HTTPServer,因为包名和函数名总是成对出现的。
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer. // It returns the length of r and a nil error. func (b *Builder) WriteRune(r rune) (int, error) {...
  • 遵守简单的原则,不应该像 ToString 这类的方法名,而直接使用 String 代替。
// String returns the accumulated string. func (b *Builder) String() string {...
  • Receiver 要尽量简短并有意义
    • 不要使用面向对象编程中的常用名。例如不要使用selfthisme等。
    • 一般使用 1 到 2 个字母的缩写代表其原来的类型。例如类型为Client,可以使用ccl等。
    • 在每个此类型的方法中使用统一的缩写。例如在其中一个方法中使用了c代表了Client,在其他的方法中也要使用c而不能使用诸如cl的命名。
func (r *Reader) Len() int {...

常量

  • 常量使用驼峰形式。(尽量不要用下划线)
const AppVersion = "1.1.1"
  • 如果是枚举类型的常量,需要先创建相应类型:
type Scheme string    const (      HTTP  Scheme = "http"      HTTPS Scheme = "https"   )

变量

  • 变量命名基本上遵循相应的英文表达或简写。
  • 采用驼峰命名,不能使用下划线。首字母是否大写根据是否需要外部访问来定。
  • 遇到专有名词时,可以不改变原来的写法。例如:
{      "API":   true,      "ASCII": true,      "CPU":   true,      "CSS":   true,      "DNS":   true,      "EOF":   true,      "GUID":  true,      "HTML":  true,      "HTTP":  true,      "HTTPS": true,      "ID":    true,      "IP":    true,      "JSON":  true,      "LHS":   true,      "QPS":   true,      "RAM":   true,      "RHS":   true,      "RPC":   true,      "SLA":   true,      "SMTP":  true,      "SSH":   true,      "TLS":   true,      "TTL":   true,      "UI":    true,      "UID":   true,      "UUID":  true,      "URI":   true,      "URL":   true,      "UTF8":  true,      "VM":    true,      "XML":   true,      "XSRF":  true,      "XSS":   true,  }

二、函数

短小

尽可能的缩短每个函数的长度。能抽象就抽象。
任何一个函数都不应该超过50行。甚至,20行封顶最佳。(PS:16寸mac满屏是60多行)
想象下,如果有个几百行,甚至上千行的函数。后面维护得多困难。

单参数

每个函数最理想应该是有0或1个入参。
尽量不要超过三个入参。如果超过,建议封装成结构体。

只做一件事

函数应该只做一件事,做好这件事,只做这一件事。

抽象层级

按顺序,自顶向下读代码/写代码。

看看反例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件核心表,写了20行     // 更新历史,写了40行     // 更新构建产物,写了20行     // ...代码越来越多,越来越不好维护。     return nil }

看看正例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件    err = updatePodMain(ctx, req)    if err != nil {       return err    }     // 更新历史    err = updatePodHistory(ctx, req)    if err != nil {       return err    }     // 更新Builds    err = updatePodBuilds(ctx, req)    if err != nil {       return err    }     return nil }  func updatePodMain(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodHistory(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodBuilds(ctx context.Context, req *UpdatePodReq) error {    // ... }

尽量少嵌套 if / else

看看反例:

func GetItem(extension string) (Item, error) {     if refIface, ok := db.ReferenceCache.Get(extension); ok {         if ref, ok := refIface.(string); ok {             if itemIface, ok := db.ItemCache.Get(ref); ok {                 if item, ok := itemIface.(Item); ok {                     if item.Active {                         return Item, nil                     } else {                       return EmptyItem, errors.New("no active item found in cache")                     }                 } else {                   return EmptyItem, errors.New("could not cast cache interface to Item")                 }             } else {               return EmptyItem, errors.New("extension was not found in cache reference")             }         } else {           return EmptyItem, errors.New("could not cast cache reference interface to Item")         }     }     return EmptyItem, errors.New("reference not found in cache") }

看看正例:

“`
func GetItem(extension string) (Item, error) {
refIface, ok := db.ReferenceCache.Get(extension)
if !ok {
return EmptyItem, errors.New(“reference not found in cache”)
}

痛点:

  1. 工程刚开始非常整洁,随着时间的流逝,逐渐变得不太好维护了..
  2. 多人开发同一工程时,架构层次不清晰,重复造轮子?
  3. 接手了一个旧工程,如何快速理解架构与设计,从而快速上手做需求?

有规范的好处:

  1. 利于多人合作开发&理解同一模块/工程。
  2. 降低团队成员之间的代码沟通成本。
  3. 架构&代码规范明确,有效提高编码效率。

前言:

读这本书的时,第一个想到的问题就是:“什么是整洁的代码?”
书中列举了各位程序员鼻祖的名言,我整理总结了下,大概有下面几条:

  • 逻辑直截了当,令缺陷难以隐藏 。
  • 减少依赖关系,便于维护。
  • 合理分层,完善错误处理 。
  • 只做好一件事。没有重复代码。

代码是团队沟通的一种方式

工作的沟通,不只是每天lark拉群或者开会交流,代码也是我们很重要的沟通方式之一。

用代码写完需求,只是万里长征的第一步。我们要用代码表达自己的设计思想。如果我们团队大部分人都能按照一定规范、思路去写代码。那么,工作沟通成本会降低许多。
比如:某位同学之前负责的一个模块,被另一位同事接手了,或者随着业务的扩张,我们多个同学共同开发同一个工程/模块。如果我们的代码结构大同小异,分层清晰、注释合理,就会降低很多沟通成本。

因此,我们需要为团队创造整洁的代码。

一是降低团队内的代码沟通成本,二是便于今后项目需求的维护与迭代。

让营地比来时更整洁

随着需求的不断迭代,保持代码整洁、工程更易理解。

有时候,我们会维护一些老项目,或者交接过来的项目。代码可能不太美观,工程可能不太好理解。

一般我们会面临两种选择:

  1. 重构
  2. 优化迭代

重构的成本比较高,得先理解原有逻辑,再进行重新设计落地。代价大,周期长,短期看不到效果。

在人力有限的情况下。我们一般会先选择“优化迭代”。

这时候,我们每做一个新需求 / 修复一个bug时,我们要尽可能的去小范围“重构”。

每一次Merge,代码都比之前更干净,工程变得更好理解。那么,我们的工程就不会变的更糟。

清理不一定要花多少功夫。也许只是改一个更加容易理解的命名;抽象一个函数,消除一点重复/冗余代码;处理一下嵌套的 if / else 等等。

一、有意义的命名

名副其实:
起有意义的名字,让人一目了然。
一看这个变量,就能知道它存储的是什么对象。
一看这个方法,就能知道它处理的是什么事。
一看这个包名,就能知道它负责处理哪个模块。

看看反例:

var array []int64 var theList []int64 var num int64

看看正例:

var mrList []*MRInfo var buildNum int64

避免误导:
不要用太长或者很偏僻的单词来命名,也不要用拼音代替英文。
更不要用容易混淆的字母(字母+数字)。尤其是lO两个字母,和数字1和0太像了。

看看反例:

func getDiZhi() string {    // .. }  func modifyPassword(password1, password2 string) string {    // .. }

看看正例:

func getAddress() string {    // .. }  func modifyPassword(oldPassword, newPassword string) string {    // .. }

有意义的区分:
声明两个同类型的变量/函数,需要用有明确意义的命名加以区分。

看看反例:

var accountData []*Account var account []*Account  func Account(id int) *Account {     // ... }  func AccountData(id int) *Account {     // ... }

可读可搜索:
起可读的,可以被搜索的名字。

看看反例:

var ymdhms = "2021-08-04 01:55:55" var a = 1

看看正例:

var date = "2021-08-04 01:55:55" var buildNum = 1

命名规范(重点)

package

  • 同一项目下,不允许出现同名的package。
  • 只由小写字母组成。不包含大写字母和下划线等字符。
  • 简短并包含一定的上下文信息。例如timehttp等。
  • 不能是含义模糊的常用名,或者与标准库同名。例如不能使用util或者strings
  • 包名能够作为路径的 base name,在一些必要的时候,需要把不同功能拆分为子包。(例如应该使用encoding/base64而不是encoding_base64或者encodingbase64。)

以下规则按照先后顺序尽量满足

  • 不使用常用变量名作为包名。
  • 使用单数而不是复数。(关键字除外,例如consts
  • 谨慎地使用缩写,保证理解。

文件名

  • 文件名都使用小写字母,且使用单数形式,如需要可使用下划线分割。

函数和方法

Function 的命名应该遵循如下原则:

  • 对于可导出的函数使用大写字母开头,对于内部使用的函数使用小写字母开头。
  • 若函数或方法为判断类型(返回值主要为 bool 类型),则名称应以 has, is, can 等判断性动词开头。
// HasPrefix tests whether the string s begins with prefix. func HasPrefix(s, prefix string) bool {...
  • 函数采用驼峰命名,不能使用下划线,不能重复包名前缀。例如使用http.Server而不是http.HTTPServer,因为包名和函数名总是成对出现的。
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer. // It returns the length of r and a nil error. func (b *Builder) WriteRune(r rune) (int, error) {...
  • 遵守简单的原则,不应该像 ToString 这类的方法名,而直接使用 String 代替。
// String returns the accumulated string. func (b *Builder) String() string {...
  • Receiver 要尽量简短并有意义
    • 不要使用面向对象编程中的常用名。例如不要使用selfthisme等。
    • 一般使用 1 到 2 个字母的缩写代表其原来的类型。例如类型为Client,可以使用ccl等。
    • 在每个此类型的方法中使用统一的缩写。例如在其中一个方法中使用了c代表了Client,在其他的方法中也要使用c而不能使用诸如cl的命名。
func (r *Reader) Len() int {...

常量

  • 常量使用驼峰形式。(尽量不要用下划线)
const AppVersion = "1.1.1"
  • 如果是枚举类型的常量,需要先创建相应类型:
type Scheme string    const (      HTTP  Scheme = "http"      HTTPS Scheme = "https"   )

变量

  • 变量命名基本上遵循相应的英文表达或简写。
  • 采用驼峰命名,不能使用下划线。首字母是否大写根据是否需要外部访问来定。
  • 遇到专有名词时,可以不改变原来的写法。例如:
{      "API":   true,      "ASCII": true,      "CPU":   true,      "CSS":   true,      "DNS":   true,      "EOF":   true,      "GUID":  true,      "HTML":  true,      "HTTP":  true,      "HTTPS": true,      "ID":    true,      "IP":    true,      "JSON":  true,      "LHS":   true,      "QPS":   true,      "RAM":   true,      "RHS":   true,      "RPC":   true,      "SLA":   true,      "SMTP":  true,      "SSH":   true,      "TLS":   true,      "TTL":   true,      "UI":    true,      "UID":   true,      "UUID":  true,      "URI":   true,      "URL":   true,      "UTF8":  true,      "VM":    true,      "XML":   true,      "XSRF":  true,      "XSS":   true,  }

二、函数

短小

尽可能的缩短每个函数的长度。能抽象就抽象。
任何一个函数都不应该超过50行。甚至,20行封顶最佳。(PS:16寸mac满屏是60多行)
想象下,如果有个几百行,甚至上千行的函数。后面维护得多困难。

单参数

每个函数最理想应该是有0或1个入参。
尽量不要超过三个入参。如果超过,建议封装成结构体。

只做一件事

函数应该只做一件事,做好这件事,只做这一件事。

抽象层级

按顺序,自顶向下读代码/写代码。

看看反例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件核心表,写了20行     // 更新历史,写了40行     // 更新构建产物,写了20行     // ...代码越来越多,越来越不好维护。     return nil }

看看正例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件    err = updatePodMain(ctx, req)    if err != nil {       return err    }     // 更新历史    err = updatePodHistory(ctx, req)    if err != nil {       return err    }     // 更新Builds    err = updatePodBuilds(ctx, req)    if err != nil {       return err    }     return nil }  func updatePodMain(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodHistory(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodBuilds(ctx context.Context, req *UpdatePodReq) error {    // ... }

尽量少嵌套 if / else

看看反例:

func GetItem(extension string) (Item, error) {     if refIface, ok := db.ReferenceCache.Get(extension); ok {         if ref, ok := refIface.(string); ok {             if itemIface, ok := db.ItemCache.Get(ref); ok {                 if item, ok := itemIface.(Item); ok {                     if item.Active {                         return Item, nil                     } else {                       return EmptyItem, errors.New("no active item found in cache")                     }                 } else {                   return EmptyItem, errors.New("could not cast cache interface to Item")                 }             } else {               return EmptyItem, errors.New("extension was not found in cache reference")             }         } else {           return EmptyItem, errors.New("could not cast cache reference interface to Item")         }     }     return EmptyItem, errors.New("reference not found in cache") }

看看正例:

“`
func GetItem(extension string) (Item, error) {
refIface, ok := db.ReferenceCache.Get(extension)
if !ok {
return EmptyItem, errors.New(“reference not found in cache”)
}

痛点:

  1. 工程刚开始非常整洁,随着时间的流逝,逐渐变得不太好维护了..
  2. 多人开发同一工程时,架构层次不清晰,重复造轮子?
  3. 接手了一个旧工程,如何快速理解架构与设计,从而快速上手做需求?

有规范的好处:

  1. 利于多人合作开发&理解同一模块/工程。
  2. 降低团队成员之间的代码沟通成本。
  3. 架构&代码规范明确,有效提高编码效率。

前言:

读这本书的时,第一个想到的问题就是:“什么是整洁的代码?”
书中列举了各位程序员鼻祖的名言,我整理总结了下,大概有下面几条:

  • 逻辑直截了当,令缺陷难以隐藏 。
  • 减少依赖关系,便于维护。
  • 合理分层,完善错误处理 。
  • 只做好一件事。没有重复代码。

代码是团队沟通的一种方式

工作的沟通,不只是每天lark拉群或者开会交流,代码也是我们很重要的沟通方式之一。

用代码写完需求,只是万里长征的第一步。我们要用代码表达自己的设计思想。如果我们团队大部分人都能按照一定规范、思路去写代码。那么,工作沟通成本会降低许多。
比如:某位同学之前负责的一个模块,被另一位同事接手了,或者随着业务的扩张,我们多个同学共同开发同一个工程/模块。如果我们的代码结构大同小异,分层清晰、注释合理,就会降低很多沟通成本。

因此,我们需要为团队创造整洁的代码。

一是降低团队内的代码沟通成本,二是便于今后项目需求的维护与迭代。

让营地比来时更整洁

随着需求的不断迭代,保持代码整洁、工程更易理解。

有时候,我们会维护一些老项目,或者交接过来的项目。代码可能不太美观,工程可能不太好理解。

一般我们会面临两种选择:

  1. 重构
  2. 优化迭代

重构的成本比较高,得先理解原有逻辑,再进行重新设计落地。代价大,周期长,短期看不到效果。

在人力有限的情况下。我们一般会先选择“优化迭代”。

这时候,我们每做一个新需求 / 修复一个bug时,我们要尽可能的去小范围“重构”。

每一次Merge,代码都比之前更干净,工程变得更好理解。那么,我们的工程就不会变的更糟。

清理不一定要花多少功夫。也许只是改一个更加容易理解的命名;抽象一个函数,消除一点重复/冗余代码;处理一下嵌套的 if / else 等等。

一、有意义的命名

名副其实:
起有意义的名字,让人一目了然。
一看这个变量,就能知道它存储的是什么对象。
一看这个方法,就能知道它处理的是什么事。
一看这个包名,就能知道它负责处理哪个模块。

看看反例:

var array []int64 var theList []int64 var num int64

看看正例:

var mrList []*MRInfo var buildNum int64

避免误导:
不要用太长或者很偏僻的单词来命名,也不要用拼音代替英文。
更不要用容易混淆的字母(字母+数字)。尤其是lO两个字母,和数字1和0太像了。

看看反例:

func getDiZhi() string {    // .. }  func modifyPassword(password1, password2 string) string {    // .. }

看看正例:

func getAddress() string {    // .. }  func modifyPassword(oldPassword, newPassword string) string {    // .. }

有意义的区分:
声明两个同类型的变量/函数,需要用有明确意义的命名加以区分。

看看反例:

var accountData []*Account var account []*Account  func Account(id int) *Account {     // ... }  func AccountData(id int) *Account {     // ... }

可读可搜索:
起可读的,可以被搜索的名字。

看看反例:

var ymdhms = "2021-08-04 01:55:55" var a = 1

看看正例:

var date = "2021-08-04 01:55:55" var buildNum = 1

命名规范(重点)

package

  • 同一项目下,不允许出现同名的package。
  • 只由小写字母组成。不包含大写字母和下划线等字符。
  • 简短并包含一定的上下文信息。例如timehttp等。
  • 不能是含义模糊的常用名,或者与标准库同名。例如不能使用util或者strings
  • 包名能够作为路径的 base name,在一些必要的时候,需要把不同功能拆分为子包。(例如应该使用encoding/base64而不是encoding_base64或者encodingbase64。)

以下规则按照先后顺序尽量满足

  • 不使用常用变量名作为包名。
  • 使用单数而不是复数。(关键字除外,例如consts
  • 谨慎地使用缩写,保证理解。

文件名

  • 文件名都使用小写字母,且使用单数形式,如需要可使用下划线分割。

函数和方法

Function 的命名应该遵循如下原则:

  • 对于可导出的函数使用大写字母开头,对于内部使用的函数使用小写字母开头。
  • 若函数或方法为判断类型(返回值主要为 bool 类型),则名称应以 has, is, can 等判断性动词开头。
// HasPrefix tests whether the string s begins with prefix. func HasPrefix(s, prefix string) bool {...
  • 函数采用驼峰命名,不能使用下划线,不能重复包名前缀。例如使用http.Server而不是http.HTTPServer,因为包名和函数名总是成对出现的。
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer. // It returns the length of r and a nil error. func (b *Builder) WriteRune(r rune) (int, error) {...
  • 遵守简单的原则,不应该像 ToString 这类的方法名,而直接使用 String 代替。
// String returns the accumulated string. func (b *Builder) String() string {...
  • Receiver 要尽量简短并有意义
    • 不要使用面向对象编程中的常用名。例如不要使用selfthisme等。
    • 一般使用 1 到 2 个字母的缩写代表其原来的类型。例如类型为Client,可以使用ccl等。
    • 在每个此类型的方法中使用统一的缩写。例如在其中一个方法中使用了c代表了Client,在其他的方法中也要使用c而不能使用诸如cl的命名。
func (r *Reader) Len() int {...

常量

  • 常量使用驼峰形式。(尽量不要用下划线)
const AppVersion = "1.1.1"
  • 如果是枚举类型的常量,需要先创建相应类型:
type Scheme string    const (      HTTP  Scheme = "http"      HTTPS Scheme = "https"   )

变量

  • 变量命名基本上遵循相应的英文表达或简写。
  • 采用驼峰命名,不能使用下划线。首字母是否大写根据是否需要外部访问来定。
  • 遇到专有名词时,可以不改变原来的写法。例如:
{      "API":   true,      "ASCII": true,      "CPU":   true,      "CSS":   true,      "DNS":   true,      "EOF":   true,      "GUID":  true,      "HTML":  true,      "HTTP":  true,      "HTTPS": true,      "ID":    true,      "IP":    true,      "JSON":  true,      "LHS":   true,      "QPS":   true,      "RAM":   true,      "RHS":   true,      "RPC":   true,      "SLA":   true,      "SMTP":  true,      "SSH":   true,      "TLS":   true,      "TTL":   true,      "UI":    true,      "UID":   true,      "UUID":  true,      "URI":   true,      "URL":   true,      "UTF8":  true,      "VM":    true,      "XML":   true,      "XSRF":  true,      "XSS":   true,  }

二、函数

短小

尽可能的缩短每个函数的长度。能抽象就抽象。
任何一个函数都不应该超过50行。甚至,20行封顶最佳。(PS:16寸mac满屏是60多行)
想象下,如果有个几百行,甚至上千行的函数。后面维护得多困难。

单参数

每个函数最理想应该是有0或1个入参。
尽量不要超过三个入参。如果超过,建议封装成结构体。

只做一件事

函数应该只做一件事,做好这件事,只做这一件事。

抽象层级

按顺序,自顶向下读代码/写代码。

看看反例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件核心表,写了20行     // 更新历史,写了40行     // 更新构建产物,写了20行     // ...代码越来越多,越来越不好维护。     return nil }

看看正例:

// 更新组件升级结果 func UpdatePodUpgradeResult(ctx context.Context, req *UpdatePodReq) error {    // 更新组件    err = updatePodMain(ctx, req)    if err != nil {       return err    }     // 更新历史    err = updatePodHistory(ctx, req)    if err != nil {       return err    }     // 更新Builds    err = updatePodBuilds(ctx, req)    if err != nil {       return err    }     return nil }  func updatePodMain(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodHistory(ctx context.Context, req *UpdatePodReq) error {    // ... }  func updatePodBuilds(ctx context.Context, req *UpdatePodReq) error {    // ... }

尽量少嵌套 if / else

看看反例:

func GetItem(extension string) (Item, error) {     if refIface, ok := db.ReferenceCache.Get(extension); ok {         if ref, ok := refIface.(string); ok {             if itemIface, ok := db.ItemCache.Get(ref); ok {                 if item, ok := itemIface.(Item); ok {                     if item.Active {                         return Item, nil                     } else {                       return EmptyItem, errors.New("no active item found in cache")                     }                 } else {                   return EmptyItem, errors.New("could not cast cache interface to Item")                 }             } else {               return EmptyItem, errors.New("extension was not found in cache reference")             }         } else {           return EmptyItem, errors.New("could not cast cache reference interface to Item")         }     }     return EmptyItem, errors.New("reference not found in cache") }

看看正例:

“`
func GetItem(extension string) (Item, error) {
refIface, ok := db.ReferenceCache.Get(extension)
if !ok {
return EmptyItem, errors.New(“reference not found in cache”)
}

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Go 代码整洁之道求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们