golang与c++区别

 

前述

从c++转到golang, 有很多不习惯和新颖的地方。偶然看到一篇文章《如何避免动态语言思维写go》, 虽然写的比较粗略, 但还是提醒了我, 转语言需要去进行比较、转换编码思维。

参考

语法区别

基础

c++:

int a = 1;
void Func(string a) {
    if (a == "a") {

    }
    switch(1) {
        case 1:
            break;
        defualt:
            break;
    }
    return a == "b" ? a : "c";
}

// 对于多返回结果
struct DoubleResult {
    int result;
    int error;
};
DoubleResult DoubleResultFunc(string a) {
    DoubleResult res;
    return res;
}

/* 或者 返回代表errcode, 其余的返回包用引用或指针作为入参  这也是最常见的写法 在go中被认为是坏习惯
int DoubleResultFunc(string a, int& result) {
    result = 1;
    return 0;
}
*/

go:

var a int = 1 // 或 a := 1
func Func(a string) {
    // 不需要括号
    if a == "a" {

    }
    // go的switch-case不需要break, 需要break的话是其他场景
    switch a {
        case "aa":
        case "bb":
        deautlt:
            a = "aa"
    }
    // go中没有三目运算符
    if a == "b" {
        return a
    } else {
        return "c"
    }
}

// 对于多返回结果 天然支持
func DoubleResultFunc(a string) int, error {
    return 1, nil
}

计算

var a, b int
// go的交换数值可以这么写!
a, b = b, a

位运算

// c++取反
a = ~a
// go取反
a = ^a

继承/接口

c++:

class Base {
    virtual void TestInheritance() {}
};

class Test : public Base  {
    void TestInheritance() override {}
};

go:

type Base Interface {
    TestInheritance() error
}

type Test struct {}

// go没有类似继承的语法 接口随拿随用; 实现了interface里的所有函数则可(类似c++继承子类的用法)
func (c *Test)TestInheritance() error {

}

重载

go不支持函数重载和运算符重载!

官方观点为: 函数/运算符同名参数不同名, 只是偶尔有用, 但会导致脆弱性, 会使人混淆。 go为了保持简洁和简单, 不新增这个特性。

个人不敢苟同…感觉不支持重载各有优有劣吧

方法

type ByteSlice []byte
// method的接受体不一定非是结构体, 例中的byte slice也可
func (p *ByteSlice) Append(data []byte) {
    // ...
}

宏观区别

  1. 代码风格区别
    • c++ google-style建议尽量使用下划线来定义变量名; 局部变量名称尽量长/有意义
    • go uber-style建议使用驼峰式命名变量; 局部变量名称越短越好(例如lineCount写为c, sliceIndex写为i), 有特殊意义除外

      the further from its declaration that a name is used, the more descriptive the name must be

  2. 在变量/函数命名方面, golang有严格要求: 小写字母开头的变量或函数, 在包外是不可见的

  3. 空指针的异同
    • c++中的nullptr, 空指针, 通常是未赋值, 无法使用对应结构的功能
    • go中的map, slice, chan, pointer在未初始化时为nil, 代表的是零值(并不是空), 说明声明了变量但是还没赋值
  4. 错误处理
    • c++通常习惯用错误码作为返回值(由 0和非0 或者 正数负数 来判断执行的正常与否), 其他的信息则在函数入参时作为引用/指针传递进来
    • go中由于支持多返回, 通常error是作为返回的内容之一, 不会去考虑错误码
  5. 代码空间
    • 个人感觉相较于c++的namespace, go的package限制作用是更强的
    • 但是go的package又支持重命名, 所以一定程度上又比c++的namespace灵活

go的一些便捷之处

  1. go fmt一键帮你解决格式问题
  2. 很方便地原生支持了UnitTest