A Tour of Golang (一)

前端之家收集整理的这篇文章主要介绍了A Tour of Golang (一)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

从入职开始学习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:
<pre name="code" class="cpp">    <span style="font-family: Arial,sans-serif;">double a = 1.0;</span>
    <span style="font-family: Arial,sans-serif;">public:</span>
    <span style="font-family: Arial,sans-serif;">double operator ()(double x,double y) const;/</span>
};double F::operator ()(double x,double y) const{
    <span style="font-family: Arial,sans-serif;">return (x+a)*y;</span>
}int main(){
    <span style="font-family: Arial,sans-serif;">F f;</span>
    std::cout<span style="font-family: Arial,sans-serif;"><<f(1.5,2.2)<<std::endl;</span>
    <span style="font-family: Arial,sans-serif;">return 0;</span>
}
 
 
这就是一个C++中重载了()函数调用运算符的类的用法。lambda不过是一个匿名的这种类的一个对象,也算是一种语法糖。
go中的闭包也是如此(demo改了N次终于觉得符合我的想法啦!)
//golang中的闭包与匿名函数
func main() {
<pre name="code" class="cpp">    <span style="font-family: Arial,sans-serif;">var a float64 = 1.0</span>
f := func(x,y float64) float64 { return (x + a) * y } fmt.Println(f(1.5,2.2))}
 
  
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()就会使得执行错误处理的流程终止(这里不是特别明白,留待以后继续学习吧)

猜你在找的Go相关文章