Go入门笔记 / Go beginner

Go入门笔记

Go是编译型语言:

Go 代码通过 go build 或 go run 等命令来编译成二进制文件。尽管 Go 允许使用 go run 直接执行代码,但背后其实是先将代码编译成二进制文件再执行,而非逐行解释执行。

Go语言常用的命名规范

在 Go 中,导出的(exported)函数名应该以大写字母开头,而 未导出的(unexported)函数名则以小写字母开头。

  • Hello: 这是一个导出的函数(首字母大写),因此它可以被包外的代码调用。导出的函数应该遵循 Go 的首字母大写命名规则。
  • randomFormat: 这是一个未导出的函数(首字母小写),只能在当前包内使用。未导出的函数名通常首字母小写。

Tutorial: Get started with Go

When you need your code to do something that might have been implemented by someone else, you can look for a package that has functions you can use in your code.

Tutorial: Create a Go module

1. Relation between module and package

In a module, you collect one or more related packages for a discrete and useful set of functions.

2. How to name a module

A module's name should look like this:

<prefix>/<descriptive-text>

The prefix is typically a string that partially describes the module, such as a string that describes its origin. This might be:

The location of the repository where Go tools can find the module’s source code (required if you’re publishing the module).

For example, it might be github.com/<project-name>/.

Use this best practice if you think you might publish the module for others to use. For more about publishing, see Developing and publishing modules.

If you’re not using a repository name, be sure to choose a prefix that you’re confident won’t be used by others. A good choice is your company’s name. Avoid common terms such as widgets, utilities, or app.

For the descriptive text, a good choice would be a project name. Remember that package names carry most of the weight of describing functionality. The module path creates a namespace for those package names.

3. 常见占位符和字符串表示

  • %v:%v 是最常用的占位符之一,它会根据值的类型来选择最合适的格式进行输出。它可以用于任何类型的数据(int、float、string、struct、slice 等)。对于复合类型(如结构体),%v 会输出字段值的默认格式。如果你想要更详细的输出,可以使用 %+v,这会在输出时包含字段名。
  • %q:用于格式化字符串,表示带有双引号的字符串。例如:"Hello"
  • %#q:格式化成带有转义的字符串,并且带上双引号。与 %q 相比,%#q 会转义所有不可打印的字符,例如换行符、制表符等。

另外,如果要打印的目标字符串当中含有双引号,那么可以使用反引号`来包围目标字符串,避免冲突。

而且,反引号包含的字符串是原始字符串,内部的字符都会被逐字解释,不会被转义。

Python当中,双引号和单引号都能用来表示字符串,但是Go当中只能用双引号;

Go中单引号只能用来表示单个字符,Go中单个字符的数据类型是rune,本质上是int32的别名;而C语言中char是int8。

示例:

want := regexp.MustCompile(`\b` + name + `\b`)

这里我们定义了一个正则表达式want,假设name变量是zzf,那么我们在括号里得到的就是`\bzzf\b`,当正则表达式引擎接受到这个字符串时,\字符被解析为转义字符,把b转义成:word boundary

4. 命名空间

每个package都是一个独立的命名空间,使用来自其他module中的函数时,要在函数名前加上相应package的限定,类似于C++的命名空间。

5.Go的指针

Go 和 C 语言中的指针对比

1. 基本概念(相同点)

  • Go 和 C 都支持指针:
    • 在 Go 和 C 中,指针都是用于存储另一个变量的内存地址。
    • 通过指针,你可以间接访问或修改指向的变量的值。
  • 获取指针和解引用:
    • 在 Go 和 C 中,符号 & 用于获取变量的地址,符号 * 用于通过指针访问变量的值。

Go 示例:

var a int = 10
var p *int = &a  // p 是一个指向 a 的指针
fmt.Println(*p)  // 解引用 p,输出 a 的值,即 10

C 示例:

int a = 10;
int *p = &a;  // p 是一个指向 a 的指针
printf("%d\n", *p);  // 解引用 p,输出 a 的值,即 10

2. 主要区别

1. 没有指针运算

Go: Go 不允许对指针进行算术运算。例如,不能对指针进行 p++p-- 这样的操作。

C: C 允许指针运算,能够通过指针运算遍历数组、内存块等。这在 C 中是一个重要的特性,用于内存管理和数组操作。

C 示例:

int arr[3] = {1, 2, 3};
int *p = arr;
p++;  // 通过指针算术运算访问下一个元素
printf("%d\n", *p);  // 输出 2

Go 示例:

var arr = [3]int{1, 2, 3}
var p *int = &arr[0]
p++  // 编译错误:Go 不支持指针运算
2. 安全性

Go: Go 语言在设计时更加关注内存安全,自动管理内存,并且有垃圾回收机制。指针操作受到更多的限制,防止出现像 C 中常见的悬空指针(dangling pointer)和内存泄漏等问题。

C: C 语言中,指针的使用更加灵活,但也更容易出错,导致内存泄漏、野指针等问题。C 中的内存管理是手动的,程序员需要负责释放动态分配的内存。

3. 垃圾回收

Go: Go 有自动垃圾回收机制,程序员不需要手动释放内存,指针所指向的对象在没有任何引用后会被垃圾回收。

C: C 没有垃圾回收,程序员需要使用 malloccalloc 动态分配内存,并在不需要时使用 free 手动释放内存。否则,会造成内存泄漏。

4. 零值指针

Go: Go 中的指针类型有一个默认的零值 nil,表示这个指针没有指向任何对象。Go 中的 nil 类似于 C 中的 NULL,但 Go 提供了对 nil 的更严格检查。

C: C 中未初始化的指针是一个悬空指针,它没有指向任何有效的内存地址。虽然 C 中也有 NULL 表示空指针,但未初始化的指针容易引发问题。

Go 示例:

var p *int  // 默认值是 nil
if p == nil {
    fmt.Println("Pointer is nil")
}

C 示例:

int *p;  // p 是一个未初始化的悬空指针
if (p == NULL) {
    printf("Pointer is NULL\n");
}
5. 传递指针的方式

Go: Go 在函数参数传递中默认是值传递。如果你想修改传入的值,必须使用指针。

C: C 也有类似的值传递和指针传递的机制。通过指针传递变量地址可以在函数内部修改变量的值。

Go 示例:

func increment(val *int) {
    *val++
}

var a = 5
increment(&a)
fmt.Println(a)  // 输出 6

C 示例:

void increment(int *val) {
    (*val)++;
}

int a = 5;
increment(&a);
printf("%d\n", a);  // 输出 6

3. 小结

特性 Go C
指针运算 不支持指针运算 支持指针运算,例如 p++, p--
内存管理 自动垃圾回收,无需手动释放 手动管理内存,使用 malloc/free
指针初始化 未初始化的指针默认为 nil 未初始化指针可能导致悬空指针
内存安全性 严格的内存安全检查 指针操作容易导致内存泄漏和野指针
传递指针修改变量 通过指针传递引用并修改 通过指针传递引用并修改

总结来说,Go 语言在指针的设计上更加简洁、安全,减少了直接操作内存的复杂性,并自动管理内存,避免了许多 C 语言中常见的内存管理问题。而 C 语言中的指针功能更为灵活,但同时也更容易出现内存相关的错误。

6.编写测试

Go的测试文件有命名规范:

需要以_test.go结尾。

Go的测试函数有命名规范:

标准形式为:TestName。

其中,Name用来描述它测试什么。

且所有的测试函数都要传入一个测试指针,例如:


func TestHelloName(t *testing.T)

结束

posted @ 2024-09-03 00:13  Gold_stein  阅读(1)  评论(0编辑  收藏  举报