1 GO基础
1.1 GO语言特点
内存自动立即回收
1.2 语法特点
- 关键字
package
Go语言的代码通过包(package)组织,包类似于其它语言里的库(libraries)或者模块(modules)。一个包由位于单个目录下的一个或多个.go源代码文件组成,目录定义包的作用。每个源文件都以一条package声明语句开始,表示该文件属于哪个包,紧跟着一系列导入(import)的包,之后是存储在这个文件里的程序语句。
package main定义了一个独立可执行的程序,而不是一个库。
import导入其他要使用的包,常用的有fmt, math等
- 变量声明
变量使用关键字var声明,可以不赋值,会有默认值。
具体类型可通过直接赋值隐式推导,也可以显式写出变量类型。
语句类型有如下几种:
//隐式推导
var a="hello,"
b := a + "world!"
var c = true
//显示声明
var d int =2
var e float64 //default 0
var f bool //default false
g := float32(e)
h := 1 //循环定义变量常用写法
可以合并声明变量
var a, b ="hello", 1
变量很多可以批量声明
var{
...
}
- 常量声明
常量使用关键字const声明,在定义时必须赋值
Go中常量没有确定的类型,会根据上下文自动确定类型
- 作用范围
包一级:所有这个包内的go文件均可使用
函数:
局部变量:写在循环,if-else,switch之后,仅此范围内使用
- 函数声明
函数使用关键字func声明,变量类型后置
func 函数名(参数名1 参数类型1, 参数名2 参数类型2) 返回值类型{
...
return ...
}
//如果参数类型相同,可合并
func 函数名(参数名1, 参数名2 参数类型) 返回值类型{
...
return ...
}
传入的参数是个拷贝,不能修改,若要修改就要使用指针
1.3 语句分支
1.3.1 语句风格
- 编辑器会自动进行格式化
包括下列提到的问题,就算使用了非默认写法,都会自动进行修改
- 分号
- 换行不需要分号
书中说“Go语言不需要在语句或者声明的末尾添加分号,除非一行上有多条语句。“ Goland会自动格式化,分行,去除分号。
实际上,编译器会主动把特定符号后的换行符转换为分号,因此换行符添加的位置会影响Go代码的正确解析(译注:比如行末是标识符、整数、浮点数、虚数、字符或字符串文字、关键字break、continue、fallthrough或return中的一个、运算符和分隔符++、--、)、]或}中的一个)。
函数的左括号{必须和func函数声明在同一行上,且位于末尾,不能独占一行,而在表达式x + y中,可在+后换行,不能在+前换行(译注:以+结尾的话不会被插入分号分隔符,但是以x结尾的话则会被分号分隔符,从而导致编译错误)。
- 在if,switch,for等后边加分号间隔不同语句
-
括号
if、for、switch等不需要括号包含条件
1.3.2 流程控制
- 必须加大括号,即使只有一行
- if-else
switch不需要加break就会退出
1.4 复合数据类型
- array
固定大小
- 切片
//definition
s := make([]type, size)
s := []type{values}
s = append(s, value)
切片的底层实现是 长度+容量+指向数组的指针 在扩容时若容量不够,会进行扩容,所以需要重新赋值(第二行)
常用函数
copy(a, b) 在两个相同数据类型(不同精度也属于不同类型)的slice间将b的值复制给a
若 len(a) < len(b),仅复制len(a)的部分
若 len(a) > len(b),仅复制len(b)的部分
- map
//definition
mp := make(map[string]int)
//set value
mp["one"] = 1
//if exits key
value, is_exist = mp["two"] //default value, bool
//delete
delete(mp, "one")
- range
表示遍历。
对于一般数组,相较于C++或python的for char c:s或者for i in range(...),go的range既有index又有value。
for index, value := range nums{
...
}
遍历map,同时获得key和value
for key, value := range mp{
...
}
- 结构体
type struct_name struct{
name1 type1
name2 type2
}
//使用
var example struct_name
不能对struct进行range
1.5 常用包
- STRINGS
import{
strings
}
//function name upper or lower case can be styled by ide
//all substrings must use double quotation mark
strings.Contains(s, "substring") //bool
strings.Count(s, "substring") //int, count substring means can be multiple characters
strings.HasPrefix(s, "prefix") //bool
strings.HasSuffix(s, "subfix") //bool
strings.Index(s, "substring") //first index the substring begins
strings.Join([]string, "separator") //join the substring with separator
strings.Repeat(s, count) //strings a*count
strings.Replace(s, "old", "new", n) //replace the first n old with new
// if n>=count(old) || n<0, replace all
strings.Split(s, "separator")//separate the string with separator
strings.ToLower(s) // total change to lowercase
strings.ToUpper(s) // total change to uppercase
len(s)//size
- JSON
想要能通过json包序列化处理的struct的成员命名需要首字母大写,后续字母大小写没有影响。不满足首字母大写的成员会在处理中自动忽略。
import{
encoding/json
}
type userInfo struct {
Name string //ok
name string //ignore
Age int `json:"age"` //here to change to age: when output fields not Age
Hobby []string
}
buf, err := json.Marshal(a) //after marshal get []byte
string(buf) //need to force type conversion string to output fields
json.MarshalIndent(a, "prefix", "indent") //usually prefix := " ", indent := "\t"
/*
{
<prefix><indent>"a": 1,
<prefix><indent>"b": 2
<prefix>}
*/
json.Unmarshal(buf, &b)
- TIME
- STRCONV
- OS