如何提高golang的可读性

栏目: 编程语言 · Clojure · 发布时间: 5年前

内容简介:反例:从这个例子来看,在service层和数据库查询,我们都进行了userId的判断. 因为当我们经常会忘记,我们是否在上一层入参的时候进行了userId为空的判断. 为了避免空指针,我们不得已一层层进行判断.假如我们尽早地返回,那么就可以避免后续的层层判空

1. 尽早返回

反例:

//UserCtrl
func UserInfo(userId string){
  user.UserInfo(userId)
  ....
  ....
  //resp result ...
}

//UserService
func UserInfo(userId string){
  if len(userId) > 0 { 
    //do query database 
    .....
  } 
}
// repo
func queryUserInfo(userId string){
  if len(userId) > 0{
    //select * from user where user_id = ?
  }
}

从这个例子来看,在service层和数据库查询,我们都进行了userId的判断. 因为当我们经常会忘记,我们是否在上一层入参的时候进行了userId为空的判断. 为了避免空指针,我们不得已一层层进行判断.

假如我们尽早地返回,那么就可以避免后续的层层判空

推荐写法:

//userCtrl
func UserInfo(userId string){
  if len(userId) == 0 {
    //resp some error
  }
  user.UserInfo(userId)
}

2. 写好分支语句

反例:

func xxx(lang string){
  if lang == "java"{
    doA()
  } else {
    doB()
  }
  
  if lang == "java"{
    doC()
  }else{
    doD()
  }
}

推荐写法:

func java(lang string){
  doA()
  doC()
}

func other(lang string){
  doB()
  doC()
}

if都需要包含else

反例:

if cmd == "1" {
  if status == 0 {
    doSome()
  }
}else {
  if tag == 1 {
    doSomeB()
  }
}

推荐写法:

if cmd == "1" {
  if status == 0 {
    
  }else{
    
  }
}else {
  if tag == 1{
    
  }else {
    
  }
}

避免啰嗦的条件

if isDone() == true {
  do()
}

推荐:

if isDone() {
  doSome()
}

使用switch语句

反例:

if lang == "java"{
  
}else if lang == "c#" {
  
}else if lang == "clojure"{
  
}

推荐写法:

switch lang:
case "java":
case "c#":
case "clojure":

减少逻辑表达式:

逻辑表达式是门电路的表达式,总会有人不能记得他的先后执行顺序。

反例:

if lang == "java" || lang == "c#" && lang == "clojure" {
  doSome()
}

如果非得使用逻辑表达式,推荐使用括号,显示地说明调用的顺序.

if (lang == "java" || lang == "c#") && lang == "clojure" {
  doSome()
}

使用正序的逻辑

反例:

if !isUserInfoSaved() {
  doA()
}else {
  doB()
}

if !isNotStop() {
  doSome()
}

用一个符合人类思考顺序方式来写分支,减少阅读代码时的时间

if isUserInfoSaved() {
  doB()
}else {
  doA()
}

if isStart(){
  doSome()
}

3.合理使用局部变量

可能我们知道定义一个变量会开辟一块新的内存,有时候觉得自己重复使用一个变量,会让性能"好一些", 于是我们就会写出下面的代码

反例:

var name
if login {
  name = "user"
  doSome(name)
}else {
  name = "guest"
  doSome(name)
}

其实在栈上开辟内存的成本很低,编译器会对代码进行逃逸分析,而且执行完这个方法后,内存就会被回收掉,所以不用担心这个性能问题.

推荐写法:

if login {
    //使用局部变量
  name := "user"
  doSome(name)
}else {
  name := "guest"
  doSome(name)
}

有的时候我们会想耍个酷,那么牛逼的调用一行代码就写完了,可是这时候阅读起来是非常痛苦的一件事情.

反例:

saveXXX(queryRole(),queryOrder(),saveXXX(queryUserInfo(genUserId())))

推荐写法:

