Go语言编程笔记2:基础

Go语言编程笔记2:基础

Go语言编程笔记2:基础_第1张图片

图源:php.cn

语言风格

Go语言是从C语言衍生而来,所以语言风格上是和C语言很相似的,不同的是Go在语言格式化上做的相当激进。

最显著的是在缩进和换行上,Go语言都有严格要求。此外在变量使用和包导入上,同样非常严格。

在Python中,如果引用了没有使用的包或者是有变量没有使用,是不会影响到程序的执行的,比如:

from typing import NamedTuple

message = 'How are you!'
print('hello world')

# hello world

其中的包NamedTuple和变量message都是不必要的,但这些都不会阻止程序的正常执行。当然可能会造成性能浪费,优秀的IDE也会通过颜色高亮来提醒你这些是可以删除的部分。但无论怎么说,大多数编程语言(如C++/Java/PHP等)都不会强制要求开发者剔除不必要的引用或者变量,但Go语言会:

package main

import "fmt"

func main() {
	message := "How are you!"
	fmt.Printf("Hello World")
}

// Build Error: go build -o C:\Users\70748\AppData\Local\Temp\__debug_bin2433955485.exe -gcflags all=-N -l .\hello.go
// # command-line-arguments
// .\hello.go:6:2: message declared but not used (exit status 2)

这里message变量虽然声明并初始化,但在后续程序中并没有真正使用,所以是无效的代码,这里直接会被编译器提示message declared but not used进而中断编译过程。事实上无效的导入也会造成同样的后果。

不过导入方面的问题不需要开发者操心,Go提供官方自动导入工具,VSC之类的IDE会自动调用该工具导入需要的包或者删除不必要的包。

在这方面Go语言是相当极端的,这样做优点和缺点同样明显。

优点是保证代码的干净高效,剔除不必要的无效代码,且可以在编译阶段发现一些不必要的bug,同时保持一致性的代码风格,让Go语言源码都具有很高的可读性。缺点是扼杀了代码的个性,可能一部分程序员初次接触后会相当的不习惯。

变量

Go语言脱胎于C,且因为同样是静态的强类型语言,所以变量声明风格是极为类似的:

package main

import "fmt"

func main() {
	var a int = 1
	var b int = 2
	var c int = a + b
	fmt.Println("the result is:", c)
}

// the result is: 3

当然我个人认为是不如int a = 1这样的方式简洁的。不过在形式上倒是颇类似使用注解后的Python:

a: int = 1
b: int = 2
c: int = a+b
print("the result is :", c)
# the result is : 3

除了上面的方式之外,Go语言还支持一种简短写法:

package main

import "fmt"

func main() {
	a := 1
	b := 2
	c := a + b
	fmt.Println("the result is:", c)
}

// the result is: 3

通过使用:=操作符,可以在声明并初始化变量的时候,根据初始化的值的类型来自动推断出变量的类型,并将变量声明为相应类型后初始化。所以a := 1var a int = 1是等效的。

有趣的是:=在Python中是赋值表达式使用的符号,还有个很别致的名称叫做“海象操作符”,但用法有所不同,因为Python并不存在所谓的类型推断,因为类型推断存在于Python本身的机制中,是Python的一部分,是对开发者不可见的。

除了上边通常的对变量“声明并初始化”的做法之外,变量是可以单独声明的并且不进行显式地初始化的,这样做并不会有C或C++中的“脏数据”的风险,因为和其它诸如Java之类的现代语言类似,Go语言会在变量声明的同时进行隐式初始化:

package main

import "fmt"

func main() {
	var integer int
	var text string
	fmt.Println("integer is ", integer)
	fmt.Println("text is ", text)
}

// integer is  0
// text is

在这个例子中int类型的变量integer被初始化为0,字符串类型的变量text被初始化为空字符串。此外bool类型的变量会被初始化为False

函数

在Go语言中定义函数和在Python中定义虽然不能说一模一样,但也可以说是极为相似了:

package main

import "fmt"

func main() {
	a := 1
	b := 10
	result := add(a, b)
	fmt.Println("result is :", result)
}

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

// result is : 11

Python中:

def add(a: int, b: int) -> int:
    return a+b


a: int = 1
b: int = 2
c: int = add(a, b)
print("the result is :", c)
# the result is : 3

不同的是,Go语言有个可以说是“堵门绝技”一般的函数功能:多返回值。

一般来说,函数都只能返回一个返回值,如果需要返回多个数据,都是用对象或者一些内建容器作为返回值来完成。但Go语言可以直接返回多个返回值:

package main

import "fmt"

func main() {
	a := 10
	b := 2
	add_result, sub_result, mul_result, div_result := four_fundamental(a, b)
	fmt.Println("add_result is :", add_result)
	fmt.Println("sub_result is :", sub_result)
	fmt.Println("mul_result is :", mul_result)
	fmt.Println("div_result is :", div_result)
}

func four_fundamental(a int, b int) (int, int, int, int) {
	return a + b, a - b, a * b, a / b
}

// add_result is : 12
// sub_result is : 8
// mul_result is : 20
// div_result is : 5

其实这种做法和Python中返回一个元组的做法类似:

def four_fundamental(a: int, b: int) -> tuple:
    return (a+b, a-b, a*b, int(a/b))


a: int = 10
b: int = 2
add_result: int
sub_result: int
mul_result: int
div_result: int
add_result, sub_result, mul_result, div_result = four_fundamental(a, b)
print("add_result is :", add_result)
print("sub_result is :", sub_result)
print("mul_result is :", mul_result)
print("div_result is :", div_result)
# add_result is : 12
# sub_result is : 8
# mul_result is : 20
# div_result is : 5

Python中的变量类型注解是不能在解包的时候写在同一行的,详情见[PEP 526 – Syntax for Variable Annotations](https://github.com/icexmoon/PEP-CN/blob/main/peps/PEP 526 – Syntax for Variable Annotations.md),当然注解并非是Python编程所必须的。

此外,如果不需要使用某个函数的返回值,可以使用空白标识符_替代:

package main

import "fmt"

func main() {
	a := 10
	b := 2
	add_result, _, _, _ := four_fundamental(a, b)
	fmt.Println("add_result is :", add_result)
}

func four_fundamental(a int, b int) (int, int, int, int) {
	return a + b, a - b, a * b, a / b
}

// add_result is : 12

Python程序员应该对此很熟悉,毕竟_也在Python中大量作为空白标识符被使用。甚至最新的Python3.10中的新功能模式匹配中也巧妙运用case _:实现了类似switch...case语句中的default的作用,详情见[PEP 636 – Structural Pattern Matching: Tutorial](https://github.com/icexmoon/PEP-CN/blob/main/peps/PEP 636 – Structural Pattern Matching Tutorial.md)。

参考资料

  • Go 简易教程

你可能感兴趣的:(Go语言,golang,开发语言,后端)