
文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载本篇指南以本仓库build-web-application-with-golang一本教你用 Go 构建 Web 应用的电子书**第 2 章「Go basic knowledge」**为骨架系统讲解 Go 语言的全部 25 个关键字及其背后的核心语法变量与常量、包与函数、流程控制、struct 与面向对象、接口、并发等。读完本文你将掌握这份关键字清单的每个用法并能在 th/code/src/apps 目录下找到与各小节一一对应的可运行示例代码为后续章节Web 基础、表单、数据库、Web 框架开发打下扎实的语法基础。25 个关键字比英文字母还少的完整语法集Go 是一门编译型系统编程语言属于 C 语言家族但它的编译速度远快于同族的其他语言。最令人印象深刻的事实是Go 的全部关键字只有 25 个——比英文字母表的 26 个字母还要少一个。这正是 Go 语言简洁设计哲学的起点。在开始编码之前先记住这份完整的清单摘自 th/02.0.mdbreak default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var这些关键字覆盖了 Go 的全部语法维度。本仓库第 2 章共分 8 个小节Hello, Go、Go foundation、Control statements and functions、struct、Object-oriented、interface、Concurrency、Summary逐一展开讲解。下面我们按功能分组逐个吃透它们。变量与常量var、const定义变量的多种写法Go 中var是定义变量的基本形式注意类型放在变量名之后// 定义名为 variableName、类型为 type 的变量 var variableName type // 同时定义多个同类型变量 var vname1, vname2, vname3 type // 定义并初始化 var variableName type value var vname1, vname2, vname3 type v1, v2, v3如果带初始值可以省略类型让编译器自行推断更简洁的是用:短变量声明直接替代var和类型var vname1, vname2, vname3 v1, v2, v3 // 省略类型 vname1, vname2, vname3 : v1, v2, v3 // 短变量声明需要特别注意的是:只能在函数体内使用在函数体外定义全局变量仍须使用var。_下划线是一个特殊的变量名赋给它的任何值都会被忽略。它最常见的用途是丢弃函数的多返回值中不需要的部分_, b : 34, 35 // 34 被丢弃Go 编译器对定义了却未使用的变量会直接报编译错误例如下面这段代码就编译不过package main func main() { var i int }常量的定义常量在编译期确定、运行期不可更改可用数字、布尔值或字符串作为常量类型const constantName value const Pi float32 3.1415926 // 必要时可显式指定类型 // 更多示例 const Pi 3.1415926 const i 10000 const MaxThread 10 const prefix astaxie_iota是配合const实现枚举的关键字从 0 开始、逐行递增const( x iota // x 0 y iota // y 1 z iota // z 2 w // 省略表达式时沿用上一行的表达式故 w 3 ) const v iota // 遇到新的 const 关键字iota 重置为 0所以 v 0 const ( e, f, g iota, iota, iota // 同一行内 iota 值相同e f g 0 )分组定义与可见性规则多个变量、常量或 import 可以用分组形式一次性定义import( fmt os ) const( i 100 pi 3.1415 prefix Go_ ) var( i int pi float32 prefix string )Go 没有public/private关键字可见性由命名决定首字母大写即导出公开小写则为私有——变量、函数、常量均遵循此规则。这一规则在 th/02.2.md 中有明确说明。包与导入package、importGo 程序由包package组成。每个源码文件第一行用package pkgName声明它属于哪个包main包会被编译成可执行程序而其他包会编译成.a归档文件。导入包有三种特殊写法详见 th/02.3.mdimport ( . fmt // 点操作调用时省略包名fmt.Printf 变成 Printf f fmt // 别名操作f.Printf(Hello world) _ github.com/ziutek/mymysql/godrv // 下划线只执行该包的 init 函数 )第三种的_操作常被初学者忽略它表示我只需要这个包执行init函数比如注册数据库驱动并不直接调用它的函数。Go 支持两种导入路径相对路径./model不推荐和绝对路径shorturl/model对应$GOPATH/pkg/shorturl/model。函数与流程控制func、return、defer、if、else、for、range、switch、case、break、continue、fallthrough、goto、default函数定义与多返回值用func关键字定义函数参数类型跟在参数名之后返回值支持多值返回——这是 Go 比 C 更强的地方// 两个返回值都不命名 func SumAndProduct(A, B int) (int, int) { return A B, A * B } // 返回值命名后只需 return 即可自动返回 func SumAndProduct(A, B int) (add int, multiplied int) { add A B multiplied A * B return }变参函数使用...表示不定数量参数在函数体内arg表现为一个slicefunc myfunc(arg ...int) {} for _, n : range arg { fmt.Printf(And the number is: %d\n, n) }函数默认按值传递拿到的是实参副本修改不影响原变量若要修改原变量需传入指针*int传xfunc add1(a *int) int { *a *a 1 // 通过指针修改原变量 return *a } x1 : add1(x) // 传 x 的内存地址流程控制四件套if不需要括号但支持在条件前附带一条初始化语句该语句定义的变量仅在 if 块内可见if x : computedValue(); x 10 { fmt.Println(x is greater than 10) } else { fmt.Println(x is less than 10) } // fmt.Println(x) // 编译错误x 超出作用域forGo 唯一的循环关键字等价于其他语言的while与range配合可遍历array、slice、map和stringsum : 1 for sum 1000 { // 省略分号后与 while 完全一致 sum sum } for _, v : range map { // 用 _ 丢弃不需要的 key fmt.Println(maps val:, v) } for { // 无限循环等价于 while true }switch条件不必是常量从上到下匹配第一个命中项即跳出无需写 break多个值可写在同一case如需继续向下匹配使用fallthroughinteger : 6 switch integer { case 4: fmt.Println(integer 4) fallthrough case 5: fmt.Println(integer 5) fallthrough case 6: fmt.Println(integer 6) fallthrough case 7: fmt.Println(integer 7) fallthrough case 8: fmt.Println(integer 8) fallthrough default: fmt.Println(default case) } // 输出integer 6、integer 7、integer 8、default casegoto 与标签goto跳转到同代码块内预先定义的标签标签名区分大小写func myFunc() { i : 0 Here: // 标签以冒号结尾 fmt.Println(i) i goto Here }defer延迟执行的资源管理利器defer保证函数返回前执行注册的操作常用来关闭文件、解锁资源多个defer按逆序执行。对比一下传统写法要在每个错误分支重复file.Close()用defer后只需一行func ReadWrite() bool { file.Open(file) defer file.Close() if failureX { return false } if failureY { return false } return true }自定义类型与面向对象struct、type、interface、mapstruct 与内嵌字段struct用于定义包含多个字段的自定义类型。初始化有三种方式按顺序、按field:value无序、匿名 structtype person struct { name string age int } P : person{Tom, 25} P : person{age: 24, name: Bob} P : struct{name string; age int}{Amy, 18}struct 支持内嵌字段embedded fields被内嵌 struct 的所有字段会隐式提升为外层 struct 的字段同名冲突时外层字段优先可视为字段重载type Human struct { name string age int phone string } type Employee struct { Human specialty string phone string // 与 Human.phone 同名访问 Bob.phone 时取 Employee 的 }所有类型包括自定义的 slice 类型、内置类型都可以作为内嵌字段完整示例见 th/02.4.md。方法带接收者的函数方法是隶属于某个类型的函数语法为func (r ReceiverType) funcName(parameters) (results)。Rob Pike 的定义是方法是一个带有隐式第一参数接收者的函数。同一个方法名可以属于不同的接收者类型type Circle struct { radius float64 } type Rectangle struct { width, height float64 } func (c Circle) Area() float64 { return c.radius * c.radius * math.Pi } func (r Rectangle) Area() float64 { return r.width * r.height }接收者可以是值或指针*Box。指针接收者能修改原对象SetColor若用值接收者只会在副本上修改。此外内嵌 struct 的方法会被外层 struct 继承在外层定义同名方法即可实现方法重写overriding见 th/02.5.md。接口一组方法的集合接口定义一组方法签名任何实现了这些方法的类型即实现了该接口一个类型可以同时实现多个接口。空接口interface{}没有任何方法因此所有类型都实现了它——它类似于 C 的void*可用于存储任意类型。判断接口中实际存储的具体类型有两种方式comma-ok 断言value, ok : element.(T)ok为 true 表示类型符合预期switch 类型测试switch value : element.(type)注意element.(type)只能用在 switch 体内。接口还可以内嵌例如container/heap包中的Interface内嵌了sort.Interface从而自动拥有Len/Less/Swap三个方法io.ReadWriter内嵌Reader与Writer。更多细节与reflect反射基础reflect.TypeOf、reflect.ValueOf、通过Elem()修改值见 th/02.6.md。map内置的字典map类似 Python 的字典用map[keyType]valueType定义key 可以是任何能用/!比较的类型。它是无序的、长度不固定、引用类型numbers : make(map[string]int) numbers[one] 1 numbers[ten] 10 rating : map[string]float32{C: 5, Go: 4.5} csharpRating, ok : rating[C#] // ok 判断 key 是否存在 if ok { fmt.Println(C# is in the map and its rating is , csharpRating) } delete(rating, C) // 删除元素make 与 new 的区别new(T)为类型分配零值内存返回指向该零值的指针*Tmake(T, args)仅用于slice、map、channel这三种内置引用类型初始化其底层数据结构并返回非零值因为这三种类型的底层数据必须初始化后才能使用。Go 的零值zero-value并不等于空值而是变量声明后的默认值int为 0、float32/64为 0、bool为 false、string为、byte为 0x0 等完整零值表见 th/02.2.md。并发go、chan、selectGo 被称为21 世纪的 C一个重要原因就是语言层面的并发支持。goroutine轻量级线程用go关键字即可启动一个新的 goroutine底层是一个函数main()本身也是一个 goroutine。每个 goroutine 通常只占用 4~5 KB 栈内存单台机器轻松运行成千上万个package main import ( fmt runtime ) func say(s string) { for i : 0; i 5; i { runtime.Gosched() fmt.Println(s) } } func main() { go say(world) // 创建新 goroutine say(hello) // 当前 goroutine }runtime.Gosched()让出 CPU使其他 goroutine 得以执行。在 Go 1.5 之后GOMAXPROCS默认等于 CPU 核心数更早版本默认只用单线程调度所有 goroutine仅并发、非并行需手动调用runtime.GOMAXPROCS(n)启用多核并行。完整示例在 th/code/src/apps/ch.2.7/goroutine/main.go。channelgoroutine 之间的通信管道goroutine 共享同一内存地址空间需要同步机制。channel是 Go 内置的双向管道用make创建用-收发数据ci : make(chan int) cs : make(chan string) cf : make(chan interface{}) ch - v // 发送 v 到 channel ch v : -ch // 从 ch 接收数据并赋给 v无缓冲 channel 的收发默认阻塞天然实现同步。channel还支持缓冲make(chan bool, 4)和range遍历需用close关闭后循环才会结束生产者关闭 channel 更安全否则容易触发 panic。select多 channel 监听select默认阻塞直到某个 channel 就绪才继续多个 channel 同时就绪时随机选择执行。它也支持default分支所有 channel 都未就绪时立即执行可用于实现超时控制select { case v : -c: println(v) case -time.After(5 * time.Second): println(timeout) o - true break }runtime 包中的 goroutine 工具函数函数作用runtime.Goexit()退出当前 goroutine但 defer 函数照常执行runtime.Gosched()让调度器执行其他 goroutine之后回来runtime.NumCPU()返回 CPU 核心数runtime.NumGoroutine()返回当前 goroutine 数量runtime.GOMAXPROCS(n)设置使用的 CPU 核心数基础类型速览从布尔到复数布尔bool值只能为true/false默认值为false且不能与数值类型互相转换整数int/uint长度取决于操作系统32 位系统为 32 位、64 位系统为 64 位另有定长类型int8…int64、uint8…uint64其中rune是int32的别名、byte是uint8的别名。不同整数类型之间不能直接赋值或运算即使int32与int也会编译错误浮点只有float32和float64没有float类型短声明时默认float64复数complex128默认64 位实部 64 位虚部与complex64形如REIMi例如var c complex64 55i字符串用双引号或反引号表示。字符串不能按下标修改但可以转换为[]byte修改后再转回或用拼接、用切片取值反引号字符串不转义任何字符可跨行s : hello c : []byte(s) c[0] c s2 : string(c) m : hello world // 多行字符串错误内置error类型配合errors包处理错误信息err : errors.New(...)。数组、切片与内存模型array长度是类型的一部分[3]int与[4]int是不同类型作为函数参数时传递的是副本而非引用可用[...]int{4,5,6}让编译器推算长度slice引用类型指向底层 array由起始指针 长度 容量三部分组成用array[i:j]切片含 i 不含 jar[:]表示整个数组len取长度、cap取容量、append追加元素、copy复制元素。注意append会修改 slice 指向的底层数组进而影响指向同一数组的其他 slice当(cap-len) 0时append会分配新数组旧数组不再受影响map 是引用类型两个 map 指向同一底层数据时任一方的修改都会影响另一方。这些基础类型的详细示例与图示含底层内存结构图请参阅 th/02.2.md对应可运行代码在 th/code/src/apps/ch.2.2/main.go。程序的初始化顺序init与main每个包都可以有可选的init函数main包必须有且仅有一个main函数两者都不能有参数和返回值。程序初始化流程为先初始化main包导入的所有包每个包只会被编译一次按常量 → 变量 → init 函数的顺序全部就绪后再初始化main包自身的常量、变量与init函数最后执行main()。流程细节见 th/02.3.md。从 Hello, Go 开始你的第一个程序按照惯例我们从打印 Hello world 开始。注意 Go 默认支持 UTF-8你可以在代码中直接使用任何语言的字符package main import fmt func main() { fmt.Printf(Hello, world or 你好世界 or Καλημέρα κόσμε or こんにちは世界\n) }逐行拆解详见 th/02.1.mdpackage main声明本文件属于main包——每个可执行程序有且仅有一个main包import fmt导入提供Printf等格式化输出函数的fmt包调用语法为pkgName.funcNamefunc main()程序入口函数不能有参数和返回值函数体用{}包裹与 C、C、Java 一致第 6 行fmt.Printf(...)包名来自package声明而非文件夹名。两个容易踩坑的细节main 包不需要main文件夹但每个可执行程序中只能有一个包含main函数的 Go 文件Go 代码不需要也不应写分号——编译器在编译时自动补分号。正因如此左花括号必须与函数名同行func main () { // 编译错误编译器在 main() 后自动补了分号 }对应示例代码位于 th/code/src/apps/ch.2.1/main.go编译运行方式在源码目录执行go build生成二进制再从应用根目录运行该二进制若程序依赖静态文件等资源务必从根目录启动否则可能遇到程序找不到资源的问题。回顾25 个关键字的完整职能表本仓库 th/02.8.md第 2 章总结对全部关键字给出了官方归类var、const定义变量与常量package、import包的使用func定义函数与方法return函数/方法返回值defer定义延迟执行的函数go启动新的 goroutineselect在多个 channel 间切换通信interface定义接口struct定义特殊自定义类型break、case、continue、for、fallthrough、else、if、switch、goto、default流程控制第 2.3 节changoroutine 间通信的 channel 类型type定义自定义类型map定义类似哈希表的映射range从slice、map、channel读取数据。配套代码与继续深入第 2 章每一节的示例代码都整理在仓库的 th/code/src/apps 目录下按ch.2.x分目录组织例如ch.2.1/main.goHello, Goch.2.2/main.go基础类型与数组/切片/mapch.2.3/main.go 与 basic_functions、variadic_functions流程控制与函数ch.2.4/main.go 与 compare_agestruct 与内嵌字段ch.2.5box_example、embedded_method、method_overload 三个子示例方法/指针接收者/继承/重写ch.2.6interface、type_check、switch_type_check接口与类型断言ch.2.7/goroutine/main.go并发掌握这 25 个关键字就等于掌握了 Go 语法的全部骨架。下一章 Web foundation 将以此为基础讲解 Web 工作原理与用 Go 搭建第一个 Web 服务器——届时你会发现这些语法知识会以net/http包的形式被反复运用。赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐Go 语言 25 个关键字全解析掌握 build-web-application-with-golang 第 2 章的基础知识Go 语言 25 个关键字全解析掌握 build web application with golang 第 2 章的基础知识 本篇文章围绕开源 Go 语言电文档教程Go 语言基础篇25 个关键字与《用 Go 构建 Web 应用》第二章学习路线Go 语言基础篇25 个关键字与《用 Go 构建 Web 应用》第二章学习路线 导读 本文面向《用 Go 构建 Web 应用build web appli文档教程Go 语言 25 个关键字全解《build-web-application-with-golang》第 2 章小结精讲Go 语言 25 个关键字全解《build web application with golang》第 2 章小结精讲 本文对应开源 Go 教程 《build文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考