我们把参数通过一个中间变量存起来,这样会很明显地说明,我们都干了些什么.

userInfo := queryUserInfo(genUserId)
u := saveXXX(userInfo)
saveXXX(queryRole(),queryOrder(),u)

4.循环

循环本身就不好读,假如在循环中包含continue,break之类的,让原本的代码更难读

反例:

for i,itm := range Users {
  if item.Name != "admin" {
    continue
  }else {
    doSome()
  }
}

推荐写法:

for i,itm := range Users {
  if item.Name == "admin" {
    doSome()
  }
}

使用i,j之类的下标,本身就比较相似,一不小心就会造成了下标越界,推荐使用foreach

反例:

for i:=0 ; i< len(users); i++ {
   for j:=0 ; j < len(users[i].children); j++ {
     // doSome
   }
}

推荐写法

for _,itm := range users {
  for _, c := range item{
    //dosome
  }
}

假如非得使用下标操作,也要避免使用i,j之类的变量

for uidx :=0 ; uidx< len(users); uidx++ {
   childen := users[uidx].children  //使用中间变量,避免臃肿
   for chidx:=0 ; chidx < len(childen); chidx++ {
       // chidx 和 uidx 能避免混淆,能在使用的过程中避免出错。
   }
}

5.面条代码, 过程式代码

面条代码过程式代码

type UserInf struct {
  UserName   string
  UserId     string
  Role       *Role
  Alias     string
}

type Role struct {
  Id string
  Name string
}

func save(inf *UserInf){
  Role(inf)
  inf.Alias = genAlias()
  update(inf)
}

func update(inf *UserInf){
  //update ....
}

func Role(inf *UserInfo) {
  queryUser(inf)
  inf.Role = queryRole(inf.UserId)
}

func queryUser(inf *UserInf){
  //select * from user where user_id = ?
  inf.UserName = ...
  inf.xxx = ...
}

思考: 为什么要使用纯函数?

6. 控制代码的长度

人的左脑关心的是逻辑,右脑做的是快照(可能是伪科学),实际情况中,假如我们一眼能看完,是不是剩下的就是在想逻辑,而不是一边读代码,一边想逻辑,这样能让我们大脑一次性把看到的代码缓存起来,然后专注于想逻辑。简短的代码,也可以避免bug,所以方法建议都控制在100行之内。

7. 命名

这个放最后来写的原因是这个命名本来就很难,命名得好就会让代码清晰可读,命名不好,就会误导导致需要大量的注视来注释代码,本来维护代码已经是一件痛苦的事情了,假如在修改了代码后,注释没有同步修改,反而会引起误导。因为母语不是英文,很多同学跟我一样也都很痛苦,这里可以上网找找相关命名的资料,本人水平有限也只能是大概地举几个例子

bool isStart // 服务启动的状态,最好使用正向的表达,是否启动,不推荐使用  bool isNotStop
func ComputeUserScore() //计算用户积分,假如这是一个耗时的操作,推荐在方法名上就表示出来,不推荐使用GetUserScore,
func DownloadFile() //下载文件,不推荐使用GetFile

个人博客 https://youkale.github.io


以上所述就是小编给大家介绍的《如何提高golang的可读性》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

你不知道的JavaScript(上卷)

你不知道的JavaScript(上卷)

[美] Kyle Simpson / 赵望野、梁杰 / 人民邮电出版社 / 2015-4 / 49.00元

JavaScript语言有很多复杂的概念,但却用简单的方式体现出来(比如回调函数),因此,JavaScript开发者无需理解语言内部的原理,就能编写出功能全面的程序;就像收音机一样,你无需理解里面的管子和线圈都是做什么用的,只要会操作收音机上的按键,就可以收听你喜欢的节目。然而,JavaScript的这些复杂精妙的概念才是语言的精髓,即使是经验丰富的JavaScript开发者,如果没有认真学习也无......一起来看看 《你不知道的JavaScript(上卷)》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具