Golang学习笔记:常见问题
Golang学习笔记:常见问题标签(空格分隔): golang
1. Golang的特点和发起目的Golang的特点以及要解决的问题概括起来就是三点: 2. Golang设计原则
3. 为什么没有泛型Generics may well be added at some point. We don’t feel an urgency for them。为什么需要泛型可以参考这篇文章,但是泛型可以带来好处也会增加复杂度,golang可能以后会添加泛型支持,目前是一个open issue。 4. 为什么没有exceptions这点是golang遭受用户(尤其是c++,java用户)诟病的重要原因,实际上Golang提供了panic,recover语法类似try catch。但是个人理解为什么没有只是一个选择问题,而不是技术问题。在很多语言的编码风格里尤其是Objective-C,一般都是使用Error Object来传递错误,虽然现在try catch的性能损失可以忽略不计,但是try catch的坏处是容易滥用,导致用户忽略error和exception的区别,另外Golang提供的多返回值也方便了error传递这种风格的使用,我个人对这种设计并不反感。 5. 为什么没有assertion和没有exceptions有点类似: programmers use them as a crutch to avoid thinking about proper error handling and reporting,当然这种牵强的说法作者自己也有点没底气:We understand that this is a point of contention. There are many things in the Go language and libraries that differ from modern practices,simply because we feel it’s sometimes worth trying a different approach。 6. 为什么build concurrency on the ideas of CSP(Communicating Sequential Processes) 7. Why goroutines instead of threads把线程控制的复杂度从用户空间转移到语言层面(用户层面不需要关系协程还是线程,让并发的使用简单和高效是其设计目的)。The Go scheduler 8. 为什么map非线程安全知道map非线程安全就行了,这种设计大都是一个trade off 9. Golang是面对对象语言吗这个问题不太对,面对对象更多的是一种设计,而非语言特性,只是不同语言的实现和支持有所不同。在Golang里面的方式是interface,无type hierarchy,subclass的方式有点类似C,比C++等更general。同时Golang里面的Method也更general,可以给任何类型添加方法,总的来说的就是轻量级,更简单却能做更多事。个人觉得是Golang里最美的设计,面试官再问你会不会面对对象编程,你就打他脸。 10. 为什么Golang没有运算符或者方法重载没什么好说的,运算符和方法重载没什么用。即使在提供这类功能的语言里面也不要使用(除非一些极端场合如数据处理框架重载+*符号用于运算矩阵,这个场合非常少,更多时候这种功能大概会带来1%的便利和1000%的代码混乱和可读性降低)。 11. interface的一个有疑问的例子Why doesn’t type T satisfy the Equal interfacetype Equaler interface {
Equal(Equaler) bool
}
type T int
func (t T) Equal(u T) bool { return t == u } // does not satisfy Equaler
因为Equaler的Equal函数需要的类型不同,正确的实现方式为 type T2 int
func (t T2) Equal(u Equaler) bool { return t == u.(T2) } // satisfies Equaler
另一个例子
type Opener interface {
Open() Reader
}
func (t T3) Open() *os.File
//T3 does not satisfy Opener,although it might in another language.
Golang没有自动类型转换,也没有多态(类之间),这也是作者的trade off 12. Error和nil的一个例子func returnsError() error {
var p *MyError = nil
if bad() {
p = ErrBad
}
return p // Will always return a non-nil error.
}
这和interface的实现有关:
一个更直观点的例子
type myError struct{}
func (this *myError) Error() string { return "" }
var error1 *myError = nil
var error2 error = error1// to interface => error2 != nil
13. go不支持tagged or untagged unionuntagged union不安全,tagged union或者Variant types,algebraic type则和interface有重合 14. 为什么没有隐式类型转换作者认为这种功能带来的隐患比便利要多,Golang中Int和int64都不是一个类型,不能隐式转换。 15. Why are maps,slices,and channels references while arrays are values?知道这回事就行了slices的实现方式是对底层array的引用(见下图),参考 理解了上图再看这个例子就明白了
sa := make([]int, 10)
fmt.Println("sa:",saa)//saa: [0 0 0 0 0 0 0 0 0 0]
sb := saa[1:8]
sb[2] = 2
sb = append(sbb, 8)
//sa 也被修改了
fmt.Println("sa:",sa,"sb:",sb)// saa: [0 0 0 2 0 0 0 0 8 0] sbb: [0 0 2 0 0 0 0 8]
16. When should I use a pointer to an interfaceAlmost never.传一个指针指向interface大都数时候都是错误。另:The insight is that although a pointer to a concrete type can satisfy an interface,with one exception a pointer to an interface can never satisfy an interface. 17. 关于闭包的一个例子func main() {
done := make(chan bool)
values := []string{"a","b","c"}
for _,v := range values {
go func() {
fmt.Println(v)
done <- true
}()
}
// wait for all goroutines to complete before exiting
for _ = range values {
<-done
}
}
// 输出是c c c 因为v共用一个变量 而输出取决于fmt.Println调用的时候v存储的数值
// 正确的写法为
for _,v := range values {
go func(u string) {
fmt.Println(u)
done <- true
}(v)
}
// 或者做一个本地拷贝
for _,v := range values {
v := v // create a new 'v'. 注意位置 写在func里面还是不对
go func() {
fmt.Println(v)
done <- true
}()
}
18. 没有?:操作符差评 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |