Go 语言入门指南:基础语法和常用特性解析|青训营

132 阅读8分钟
Go语言是一种开源的编程语言,以其简洁、高效和并发特性而闻名,作为一个小白,如何从已知的语言出发去了解GO,并在此过程中体会GO语言的特点是我认为比较好的初学方式。笔记中,我将主要根据所学的多种(C/JAVA/Python)编程语言去了解GO语言。

(一)GO语言与C、Java、Python在基础语法上的异同

(1)定义变量
  • C语言
int ages = 20;
char str[] = "Hello, World!";
  • Java语言
int age = 20;
String str = "Hello, World!";
  • python语言
age = 20     #当输入;将被自动忽略,如果编译器有代码规范的话,会标黄
str = "Hello, World!"

-GO语言

age := 20    //相对C/Java更加简洁
str := "Hello, World!"

其中GO语言的Hello, World!编码如下:

package main

import "fmt"

func main() {
    str := "Hello, World!"
    fmt.Println(str)
}
(2)条件语句
  • C语言
if (age >= 18) {
    printf("成年人");
} else {
    printf("未成年人");
}
  • Java语言
if (age >= 18) {
    System.out.println("成年人");    
} else {
    System.out.println("未成年人");
}
  • python语言
if age >= 18:
    print("成年人")
else:
    print("未成年人")

-GO语言

if age >= 18 {
    fmt.Println("成年人")   
} else {
    fmt.Println("未成年人")
}

可以看出GO语言在条件语句上的if-else输出形式上并无太多不同,但是值得注意的是在GO语言中,switch语句有些许不同,如下:

package main

import "fmt"

func main() {
    num := 2

    switch num {
    case 1:
        fmt.Println("Num is equal to 1")
    case 2:
        fmt.Println("Num is equal to 2")
    case 3:
        fmt.Println("Num is equal to 3")
    default:
        fmt.Println("Num is not 1, 2, or 3")
    }
}

注意以下几点:

  • 每个case后面不需要使用break语句来结束,Go语言中的switch语句默认会自动退出。
  • case后面的表达式必须是一个常量值(比如整数、字符、字符串),而不是一个变量。
  • default块是可选的,用于处理除了case块之外的其他情况。

当然这只是switch语句的基本用法,还可以使用switch语句进行更复杂的判断,比如使用表达式或类型断言作为判断条件,以及使用fallthrough关键字来实现穿透效果。根据具体的需求,可以灵活运用switch语句来处理不同的情况。

(3)循环语句
  • C语言:
    for (int i = 0; i < 5; i++) {
        printf("%d ", i);
    }
    
  • Java语言:
    for (int i = 0; i < 5; i++) {
        System.out.print(i + " ");
    }
    
  • Python语言:
    for i in range(5):
        print(i, end=" ")
    
  • Go语言:
    for i := 0; i < 5; i++ {
        fmt.Printf("%d ", i)
    }
    
    值得一提的是,Go语言中只有一种循环结构,即for循环,而其他三种语言具有多种循环结构(如C语言的forwhiledo-while,Java语言的forwhiledo-while,Python语言的forwhile)。 而且在循环条件表达式上Go语言的for循环的条件部分不需要使用括号,而其他三种语言通常需要使用括号将条件表达式包裹起来。在C语言和Java语言中,循环变量的作用域限制在循环语句块内部;而在Go语言和Python语言中,循环变量的作用域扩展到整个循环体外部。
(4)数组
  • C语言:
    int arr1[5];         // 声明一个大小为5的整数数组 
    char arr2[] = {'a', 'b', 'c'};      // 声明并初始化一个含有3个字符的数组
    
  • Java语言:
    int[] arr1 = new int[5];                 // 声明一个大小为5的整数数组
    String[] arr2 = {"a", "b", "c"};         // 声明并初始化一个含有3个字符串的数组
    
  • Python语言:
    arr1 = [0] * 5             # 声明一个大小为5的整数数组,并初始化为0 
    arr2 = ["a", "b", "c"]         # 声明并初始化一个含有3个字符串的数组
    
  • Go语言:
    var arr1 [5]int             // 声明一个大小为5的整数数组 
    arr2 := [3]string{"a", "b", "c"}     // 声明并初始化一个含有3个字符串的数组
    

