青训营第一课 | Go 语言入门

71 阅读3分钟

Go 相比 Java 的优势

  • 简洁性:Go 语言的语法简洁,代码量少,易于维护。
  • 并发性:原生支持 goroutine 和 channel,便于实现并发编程。
  • 高效性:Go 编译速度快,运行性能接近 C++。
  • 内存管理:内置垃圾回收机制,减少了手动内存管理的复杂性。

类型声明

  • 使用 var 声明类型,例如 var e float64
  • 使用 := 自动推导类型,例如 f := float32(e)
  • const 常量声明时会自动确定类型

为什么要类型后置

Go 采用类型后置,使代码更接近自然语言阅读顺序,有助于理解函数签名和变量声明的含义。

在《Go's Declaration Syntax》里,Rob Pike 解释了为什么 Go 语言的声明语法采用类型后置的设计,而非像 C 语言那样的类型前置语法。这个设计不仅让 Go 的语法更加直观,而且在处理复杂类型声明时具有明显优势。

C 语言的声明方式

在 C 中,声明语法通过模拟表达式来描述类型。这种方法对简单的类型有效,但对于复杂的类型,特别是指向函数的指针,阅读起来会变得非常困难。

例如,在 C 中定义一个指向函数的指针,我们会写成:

int (*fp)(int a, int b);

上面的声明表示 fp 是一个指向返回 int 类型、接受两个 int 参数的函数的指针。这个声明规则要求开发者从内向外阅读类型,这会使得复杂的类型声明变得不直观,特别是当返回值或参数中包含其他函数指针时。例如:

int (*(*fp)(int (*)(int, int), int))(int, int);

这样的声明非常复杂且难以阅读,令人难以直接理解 fp 的类型。

Go 语言的声明方式

使用 Go 的语法,前面的 C 例子可以更清晰地表达为:

var fp func(func(int, int) int, int) func(int, int) int

在 Go 中,我们可以直接从左到右阅读,理解 fp 的类型:fp 是一个函数,它接受一个返回 int 类型的函数(参数是两个 int),以及另一个 int 作为参数,返回的也是一个接受两个 int 并返回 int 的函数。通过这种语法,代码的意图变得更加清晰,阅读更加流畅。

控制语句

  • if-else 支持简洁的赋值和条件判断,例如 if num := 9; num < 0
  • for 循环for {} 表示死循环,Go 没有 while,用 for 来代替。
  • 函数返回值:Go 函数可以返回两个值,第一个是正常的返回值,第二个是错误值。
  • switch-case
    • switch 语句不需要加括号。
    • 每个 case 分支不需要 break,默认自动终止。
    • 推荐使用 switch-case 替代多个 if-else
    • 支持多种类型,包括结构体等。

结构体创建

  • 使用 typestruct 关键字定义结构体,例如:
    type Person struct {
        Name string
        Age  int
    }
    
  • 创建实例时可以使用字段名初始化:
    p := Person{Name: "Alice", Age: 30}
    

字符串操作

  • 使用 strings 包进行字符串操作,例如 strings.Contains() 检查字符串是否包含子串。
  • 使用 %v 格式化输出任意结构体,用 %+v 输出字段名,用 %#v 输出详细内容。

JSON 操作

  • 导入 "encoding/json" 包进行 JSON 序列化和反序列化。
  • 序列化:buf = json.Marshal(a)a 是结构体。buf 需要强制转换成 string 才能打印。
  • 反序列化:json.Unmarshal(buf, &b)b 是结构体的指针。

数字解析

  • 使用 strconv 包处理字符串到数字的转换:
    • strconv.ParseInt(字符串, 进制(整数), 位数(64/32))
    • strconv.ParseFloat(字符串, 精度(64/32))