这是我参与「第五届青训营 」笔记创作活动的第1天。
本文重点内容
- Go 准备与环境配置
- Go基础语法
重点知识点介绍
背景知识
Go是一门编译型语言,Go语言的工具链将源代码及其依赖转换成计算机的机器指令(译注:静态编译)。Go语言提供的工具都通过一个单独的命令go
调用,go
命令有一系列子命令。最简单的一个子命令就是run。这个命令编译一个或多个以.go结尾的源文件,链接库文件,并运行最终生成的可执行文件。(本书使用$表示命令行提示符。)
Go模块代理
命名
Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的:heapSort和Heapsort是两个不同的名字。
Go语言中类似if和switch的关键字有25个;关键字不能用于自定义名字,只能在特定语法结构中使用。
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
此外,还有大约30多个预定义的名字,比如int和true等,主要对应内建的常量、类型和函数。
内建常量: true false iota nil
内建类型: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error
内建函数: make len cap new append copy close delete
complex real imag
panic recover
这些内部预先定义的名字并不是关键字,你可以在定义中重新使用它们。在一些特殊的场景中重新定义它们也是有意义的,但是也要注意避免过度而引起语义混乱。
如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问。名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的(译注:必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问。包本身的名字一般总是用小写字母。
名字的长度没有逻辑限制,但是Go语言的风格是尽量使用短小的名字,对于局部变量尤其是这样;你会经常看到i之类的短名字,而不是冗长的theLoopIndex命名。通常来说,如果一个名字的作用域比较大,生命周期也比较长,那么用长的名字将会更有意义。
在习惯上,Go语言程序员推荐使用 驼峰式 命名,当名字由几个单词组成时优先使用大小写分隔,而不是优先用下划线分隔。因此,在标准库有QuoteRuneToASCII和parseRequestLine这样的函数命名,但是一般不会用quote_rune_to_ASCII和parse_request_line这样的命名。而像ASCII和HTML这样的缩略词则避免使用大小写混合的写法,它们可能被称为htmlEscape、HTMLEscape或escapeHTML,但不会是escapeHtml。
数据与容器
-
Go中变量可以定义类型(在变量名称后声明)或者不定义。
两种方式的例子:
var b, c int = 1, 2
-
常量用
const
声明 -
字符串可以直接
+
相连:g := a + "foo"
-
switch
语句可以用来代替传统if-else
switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") }
-
数组的两种定义方式
var a [5]int
b := [5]int{1, 2, 3, 4, 5}
-
切片的两种定义方式
c := make([]string, len(s))
good := []string{"g", "o", "o", "d"}
-
map
的两种定义方式m := make(map[string]int)
m2 := map[string]int{"one": 1, "two": 2}
-
range
与map
键值对的用法m := map[string]string{"a": "A", "b": "B"} for k, v := range m { fmt.Println(k, v) // b B; a A } for k := range m { fmt.Println("key", k) // key a; key b }
传参类型
Go
中默认为传值,经过设置后可以传址(引用),处理数据用&
,声明类型和指代变量用*
:
结构体
结构体赋值类似于Json
,结构体中可以带成员函数,用前导括号表示,带指针版能修改内部内容。
type user struct {
name string
password string
}
func checkPassword(u user, password string) bool {
return u.password == password
}
//结构体成员函数
func (u user) checkPassword(password string) bool {
return u.password == password
}
//带指针版能修改内部内容
func (u *user) resetPassword(password string) {
u.password = password
}
func main(){
c := user{name: "wang"}
}
strings常用函数
字符串相关处理的函数,总结如下:
a := "hello"
fmt.Println(strings.Contains(a, "ll")) // true
fmt.Println(strings.Count(a, "l")) // 2
fmt.Println(strings.HasPrefix(a, "he")) // true
fmt.Println(strings.HasSuffix(a, "llo")) // true
fmt.Println(strings.Index(a, "ll")) // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
fmt.Println(strings.Repeat(a, 2)) // hellohello
fmt.Println(strings.Replace(a, "e", "E", -1)) // hEllo
fmt.Println(strings.Split("a-b-c", "-")) // [a b c]
fmt.Println(strings.ToLower(a)) // hello
fmt.Println(strings.ToUpper(a)) // HELLO
fmt.Println(len(a)) // 5
strings.Trim(input, "\r\n")
strings.NewReader(`{"trans_type":"en2zh","source":"he"}`)
本文小结
多种数据类型与结构体、容器、以及字符串的相关介绍