从入职开始学习Go也有2周了吧,看书比较慢,加上平时使用,对于Golang只能说是有了一个初步的了解。一边翻书,一边简单的总结一点基础的东西。写着写着感觉就变成了一个C++11和Golang的比较。
1、:= 初始化
相对于C,go提供的:=可以推导表达式的类型还是很方便的,如同C11里提供的 auto 类型。
但是也有个坑在这里。:= 操作相当于生命了一个变量,不能用于给已经存在的变量进行赋值,这样会报错。而且:=不能用于声明全局变量。
2、多重赋值
多重赋值实在是方便,比如swap直接写 a, b = b, a就可以。但是因为有了多重赋值,C/C++的 , 逗号表达式被取消了。我个人觉得是因为这个原因,因为这样写就会有歧义:
a, b = 4 , c
如果有,逗号表达式, 就会有歧义:到底是多重赋值还是声明语句呢?
3、iota 与 const 枚举
- 我自己把这俩划分到一起了,因为iota实在是让我感到迷惑。。。这个iota其实跟true false 一样是go的预定义常量,只不过iota可以被编译器修改。iota我个人觉得就是一个const枚举中的行号。iota有些限制只能在 const 里面使用
- 是 const 里面的行数索引器
- 每个 const 里面,iota 都从 0 开始。
const(
A = iota
B
C
)
这个const(
)又是一个枚举一样的东西,每个变量都有一个右值,因此iota可以被用于推断行号...上例中,A是1,B是2,C是3,因为iota从0开始计算。
4、bool
bool终于不能够再被随意的赋值了。也就是说你不能让一个bool等于1或者0。这应该是一个更加严谨的决定。虽然会有一些麻烦。
5、~ 变成了 ^
golang规定,取反运算符是 ^ 。。。
6、数组 与 切片slice
数组分配后不可修改长度,这与C中的内置类型数组相似。因此也会需求类似vector的容器。好在有slice。
其实slice跟vector真的很相似。都是基于内置数组而封装出的可变数组,都有capcity和length,这种allocate之后再new的方式让人更容易控制分配效率和性能。
我不知道slice是不是如同vector,每次size==capcity之后都成倍扩大capcity。但是这个功能真的提高了很多效率,尤其再这样一个有GC的语言中,复用显得更加重要。
7、map的查找
golang的map查找非常方便,不像C++会有at函数和[]运算符的区别。
value,ok := map[key]
if ok{
//DO
}
golang中的每次map访问都会返回2个值,一个是key对应的value,另一个是是否含有这个key对应的value,因此避免了复杂的判断步骤。
8、匿名函数 与 函数闭包
想了很久决定把这两个特性放在一个题目下
C11中引入了匿名函数lambda,使用[]捕获列表的方式获得上下文环境,其实就是创建了一个重载了()的匿名的可调用类,lambda就是这样一个类的一个实例。然后又说到了闭包,c11中的lambda其实也算是一种闭包吧我觉得,有人曾经给我类比函数指针来讲解闭包我觉得这是个错误的例子
//C++:举例子,写了一个重载了()的类class F
class F
{
private:
double a = 1.0;
public:
double operator ()(double x, double y) const;
};
F::operator ()(double x, double y) const{return (x+a)*y;}
int main(){
F f;
std::cout<<f(1.5, 2.2)<<std::endl;
return 0
}
这就是一个C++中重载了()函数调用运算符的类的用法。lambda不过是一个匿名的这种类的一个对象,也算是一种语法糖。
go中的闭包也是如此(demo改了N次终于觉得符合我的想法啦!)
//golang中的闭包与匿名函数
func main() {
var a float64 = 1.0
f := func(x, y float64) func()float64 {return func(){(x + a) *y }
} (1.5, 2.2)
fmt.Println(f())
}
go闭包相当于把 var a和一个匿名函数封装到了一起,声明并调用匿名函数,返回一个接受2参数的匿名函数对象(实在找不到形容的方法,函数对象这个东西算是C++特有?)
再来对比一下C++中的lambda
//C++中的lambda
int main() {
double a = 1.0;
auto f = [&a](double x, double y) ->return double { return (x + a) * y };
std::cout << f(1.5, 2.2) << std::endl;
}
区别并不大,我也是做一个比较,如果不知这样也希望指教。打心里说,我更喜欢C++的lambda一点。
9、panic() recover() 与 defer
把这三个放在一起也是没想好能不能这么总结
defer表示默认执行的,相当于在析构函数中的语句。panic()和defer配合使用,调用panic之后就会执行defer中的语句,defer中遇到recover()就会使得执行错误处理的流程终止(这里不是特别明白,留待以后继续学习吧)