简单对比一下 C 与 Go 两种语言

简单,对比,一下,go,两种,语言 · 浏览次数 : 963

小编点评

**C 语言与 Go 语言的比较** **C 语言** * for 循环:使用 `for` 关键字实现对一组值的迭代访问。 * 变量声明和赋值:需要通过 `int count = 1; count <= 10; count++` 等方式进行。 * 标准库函数 `printf()` 用于打印变量值。 **Go 语言** * for 循环:使用 `for` 关键字实现对一组值的迭代访问。 * 语法类似于 C 语言,但 `for` 循环的初始条件可以包含表达式。 * 变量声明和赋值:可以使用 `var count int for count := 1; count <= 10; count++ { ... }` 等方式进行。 * 标准库函数 `fmt.Println()` 用于打印变量值。 **结果** | 字段 | C 语言 | Go 语言 | |---|---|---| | for 循环 | `for (int count = 1; count <= 10; count ++) { ... }` | `for count := 1; count <= 10; count++ { ... }` | | 变量声明 | `int count = 1; count <= 10; count ++` | `var count int for count := 1; count <= 10; count++ { ... }` | | `printf()` | `printf("\"%d\\", count);` | `fmt.Printf("sum is %d\\", sum);` | **结论** C 语言和 Go 语言在语法上相似,但 `for` 循环的初始条件可以包含表达式,Go 语言允许使用 `for` 循环的初始条件。在其他方面,它们的行为基本相同。

正文

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/U6jIT837x5Yxe6Ev1aMDsA

使用一个简单的计数程序将古老的 C 语言与现代 Go 进行比较。

Go 是一种现代编程语言,追溯其历史大部分源自编程语言 C。所以,任何熟悉 C 语言的开发者都可能会觉得 Go 很熟悉。C 程序员使用 Go 编写新程序变得容易,同时避免了 C 编程语言的许多常见缺陷。

下面通过实现一个简单的加法逻辑,来比较 C 和 GO 的区别。该程序将数字从一加到十,计算过程和结果数值都比较小,所以代码仅使用普通整数变量。像这样的循环逻辑在编程中很常见,所以对比效果会显而易见。

C 语言做循环

C 语言中的基本循环是 for 循环,它可以实现对一组值的迭代访问。

for 基本语法:

for (初始化条件; 判断条件为真; 每次循环之后的操作) {
  // do something;
}

比如,可以编写一个循环,初始化条件时设置变量 count 为 1,然后判断 count <= 10 为真时执行 {} 内的语句,在再次执行条件判断之前,对变量 count 增加 1。直到判断 count <= 10 为假就退出循环。

在每次迭代后,对变量 count 增加 1,除了常规的 count = count + 1 书写格式之外,也可以对变量采用 ++ 的自加操作符,这种变通可以使得代码更简洁易读。

在循环内部,为了直观查看变量的变化过程,可以使用标准库函数 printf 打印变量 count 的值:

for (int count = 1; count <= 10; count ++) {
  printf("%d\n", count);
}

为了演示完整的逻辑,下面是一个示例程序,将数字从 1 加到 10,然后打印和的结果。

#include <stdio.h>
int main()
{
  puts("adding 1 to 10 ..");
  int sum = 0;
  for (int count = 1; count <= 10; count ++) {
    sum += count;
  }
  
  printf("sum is %d\n", sum);
  return 0;
}

上面的代码使用了两种函数把信息打印出来,最终输出到标准输出 stdout。puts 函数打印一个字符串,直到遇到字符串的空字符,而 printf 函数支持格式化打印,非常灵活,所以更常用。关键字 %d 表示打印一个十进制(或整数)值,\n 表示换行符。

如果编译并运行该程序,你将看到以下输出:

adding 1 to 10 ..
sum is 55

GO 语言做循环

在 GO 语言中,同样提供了 for 循环,而且与 C 语言中的 for 循环语法非常相似,甚至可以直接转换成 GO 的书写格式。

下面为了直观查看变量的变化过程,在循环内部同样使用方法打印变量 count 的值:

var count int
for count = 1; count <= 10; count ++ {
  fmt.Printf("%d\n", count)
}

fmt 是包名,使用包之前需要先导入,用关键词 import。C 语言中就没有导入包的概念,只能通过包含头文件 .h 来引入其它现成模块。

fmt 实现了类似 C 语言的打印输出 printf 和读取输入 scanf。fmt.Printf 方法也是支持格式化输出的,甚至格式变量就是从 C 语言的 printf 派生而来。

在 C/C ++ 代码中,比较推荐的编码规范中通常每行是只写一句操作语句,虽然语法上多个操作语句是允许书写在同一行的,但这样易读性就很差。有没有发现,在每行 GO 语句的末尾都没有分号 ';' 了? 因为 GO 编译器默认每行就是一个语句,这样其实是强制提高了代码的可读性。

再来看看 GO 语言实现的完整逻辑,基于上面的 C 语言代码版本直接翻译如下

package main
import "fmt"

func main() {
  var sum, count int
  fmt.Println("adding 1 to 10 ..")

  for count = 1; count <= 10; count ++ {
    sum = sum + count
  }
  fmt.Printf("sum is %d\n", sum)
}

上面的代码是有效和可以正确运行输出的,但是这很不 GO ! GO 不单单是一门语言,也是一种态度。

有没有看到 C 语言版本中, for 循环里的初始化条件是可以同时声明定义并赋值变量的?换成在 GO 中是否也支持类似操作?

在 GO 中,有个声明变量并赋值的操作符 :=,就可以做到

for count := 1; count <= 10; count ++ {
  sum = sum + count
}

另外,你如果再细心一点可能会发现,GO 代码里声明定义的变量会被默认初始化为 0,而 C 代码中定义的变量如果未经初始化会是任何未知的值,如此看来 GO 的安全性有了很大的提高。

变量的生命周期管理对开发者来说是很耗费心智的,所以很多时候变量的声明定义都是应该尽量靠近使用的地方,并且缩窄变量的生命周期,对于事故的发生可以有效缩小排查错误的范围,简直就是在打救程序员的生命啊。

再来看看,优化后的 GO 范式代码

package main
import "fmt"

func main() {
  fmt.Println("adding 1 to 10 ..")
  var sum int
  for count := 1; count <= 10; count++ {
    sum += count
  }

  fmt.Printf("sum is %d\n", sum)
}

看到这里,和 C 代码的 main 函数比起来,GO 的 main 函数没有显式的返回值。实际上,GO 的 main 函数默认返回值 0,如果需要返回其它值,可以调用 os.Exit(n) 返回值 n,这个方法可在任何位置调用,程序会在调用该方法后会终止运行并退出,就类似 C 语言中的标准库函数 exit(n) 一样。

简单回顾

从上面的逻辑实现过程来看,两种语言实现过程差别不大,语法上是有差别的,书写的习惯其实就透露着各自的态度。

虽然老气横秋的 C 语言代码很多,但是如果按照现代 C 语言书写规范来看,GO 的代码是何其相似。

虽然你会说新出来的语言有很多方便到爆炸的语法糖。但问题是,语言的精髓是语法糖吗?答案不唯一,酸甜苦辣唯有尝过的人才知道。

与简单对比一下 C 与 Go 两种语言相似的内容:

简单对比一下 C 与 Go 两种语言

使用一个简单的计数程序将古老的 C 语言与现代 Go 进行比较。

Nginx与Tomcat作为前端服务器的性能比较

Nginx与Tomcat作为前端服务器的性能比较 摘要 最近总遇到使用tomcat还是使用nginx进行前端文件访问的争论 想着出差周末在酒店, 可以自己进行一下简单的测试. 希望能够对未来的工作进行一些指导. 测试脚本 30KB 文件测试 ab -c 1000 -n 50000 -k http:/

C#.Net筑基-基础知识

C# (读作C Sharp)是由微软公司开发的一种面向对象、类型安全、高效且简单的编程语言,最初于 2000 年发布,并随后成为 .NET 框架的一部分。所以学习C#语言的同时,也是需要同步学习.NET框架的,不过要要注意C#与.NET的对应版本。

.NET科普:.NET简史、.NET Standard以及C#和.NET Framework之间的关系

最近在不少自媒体上看到有关.NET与C#的资讯与评价,感觉大家对.NET与C#还是不太了解,尤其是对2016年6月发布的跨平台.NET Core 1.0,更是知之甚少。在考虑一番之后,还是决定写点东西总结一下,也回顾一下.NET的发展历史。 首先,你没看错,.NET是跨平台的,可以在Windows、

Builder 生成器模式简介与 C# 示例【创建型2】【设计模式来了_2】

在构造一个复杂的对象(参数多且有可空类型)时,通过一个统一的构造链路,可选择的配置所需属性值,灵活实现可复用的构造过程。

Abstract Factory 抽象工厂模式简介与 C# 示例【创建型1】【设计模式来了_1】

通过对抽象类和抽象工厂的一组实现,独立出一系列新的操作,客户端无需了解其逻辑直接访问。

Composite 组合模式简介与 C# 示例【结构型3】【设计模式来了_8】

〇、简介 1、什么是组合设计模式? 一句话解释: 针对树形结构的任意节点,都实现了同一接口,他们具有相同的操作,可以通过某一操作来遍历全部节点。 组合模式通过使用树形结构来组合对象,用来表示部分以及整体层次。组合模式属于结构型模式,多用于递归。 官方意图描述:将对象组合成树形结构,以表示“部分-整体

Bridge 桥接模式简介与 C# 示例【结构型2】【设计模式来了_7】

〇、简介 1、什么是桥接模式? 一句话解释: 通过一个类的抽象,与另一个类的抽象关联起来,当做桥。此后不管两个抽象类的实现有多少种,均可以通过这个桥来将两个对象联系起来。 桥接,顾名思义就是用桥来连接河两岸,将原本不关联的两部分联系起来,且不影响两岸的各自演化,演化出来的不同对象仍可以通过这个桥连接

C/S UDP通信实践踩坑记录与对于ICMP的进一步认识

背景 最近有个业务场景需要服务端(简称S)与客户端(简称C)设计一套基于UDP的通信协议--要求尽可能快的前提下可容忍一定丢包率,得以比较深入地学习和了解UDP通信和实践,在开发调试期间先后碰到了C端UDP发包无响应、响应Host Unreachable、响应Port Unreachable、再次C

阶段总结与展望——我的简历

我是一位刚进大二的大学生,在大数据这个专业已经学习了一年多了。 目前,对c++、python、java等编程语言有所了解,能够编写出一些基本的程序,当前接触了Linux操作系统、爬虫操作、Web前端、数据库,有一定的编写程序能力;在校期间获得了“python程序设计一等奖”。 在这门课程结束后,你将