Go语言入门指南:从C++到Go | 青训营

208 阅读5分钟

Go语言入门指南:从C++到Go

欢迎来到Go语言入门指南!如果你已经熟悉C++,你会发现Go在很多地方都很直观,但同时它也带来了一些新颖和独特的特性。以下是为C++程序员编写的Go基础指南。

1. 基础

1.1 Hello, World!

像大多数编程语言一样,我们从简单的“Hello, World!”开始。Go程序始于一个main函数,fmt.Println是用于打印的基本函数。

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

此代码定义了一个简单的Go程序,它打印出"Hello, World!"。所有的Go程序都从main函数开始执行。

1.2 变量声明

在Go中,变量可以使用var关键字声明,但更常见的做法是使用“:=”进行简短声明和初始化。这让代码更简洁,更易于阅读。

var i int = 10
j := 20

上面的代码首先使用var关键字声明了一个整数变量i并初始化为10。接下来,它使用简短声明方式声明并初始化了变量j为20。

1.3 数据类型

Go有多种基本数据类型,与C++类似,但提供了更多的位宽类型选择。例如,你可以选择明确的int32或int64,取决于你的需求。

1.4 数组和切片

数组在Go中是值类型,并且其大小固定。而切片是对数组的引用,可以动态增长。切片在很多情况下都更有用,因为它们是动态大小的。

var arr [5]int            // 声明一个整数类型的数组,长度为5
s := []int{1, 2, 3, 4, 5} // 声明一个整数类型的切片

此代码首先声明了一个长度为5的整数数组arr。然后,它定义了一个整数类型的切片s并进行了初始化。

2. 控制结构

2.1 If条件语句

Go的if语句允许声明一个在条件作用域内的变量。这可以简化代码,同时确保变量的作用域被限制。

if i := 10; i < 20 {
    fmt.Println("i is less than 20")
} else {
    fmt.Println("i is greater than or equal to 20")
}

此代码在if语句中声明了一个变量i并初始化为10,接着它检查i是否小于20,并根据条件打印相应的消息。

2.2 循环

Go中并没有C++中的多种循环结构。只有for循环,它可以像C++的forwhiledo-while一样使用。

for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// 使用range遍历数组或切片
for index, value := range s {
    fmt.Println(index, value)
}

第一段代码使用for循环打印数字0到9。第二段代码使用range关键字遍历切片s,并打印每个元素的索引和值。

3. 函数

在Go中,函数定义简洁明了,返回类型位于函数名之后。

func add(a int, b int) int {
    return a + b
}

此函数接受两个整数参数ab,并返回它们的和。

3.1 多返回值

。Go语言有一个独特的功能,那就是函数可以返回多个值。这种能力在许多场景中都非常有用,特别是在错误处理上。在许多Go库和应用程序中,当一个函数可能出错时,它会返回一个结果和一个错误。这种模式可以让你轻易地处理错误,而不用依赖例如全局的错误状态或异常。

让我们考虑一个函数,它的任务是读取一个文件并返回其内容。在读取文件时可能会发生多种错误,如文件不存在、权限问题等。使用Go的多返回值功能,我们可以同时返回文件的内容和一个可能的错误。

func readFile(filename string) (string, error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return "", err
    }
    return string(data), nil
}

这种模式让错误处理变得简单直接。你总是知道在哪里检查错误,并且你的代码不会因为未处理的错误而继续执行。

4. 结构体与接口

4.1 结构体

结构体是Go中定义新类型的方式。它可以包含多个字段,并支持方法。

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "John", Age: 25}

这段代码定义了一个Person结构体,并创建了一个Person类型的变量p,其中Name字段为"John",Age字段为25。

4.2 接口

接口定义了一组方法,但不实现它们。任何实现了接口方法的类型都被认为实现了该接口。

type Shape interface {
    Area() float64
}

这是一个简单的接口定义,任何类型只要实现了Area方法(返回一个float64)就被认为实现了Shape接口。

5. Goroutines 和 Channels

Go的一大特点是其并发模型。Goroutines类似于轻量级线程,但与C++的线程管理相比,资源开销更小。

5.1 Goroutines

通过在函数前加go关键字,你可以轻易地启动一个goroutine。这与C++中创建线程的过程相比要简单得多。

func sayHello() {
    fmt.Println("Hello!")
}

go sayHello() // 使用go关键字来启动goroutine

此代码定义了一个简单的函数sayHello,并使用go关键字以goroutine的方式异步调用它。

5.2 Channels

Channels是Go中goroutines之间进行通信的主要方式。它们提供了一种在goroutines之间发送和接收值

的方法,确保并发安全。

ch := make(chan int)
go func() {
    ch <- 1  // 发送数据到channel
}()
value := <-ch  // 从channel接收数据

这段代码首先创建了一个整数类型的channel。接下来,它启动了一个goroutine来发送数字1到channel。在主goroutine中,它等待并从channel接收这个值。

结论

从C++迁移到Go,你会发现很多熟悉的元素,但也有许多新的和有趣的特性。Go为并发和并行编程提供了一种新的,简洁的方式。希望这篇指南能够帮助你入门Go!