从C++到Go(二)

从C++到Go(二)1

上一节讲完了概念差异,这节讲解语法

语法

声明语法和C++相反,类型跟在名字后面。类型的语法和变量的使用方式与C++不同。类型声明可以很容易地从左向右阅读。(var v1 int -> 变量v1是一个int

//Go                      C++
var v1 int                // int v1;
var v2 string             // const std::string v2;  (approximately)
var v3 [10]int            // int v3[10];
var v4 []int              // int* v4;  (approximately)
var v5 struct { f int }   // struct { int f; } v5;
var v6 *int               // int* v6;  (but no pointer arithmetic)
var v7 map[string]int     // unordered_map<string, int>* v7;  (approximately)
var v8 func(a int) int    // int (*v8)(int a);

声明通常采用关键字地形式,后跟要声明的对象的名称。关键字可以是var, func, const, 或 type中的一个。方法的声明是一个例外,因为方法的接收者出现在要声明的对象名称之前。

你也可以使用关键字,然后在圆括号中使用一系列声明。

var (
	i int
	m float64
)

当声明一个函数时,你必须为每个参数提供参数名或者不提供任何参数(也就是说,C++允许void f(int i, int);但是Go不允许func f(i int, int))。为了方便,在Go中你可以将具有相同类型的多个名称分组:

func f(i, j, k int, s, t string)

变量可以在声明时初始化。完成此操作后,可以指定类型但不是必须的。当没有指定类型时,变量的类型为初始化表达式的类型

var v = *p

如果一个变量没有被显式初始化,则必须指定变量的类型。此时变量将被隐式初始化为类型的0值(0, nil等)。因此在Go中没有未初始化的变量。

在函数内部,存在一个简短的声明语法:=

v1 := v2 // C++11: auto v1 = v2;

这等价于

var v1 = v2 // C++11: auto v1 = v2;

Go允许同时执行多个赋值。也就是说,首先计算右侧的所有值,然后将这些值赋值给左侧的变量。

i, j = j, i // Swap i and j.

函数可以有多个返回值,在圆括号列表中声明。返回的值可以赋值给变量的列表

func f() (i int, j int) { ... }
v1, v2 = f()

在Go中多个返回值是错误处理的主要机制

result, ok := g()
if !ok {
  // Something bad happened.
  return nil
}
// Continue as normal.

或者更简洁地说,

if result, ok := g(); !ok {
  // Something bad happened.
  return nil
}
// Continue as normal.

Go语言的代码通常不使用分号。从技术上说,所有Go语句都是由分号结束的。但是会将非空白行的末尾视为分号,除非该行为明显不完整(精确的规则被描述在语言规范中)。这么做的后果是,在某些情况下,Go不允许你使用换行符。例如,你可能想这么做

func g()
{                  // 无效
}

一个分号将被插入到g()的后面,导致了一个函数声明而不是一个函数定义。类型地,你可能想这么做

if x {
}
else {             // 无效
}

一个分号将被插入到}后面,导致了一个语法错误。

由于分号会结束语句,因此您可以像在C ++中一样继续使用它们。但是,这是不推荐的编码风格。Go语言的代码省略不必要的分号,实际上,除了for语句中的分号和在一行中需要多个简单语句时,几乎不再使用分号。

我们建议你不要关心分号和括号的位置,而是使用gofmt程序格式化代码。这个工具会产生一个唯一标准的Go语言代码风格,并且让你把注意力集中在代码而不是代码的格式上。虽然这种风格可能在刚开始看起来很奇怪,但熟悉之后会带来舒适感。

当使用指向结构体的指针时,使用.而不是->。从语法上讲,结构体和指向结构体的指针的使用方式相同。

type myStruct struct{ i int }
var v9 myStruct  // v9是一个结构体类型
var p9 *myStruct // p9是一个指向结构体的指针
f(v9.i, p9.i)

Go不需要if语句、for语句和switch语句中的圆括号。Go需要再iffor语句中使用花括号。

if a < b { f() }             // 无效
if (a < b) { f() }           // 无效
if (a < b) f()               // 无效
for i = 0; i < 10; i++ {}    // 有效
for (i = 0; i < 10; i++) {}  // 无效

Go没有while语句,因此也没有do/while语句。for语句可以等价地成为while语句。

Go允许breakcontinue指定一个标签,该标签必须引用forswitchselect语句。

switch语句中,case标签不会穿越。你可以让他们穿越通过使用fallthrough关键字。

switch i {
case 0: // 空的case
case 1:
	f() // 当i == 0时,f不会被调用!
}

一个case可以有多个值

switch i {
case 0, 1:
	f() // f is called if i == 0 || i == 1.
}

case中的值不需要为常量,任何支持相等性比较操作的类型例如字符串或指针,都可以被使用,当忽略switch的值时,默认为true(switch true)。

switch {
case i < 0:
	f1()
case i == 0:
	f2()
case i > 0:
	f3()
}

在包含defer语句的函数返回后,defer通常用来代替C ++中析构函数,但与调用代码关联,而不与任何特定的类或对象关联。

d := open("filename")
defer close(fd) // fd will be closed when this function returns.

  1. 翻译自 https://github.com/golang/go/wiki/GoForCPPProgrammers ↩︎

相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页