需要注意的以下几点:

  1. 数组长度:Go语言中声明数组时,必须显式指定数组的长度,而其他三种语言中可以动态初始化数组或使用动态数组。
  2. 数组切片:Go语言引入了数组切片(slice)的概念,使得对数组的操作更加灵活。C语言、Java语言和Python语言没有直接对应的数组切片概念,需要使用其他数据结构来实现类似的功能。数组切片是一个引用类型,可以动态调整大小,并支持类似于动态数组的功能。
  • GO语言示例:

    arr := []int{1, 2, 3, 4, 5}    // 声明并初始化一个数组切片
    arr = append(arr, 6)           // 在数组切片末尾添加元素
    
  1. 数组传递方式:在函数调用中,Go语言中数组作为参数传递给函数时是按值传递的,而其他三种语言中数组作为参数传递时通常是按引用传递的.
  • Go语言:
     func modifyArray(arr [5]int) {
        arr[0] = 100
        }
     arr := [5]int{1, 2, 3, 4, 5}
     modifyArray(arr)
     fmt.Println(arr)    // 输出 [1 2 3 4 5]
    
  • Python语言:
    def modify_array(arr):
    arr[0] = 100
    arr = [1, 2, 3, 4, 5]
    modify_array(arr)
    print(arr[0])    # 输出 100
    
(5)函数定义
  • C语言:
    int add(int a, int b) {
        return a + b;
    }
    
  • Java语言:
    public int add(int a, int b) {
        return a + b;
    }
    
  • Python语言:
    def add(a, b):
        return a + b
    
  • Go语言:
    func add(a, b int) int {
        return a + b
    

需要注意的是:

1. Go语言中的函数参数传递方式与其他三种语言略有不同。

  • Go语言中的函数参数传递方式既可以是值传递,也可以是引用传递。当参数是基本类型时,采用值传递;当参数是引用类型(如指针、数组、切片、映射、通道)时,采用引用传递。
  • C语言中的函数参数传递方式是按值传递,即传递参数的副本给函数。
  • Java语言中的函数参数传递方式也是按值传递,但对于对象类型的参数,实际上是传递了对象的引用。
  • Python语言中的函数参数传递方式是按对象引用传递。

2. Go语言与其他三种语言在返回值方面也存在一些区别。

  • Go语言可以返回多个值,而其他三种语言通常只能返回一个值。这使得Go语言在一些情况下更加方便和灵活。
  • C语言中可以通过指针参数来实现函数返回多个值的效果。
  • Java语言和Python语言可以使用类或者对象封装多个返回值。

3. Go语言对于错误处理有着独特的设计。

  • Go语言使用函数的多返回值机制来处理错误。通常,一个函数在遇到错误时会返回一个错误对象,调用者可以根据返回的错误对象来判断和处理错误。
  • C语言通常使用函数的返回值来表示错误码,或者通过指针参数返回错误码。
  • Java语言使用异常机制来处理错误,异常可以被捕获和处理,或者继续抛出。
  • Python语言也使用异常机制来处理错误,异常可以被捕获和处理,或者继续抛出。

(二)GO语言常用特性解析

1. 包管理:

  • Go使用包(package)来组织和管理代码。每个Go程序都必须有一个main包,并在其中的main函数作为程序的入口点。

2. 变量和类型:

  • 声明变量时,需要指定变量名和类型。Go具有基本类型(如整数、浮点数、布尔值)和复合类型(如数组、切片、映射)。 - 可以使用var关键字声明变量,也可以使用短变量声明(:=)进行快速声明并初始化变量。

3. 控制结构:

  • Go支持常见的控制结构,包括条件语句(if/else)、循环语句(for)、选择语句(switch)和错误处理(defer/panic/recover)。

4. 函数和方法:

  • 可以使用func关键字定义函数。函数可以有多个参数和返回值。
  • Go还支持面向对象编程范式,它提供了方法(method)的概念。方法是与特定类型关联的函数。

5. 并发和并行:

  • Go内置了原生的并发支持,使用go关键字可以创建并发执行的goroutine。可以使用通道(channel)在goroutine之间进行通信和同步。
  • 此外,Go还提供了sync包,用于更复杂的并发模式,如互斥锁和条件变量。

6. 错误处理:

  • Go鼓励显式处理错误,以避免悬挂的goroutine和未处理的异常。常见的做法是使用多返回值,其中一个返回值是错误类型。

7. 运行时反射:

  • Go提供了反射机制,使程序能够检查和修改变量的类型和值。这对于编写通用代码和处理未知类型非常有用。

8. 包和依赖管理:

  • Go使用go mod命令来管理包和依赖项。可以使用go get命令下载和安装外部包,使用import关键字引入包。

本人对GO语言的了解还不够,编写过程可能存在错误,希望各位批评指正。