Golang上手小记:基础篇

最近一直在考虑自己技术栈的问题,Python+C+JS这个技术栈,的确能覆盖我当下的需求。但是,写一些项目的时候,我会觉得JS太笨重、Python太慢而C又太麻烦,所以,我需要这样一个语言,它需要满足以下的要求:

  1. 是过程式的,不应该是OOP和FP的,因为我需要最大程度利用我现在的编码逻辑。
  2. 有GC,我不想再手动malloc、free内存空间了,我需要把这部分的心智负担交给语言本身。
  3. 生态足够发达,这样的话就有大量的资料,大量的第三方库可用。

于是,我选择出来了Golang作为新学习的一个语言。因为它在满足上面的三个性质之外,又足够简单。

创建项目

Golang和现在很多语言都是一样的,首先要创建一个项目,然后进行依赖处理、编码等。只要安装好了Golang的开发环境,只要在终端输入:

1
go mod init example/project

就可以创建一个空的项目。至于依赖,很有意思,只需要在项目文件中引入:

1
import "rsc.io/quote"

然后在终端输入:

1
go mod tidy

就可以从网站下载到这个包,相比于Python,我认为这种处理依赖的方式很优雅。

想要预览程序的效果,就可以:

1
go run .

在构造的时候,只需要:

1
go build

就可以构造出一个二进制文件来。

这种项目的创建、构造方式实际上和Haskell、Rust等语言很接近了,不如说,现在的大部分语言都是这样的创建和构造方式。

编码体验

至于实际的编码,语法上相比于C并没有特别大的变化,都可以轻易把对C语言的理解迁移过来。一个代码块如下:

1
2
3
4
5
6
7
8
9
10
11
func Hello(name string) (string, error) {
name_prefix := []string{
"Hello, ",
"Hi, ",
"Hiya, ",
}
if name == "" {
return "", errors.New("no name given")
}
return fmt.Sprintf("Hello, %s, %s!", name_prefix[rand.Intn(len(name_prefix))], name), nil
}

变量的赋值有两种方式,一种是采用:=操作符,另一种则是采用var关键字和=结合的方式,前者相当于后者的一种语法糖,相当于“声明了这是一个变量,又给它赋值”,比如下面这两种方式是完全一致的:

1
2
3
4
5
6
// Case 1
var a int
a = 3

// Case 2
a := 3

我觉得:=是一种“脱裤子放屁的设计”,我还是喜欢C那种“类型 变量名 = 变量值”的方式,统一又便于理解。怎么说呢,我能感受到,喜欢:=的人会很喜欢它,不喜欢它的人,就很极其厌恶它。如您所见,采用var关键字进行变量声明和赋值的时候,类型是写在变量名后面的,这一点我觉得也很合理,比较符合人类的简单句读写习惯,“我有一个苹果。苹果是红色的。”

对于条件操作,if语句不需要写括号括起来,倒是一个比较明显的设计。

比较有意思的是Golang中的函数声明,在函数的声明中,变量在前,类型在后,返回值在大括号的前面,这对我来说是一种比较新奇,但又意外非常直觉的一种体验。我需要一段时间才能够适应这种写法。这里的函数依然包含了值传递和引用传递两种写法,通常是值传递,当需要引用传递的时候,就可以:

1
2
3
func SwapInPlace(num1 *int, num2 *int) {
*num1, *num2 = *num2, *num1
}

至于结构体,没什么好说的,和C语言大差不差,一个例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"
)

type Complex struct {
Real float64
Image float64
}

func OutputComplex(complex Complex) string {
return fmt.Sprintf("%v + %vi", complex.Real, complex.Image)
}

func main() {
complex_1 := Complex{2, 1}
fmt.Println(OutputComplex(complex_1))
}

不过,如果结构体是以指针形式给出的,那么访问成员依然使用.操作符,非常好的设计。

至于数据结构,哈希表的创建也很有意思,非常简单,有种Python的美:

1
2
3
4
5
6
7
8
9
10
func main() {
complex_to_Id := make(map[Complex]int)
complex_2 := Complex{1, 3}
complex_3 := Complex{1, 4}
complex_to_Id[complex_2] = 0
complex_to_Id[complex_3] = 1
for complex_element, idx := range complex_to_Id {
fmt.Printf("Idx: %v, Complex: %v\n", idx, OutputComplex(complex_element))
}
}

第二行相当于创建了一个从Complexint的哈希表,这段代码里值得注意的是range关键字,其作用和Python语言中的in差不多,限定了一个范围。对于循环操作,Golang中只有for循环,没有while和do-while语句,这一点我觉得略有一些不便——虽然这三种语句的表达能力是完全等价的。除此之外,字符串的操作和C语言下面很相似,但是增加了+运算符等操作,体验要比C语言好很多。

单元测试是包含在标准库之内的,这也省去了C、C++、Java等语言需要额外单元测试库的开销。

除此之外,Golang也支持泛型,简单而不简陋。只是这块还没弄懂,下次和接口、多线程一起讲讲。

文章作者:
文章链接: https://www.coderlock.site/2025/11/09/Golang上手小记/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 寒夜雨