请你按照我已有的 Go 学习笔记风格,帮我整理新的 Go 知识点笔记,并写成适合直接放入 Obsidian 的 Markdown 内容。

笔记整体风格

  • 使用简洁、直接、偏学习记录式的中文表达。
  • 不要写得太像教材,要像个人学习笔记。
  • 先给出概念,再给出常见语法或代码示例,最后补充特点、注意事项或理解。
  • 重点内容可以使用 加粗
  • Go 关键词、变量名、函数名、类型名、包名、方法名、接口名、运算符、代码片段使用反引号包裹,例如:varconstfuncreturndefergochanintstringfmt.Println()make()append()
  • 适合初学者理解,不要堆太多复杂概念。
  • 可以适当补充用途、场景、注意事项和常见错误。
  • 不需要生成 YAML frontmatter,文件属性会由 Obsidian 自动生成。
  • 完成整理后,应根据正文内容总结 tags
  • tags 的语义不能和文档所在目录重复。
  • 完成整理后,这篇文章属于 AI 写作,应在 author-type 改为 ai
  • 完成整理后,应在 status 列表中添加 Completed
  • status 只允许使用:BacklogPlannedReadyIn ProgressBlockedIn ReviewCompleted
  • note-sections 只允许使用 introductionoutlinemain-bodylead-out key-highlight,如果笔记已经包含这些内容,就可以全部写入。
  • tagstatusnote-sections 这些都是 yaml 列表数组,请采用多行数组格式

标题结构

正文优先使用以下层级:

引入

用一小段话说明这个知识点为什么存在,特别是指出它解决什么问题。

例如:

Go 是一门编译型语言,代码写好之后需要编译成可执行文件才能运行。Go 的编译速度非常快,而且编译后的程序可以直接运行,不需要虚拟机或运行时环境。

正文

正式解释概念和用法。

可以根据内容拆分为:

定义

使用引用块或 callout 说明核心定义,例如:

定义

变量是用来保存数据的名字,后续可以通过这个名字读取或修改数据。

或者普通引用:

Go 的核心就是:用简洁的语法写出高效的程序,编译后直接运行,不需要额外环境。

语法

给出最常见的基础写法。

var name string = "Tom"
age := 18

例如:

count := 0
count = count + 1

例子

用具体小例子说明。

示例标题

说明这个例子在做什么。

// 示例代码

常见写法

如果这个知识点涉及多个写法,可以用列表或表格整理。

写法作用
var name string = "Tom"完整声明一个字符串变量
name := "Tom"短变量声明,自动推断类型
fmt.Println(name)在终端输出内容

特点

用无序列表总结规则、特征或注意事项。

  • var 声明的变量可以重新赋值
  • := 短变量声明只能在函数内部使用
  • const 声明的常量必须初始化,且不能修改
  • Go 是强类型语言,变量类型确定后不能改变
  • Go 代码必须写在 package 里,入口是 main 包的 main() 函数
  • 未使用的变量会导致编译错误

理解

用更口语化的方式总结这个知识点的本质理解。

例如:

可以把变量理解为一个带名字的盒子,盒子里放的是数据。

var:= 都能创建变量,区别是 := 更简洁,但只能在函数内部用。

Go 和 JS 不同,Go 代码必须先编译再运行,编译时会检查所有变量是否被使用。

引出

不能死板的写:后序可以继续学习某某知识点,需要思考这个知识点还有什么方向没提及,有什么可以优化地方,提出后序的问题,不一定需要给出回答,留下问题引出即可。 如果这个知识点会连接到下一个知识点,可以简单写一句。下一个知识点请根据 Go/Go.md 这个文件中寻找存在的,不能凭空生成。

