不忘初心,砥砺前行
作者 | 陌无崖
转载请联系授权
导语
什么样的代码,才算优雅的代码,身为程序员,写代码就像写文章,写出好的文章不仅自己读着赏心悦目,同时也会让读者受到启发。然而事实上,大多数我们去回顾或者维护我们之前的代码,浮现在你眼前的是对自己代码的厌恶,会严重怀疑当时写这些代码时,大概是脑子进了水。那么该如何写好的优雅的代码?
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服务架构
▼关注我,一起成长
主要分享 学习心得、笔记、随笔▼