前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang如何才能写出值得阅读的代码

Golang如何才能写出值得阅读的代码

作者头像
陌无崖
发布2019-08-21 17:56:19
6100
发布2019-08-21 17:56:19
举报

不忘初心,砥砺前行

作者 | 陌无崖

转载请联系授权

导语

什么样的代码,才算优雅的代码,身为程序员,写代码就像写文章,写出好的文章不仅自己读着赏心悦目,同时也会让读者受到启发。然而事实上,大多数我们去回顾或者维护我们之前的代码,浮现在你眼前的是对自己代码的厌恶,会严重怀疑当时写这些代码时,大概是脑子进了水。那么该如何写好的优雅的代码?

Hello World

我们仍然从最简单的开始,编写一个hello函数

代码语言:javascript
复制
func Hello(name string) string {
    return "Hello," + name
}

现在我们进行需求变更,我们希望用不同的语言发送hello….

代码语言:javascript
复制
func Hello(name string, language string) string {
    if language == "Franch" {
        return "用Franch进行问好:Hello," + name
    } else if language == "English" {
        return "用English进行问好:Hello," + name
    } else if language == "Spanish" {
        return "用Spanish进行问好:Hello," + name
    }
    return "hello," + name
}

我们暂时只用这个例子,想一下,如果我们的语言非常多,我们将会出现很多if else的语句,而且我们也发现在返回数据时,有一些前缀,我们是否可以将这些统一进行变量进行更好的管理呢?因此我们需要用到switch语句。 首先需要定义前缀

代码语言:javascript
复制
const (
    frenchHelloPrefix  = "用Franch进行问好:"
    englishHelloPrefix = "用English进行问好:"
    SpanishHelloPrefix = "用Spanish进行问好:"
    common             = "Hello,"
    English            = "English"
    Franch             = "Franch"
    Spanish            = "Spanish"
)

重新修改我们的函数

代码语言:javascript
复制
func Hello(name string, language string) string {
    prefix := ""
    switch language {
    case Franch:
        prefix = frenchHelloPrefix
    case English:
        prefix = englishHelloPrefix
    case Spanish:
        prefix = SpanishHelloPrefix
    default:
        prefix = ""
    }
    return prefix + common + name
}

这样我们很轻易的对我们的整体的思路进行了很好的组织,在case中只是专注了前缀,只用一个return返回结果便能达到我们的要求,并且我们的代码阅读时也会更加显得简洁。

type类型的巧妙使用

反面案例

首先需要明确我们的需求,我们将会定义一个钱包,实现存钱和取钱 首先定义一个结构体

代码语言:javascript
复制
type Wallet struct {
    balance int
}

存钱

代码语言:javascript
复制
func (w *Wallet) Deposit(amount int) {
    w.balance += amount
}

取钱

代码语言:javascript
复制
func (w *Wallet) Withdraw(amount int) error {
    if amount > w.balance {
        return errors.New("cannot withdraw, insufficient funds")
    }
    w.balance -= amount
    return nil
}

上面是一个非常简单的程序,但是却有一个缺点,在现实生活中,我们的钱包里面是什么样的呢?除了现金,我们也存了各种银行卡,如何才能准确的定义这些属性呢?可能有的同学会按照下面的格式进行定义。

代码语言:javascript
复制
type Wallet struct {
    balance       int //零钱
    creditbalance int //信用卡
    Bankbalance   int //银行卡

}

然后我们或许会猜到,他将会定义三个存储的函数进行存钱,是这样的

代码语言:javascript
复制
func (w *Wallet) Deposit(amount int) {
    w.balance += amount
}
func (w *Wallet) Depositcreditbalance (amount int) {
    w.creditbalance += amount
}
func (w *Wallet) DepositBankbalance   (amount int) {
    w.Bankbalance  += amount
}

这些代码看起来“简洁”大概是因为少吧,如果说在真正存钱时会出现验证,转账,等这些大概就不能称之为简洁了,代码中将会出现大量重复的代码那应该怎么改呢?

正面案例

我们需要为我们的各种类型重新定义变量,像这样

代码语言:javascript
复制
type coin int
type creditCard int
type BankCard int

有了这些类型,我们需要存钱是指定我们的类型所有我们同样也需要定义一些常量

代码语言:javascript
复制
const (
    CREDITCARD = "creditCard"
    BANKCARD   = "BankCard"
)

编写我们的函数

代码语言:javascript
复制
func (w *Wallet) Deposit(amount int, card string) {
    switch card {
    case CREDITCARD:
        w.creditbalance += creditCard(amount)
    case BANKCARD:
        w.Bankbalance += BankCard(amount)
    default:
        w.balance += coin(amount)
    }
}

这样我们只用了一个函数就完成了需求,同时逻辑因为有了变量也变得更加的清晰,代码也会给人一种阅读文章的感觉。 现在我们写一个取钱的函数,我们需要注意取钱时需要注意总金额不能超出金额的取钱。

代码语言:javascript
复制
func (w *Wallet) Withdraw(amount int, card string) error {
    switch card {
    case CREDITCARD:
        if creditCard(amount) > w.creditbalance {
            return InsufficientFundsError
        }
        w.creditbalance -= creditCard(amount)
    case BANKCARD:
        if BankCard(amount) > w.Bankbalance {
            return InsufficientFundsError
        }
        w.Bankbalance -= BankCard(amount)
    default:
        if coin(amount) > w.balance {
            return InsufficientFundsError
        }
        w.balance += coin(amount)
    }
    return nil
}

以上需要注意的是,在返回错误时,我同样定义了一个变量,这样做的好处是,将来如果错误的类型较多,我们可以提前预制好一些错误信息,进行返回,然后统一放在一个文件中,使用的时候,直接调用,修改的时候也会方便查找。在这里我的定义如下:

代码语言:javascript
复制
var InsufficientFundsError = errors.New("超出了总金额")

总结

当然除了以上的代码习惯,或许也有更好的方式,都在与平时写代码时多思考,多参考,多积累。我们的代码才会写的越来越好,以上的总结是我今天在学习测试驱动开发时的突然的代码启发,整理成的笔记。因为测试驱动前面的基础比较简单,等到我学到后面的,再总结分享。

END

今日推荐阅读

RabbitMQ系列笔记广播模式和路由模式 RabbitMQ系列笔记入门篇

RabbitMQ系列笔记work模式

RabbitMQ系列笔记work模式

protoc语法详解及结合grpc定义服务

Golang中Model的使用

基于Nginx和Consul构建高可用及自动发现的Docker服务架构

▼关注我,一起成长

主要分享 学习心得、笔记、随笔▼

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang技术杂文 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • Hello World
  • type类型的巧妙使用
    • 反面案例
      • 正面案例
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档