代码风格

  • Go 代码块使用 go 语言标记。
  • 代码示例要尽量短,能说明问题即可。
  • 代码中可以加入简短注释,但不要过多。
  • 代码格式遵循 go fmt 标准格式。
  • 赋值运算符两边保留一个空格,例如:count := 0
  • 函数名和括号之间不加空格,例如:fmt.Println()
  • 代码块中每条语句尽量独占一行。
  • Go 不需要写分号,编译器会自动处理。
  • 大括号 { 必须和声明在同一行,不能另起一行。
  • 初学阶段优先使用清晰写法,不为了简短写过度压缩的代码。
  • 导入包时使用标准导入路径,例如:import "fmt"

内容组织习惯

请优先按照这个顺序写:

  1. 这个东西是什么
  2. 为什么需要它
  3. 基础语法是什么
  4. 常见用法有哪些
  5. 代码例子
  6. 注意事项
  7. 我的理解式总结

表达习惯

  • 解释变量时,可以写成:“用于保存数据,后续可以通过变量名使用这个数据”。
  • 解释常量时,可以写成:“用于保存不希望被重新赋值的数据”。
  • 解释数据类型时,可以写成:“用于告诉编译器数据是什么种类,Go 是强类型语言,类型必须明确”。
  • 解释字符串时,可以写成:“用于保存一段文本内容,Go 的字符串是 UTF-8 编码的”。
  • 解释函数时,可以写成:“把一段代码封装起来,需要时再调用”。
  • 解释参数时,可以写成:“调用函数时传进去的数据,Go 的参数必须声明类型”。
  • 解释返回值时,可以写成:“函数执行后交回来的结果,Go 支持多返回值”。
  • 解释结构体时,可以写成:“用来把一组相关数据组合在一起”。
  • 解释数组时,可以写成:“用来按顺序保存多个相同类型的数据,长度固定”。
  • 解释切片时,可以写成:“动态长度的序列,比数组更常用”。
  • 解释 map 时,可以写成:“用键值对保存数据,通过键快速查找值”。
  • 解释指针时,要说明它”保存的是另一个变量的内存地址,通过指针可以间接修改数据”。
  • 解释接口时,可以写成:“定义一组方法签名,任何实现了这些方法的类型都算实现了这个接口”。
  • 解释 goroutine 时,可以写成:“Go 的轻量级并发执行单元,用 go 关键字启动”。
  • 解释 channel 时,可以写成:“goroutine 之间传递数据的管道”。
  • 解释 defer 时,可以写成:“延迟执行的语句,通常用于释放资源,会在函数返回前执行”。
  • 解释错误处理时,可以写成:“Go 用返回值代替异常,通过检查 error 是否为 nil 来判断是否出错”。
  • 解释包时,可以写成:“把代码按功能组织在一起,方便复用和管理”。

常见主题写法

变量

重点说明 var 声明、:= 短变量声明、零值。

var id int
id = 10001

可以写成:var 用来声明变量,id 是变量名,int 是类型,10001 是保存进去的数据。

常量

说明 const 用于声明不能重新赋值的量。

const id = 1
  • const 声明时必须初始化
  • const 不能重新赋值
  • iota 可以用来生成递增的常量序列

数据类型

说明 Go 里的数据必须明确类型,分为基本类型复合类型

  • 基本类型:intfloat64boolstringbyterune
  • 复合类型:arrayslicemapstructpointerfunctioninterfacechannel

字符串

说明字符串用于保存文本,Go 的字符串是不可变的 UTF-8 字节序列。

title := "学习 Go"
message := "标题是:" + title

可以写成:字符串用双引号 "" 包裹,Go 字符串原生支持 UTF-8。

函数

说明函数用于封装一段可以重复执行的代码。

func sayHello(name string) string {
	return "你好," + name
}
 
sayHello("Tom")

需要说明:name string 是参数和类型,string 是返回值类型,Go 支持多返回值。

结构体

说明结构体用于把一组相关数据组合在一起。

type User struct {
	Name string
	Age  int
}
 
user := User{Name: "Tom", Age: 18}
fmt.Println(user.Name)

可以写成:NameAge 是结构体的字段,通过 user.Name 可以读取字段值。

切片

说明切片是动态长度的序列,比数组更常用。

list := []string{"Go", "Python", "JS"}
fmt.Println(list[0])

需要说明:切片下标从 0 开始,长度可以用 len() 获取。

Map

说明 map 用于通过键值对保存和查找数据。

scores := map[string]int{
	"Tom": 90,
	"Bob": 85,
}
 
fmt.Println(scores["Tom"])

注意说明:访问不存在的键会返回零值,需要用 ok 判断键是否存在。

接口

说明接口用于定义行为约束,Go 的接口是隐式实现的。

type Writer interface {
	Write(data []byte) (int, error)
}

可以写成:任何实现了 Write 方法的类型,都自动实现了 Writer 接口。

goroutine 和并发

说明 goroutine 是 Go 的并发执行单元。

go func() {
	fmt.Println("在后台运行")
}()

注意说明:goroutine 启动后不会等它执行完毕,需要用 channelsync.WaitGroup 来协调。

channel

说明 channel 用于 goroutine 之间传递数据。

ch := make(chan string)
 
go func() {
	ch <- "你好"
}()
 
msg := <-ch
fmt.Println(msg)

可以写成:ch <- 是发送数据,<-ch 是接收数据,无缓冲 channel 会阻塞直到双方准备好。

错误处理

说明 Go 用返回值处理错误,而不是异常。

result, err := doSomething()
if err != nil {
	fmt.Println("出错了:", err)
	return
}
fmt.Println(result)

注意说明:Go 的习惯是每次都检查 err,不要忽略错误。

包和模块

说明包是 Go 组织代码的基本单位。

package main
 
import "fmt"
 
func main() {
	fmt.Println("Hello, Go")
}
import "github.com/user/project/pkg"
  • 每个 .go 文件必须声明所属 package
  • 导出名首字母大写,未导出名首字母小写
  • go mod init 用来初始化模块

链接和资料

如果有权威参考资料,可以放在靠前位置,也可以放在正文中。

常用资料:

Go 官方文档

Effective Go

Go 语言中文网

Go by Example

输出要求

  • 只输出完整 Markdown 笔记内容。
  • 不要额外解释”我将如何写”。
  • 不要使用过度复杂的术语。
  • 内容要能直接复制进 Obsidian。
  • 如果我给出笔记标题,例如 Go 变量,就按这个主题生成完整笔记。
  • 如果我要求”写入”,就直接整理成对应文件内容。

使用方式

之后可以这样提问:

请按照我的 Go 学习笔记风格,整理一篇 [[Go 变量]]

或者:

按照 Go 学习笔记风格,帮我写入 [[Go 切片]]