前言
这是Go常见谬误系列的第14篇:适度应用getter和setter办法。
素材来源于Go布道者,现Docker公司资深工程师Teiva Harsanyi。
本文波及的源代码全副开源在:Go常见谬误源代码,欢送大家关注公众号,及时获取本系列最新更新。
常见谬误和最佳实际
现状
写Java或者C++的人,可能会习惯上面的编程模式:
- 将不心愿内部间接拜访的类成员变量设置为private公有成员。
- 在类里定义public的get和set办法,用于内部获取和批改这个成员变量的值。get办法咱们叫做getter,set办法叫做setter。
这是一种数据封装模式,在Java和C++里被宽泛应用。
然而在Go语言里,官网素来没有倡议应用getter和setter,咱们能够间接拜访构造体里的成员变量。
成员变量的可见性通过构造体标识符首字母大小写以及成员变量首字母大小写来管制到package这个层面。
- 如果构造体要被其它package应用,那构造体的标识符或者说构造体的名称首字母要大写。
- 如果构造体的成员要被其它package应用,那构造体和构造体的成员标识符首字母都要大写,否则只能在以后包里应用。
举个Go规范库里的time.Timer构造体的例子:
// The Timer type represents a single event.// When the Timer expires, the current time will be sent on C,// unless the Timer was created by AfterFunc.// A Timer must be created with NewTimer or AfterFunc.type Timer struct { C <-chan Time r runtimeTimer}
Timer构造体定义如上所示,外面有一个成员变量C
用于接管Timer到点后的以后工夫。
Timer和C都是大写,所以咱们能够间接在上面的代码里拜访Timer里的成员变量C拿到以后工夫。
package mainimport ( "fmt" "time")func main() { // print current time fmt.Println(time.Now()) // NewTimer creates a new Timer that will send // the current time on its channel after at least duration d. timer := time.NewTimer(5 * time.Second) // print current time fmt.Println(<-timer.C)}
下面程序执行后果是:
2022-11-06 13:07:07.706011 +0800 CST m=+0.0001742562022-11-06 13:07:12.709128 +0800 CST m=+5.003141645
这种写法当然不是Go官网所预期的,因为成员变量C
一般来说是不间接对外拜访。
如果C
裸露了能够对外拜访,那咱们甚至批改C
的值,导致程序出错。
只管不举荐这种写法,然而通过这个例子,咱们能够晓得如下事实:
Go规范库里对于构造体里不应该批改的字段,也没有应用getter和setter办法。
辩证来看
只管Go官网没有应用getter和setter,然而从另一方面来说,在一些特定场景下应用getter和setter是有益处的。
- getter和setter暗藏了外部实现,咱们能够本人灵便管制该裸露哪些货色。
- 如果成员变量的值产生了预期之外的变动,那通过getter和setter,咱们能够不便做一些调试,更快发现问题。
Go语言里如果要应用getter和setter办法,有一些命名标准须要遵循。
假如咱们要对构造体里的成员变量balance减少getter和setter办法,那么标准如下:
- getter办法应该被命名为Balance(而不是GetBalance)。
- setter办法应该被命名为SetBalance。
- 首字母大写是因为要被内部package应用,要大写来保障可见性。
示例如下:
currentBalance := customer.Balance()if currentBalance < 0 { customer.SetBalance(0)}
总结
- Java/C++等语言里罕用的getter和setter,在Go语言里并不是常规和标准。
- 然而如果发现有下面讲到的须要应用到getter和setter的场景,那还是应该应用的,而不是齐全不必。
- getter和setter办法命名参考下面提到的命名标准。
举荐浏览
- Go面试题系列,看看你会几题?
- Go常见谬误第1篇:未知枚举值
- Go常见谬误第2篇:benchmark性能测试的坑
- Go常见谬误第3篇:go指针的性能问题和内存逃逸
- Go常见谬误第4篇:break操作的注意事项
- Go常见谬误第5篇:Go语言Error治理
- Go常见谬误第6篇:slice初始化常犯的谬误
- Go常见谬误第7篇:不应用-race选项做并发竞争检测
- Go常见谬误第8篇:并发编程中Context应用常见谬误
- Go常见谬误第9篇:应用文件名称作为函数输出
- Go常见谬误第10篇:Goroutine和循环变量一起应用的坑
- Go常见谬误第11篇:意外的变量遮蔽(variable shadowing)
- Go常见谬误第12篇:如何破解箭头型代码
- Go常见谬误第13篇:init函数的常见谬误和最佳实际
开源地址
文章和示例代码开源在GitHub: Go语言高级、中级和高级教程。
公众号:coding进阶。关注公众号能够获取最新Go面试题和技术栈。
集体网站:Jincheng's Blog。
知乎:无忌。
福利
我为大家整顿了一份后端开发学习材料礼包,蕴含编程语言入门到进阶常识(Go、C++、Python)、后端开发技术栈、面试题等。
关注公众号「coding进阶」,发送音讯 backend 支付材料礼包,这份材料会不定期更新,退出我感觉有价值的材料。
发送音讯「进群」,和同行一起交流学习,答疑解惑。
References
- https://livebook.manning.com/...
- https://github.com/jincheng9/...