走进go语言基础 | 青训营笔记

92 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第1天

1.本堂课重点内容

  • 介绍了go语言的特性
  • go语言基础语法及标准库

2.具体案例

3.go语言的特性

  1. 高性能、高并发
  2. 语法简单、学习曲线平缓
  3. 丰富的标准库
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收

4.go语言基础语法及标准库

4.1 变量&常量
var name = value   //自动推导变量类型
var name type = value //自己定义类型
name := value   //声名并且赋值  会自动推导变量类型
const name = value //常量的定义   无确定类型,根据上下文自动确定类型
const name type = value
4.2 判断语句

go语言中if的用法和c/c++/java都很类似,只是if后面不用加括号,但是if语句必须跟大括号,不能像c/c++/java一样省略。

if bool {
    语句
} else {
    语句
}
//特殊写法
//通过变量得到一个value值然后再根据变量值进行判断
if name := value; name != nill {
    语句
} 
4.3 循环语句

没有while循环和do while循环只有唯一的for循环 并且省略了for循环的括号

//死循环 类比 while(true)
for {
    语句
}

//类比while条件判断循环
for i <= 3 {
    语句
}

// 类比c的for循环 将初始化变量 int n = 0 变为 n := 0 省略括号
for n := 0 ; n < 5 ; n ++ {
    语句
}
4.4 switch语句

switch后面不需要括号, 并且不需要break, 像c/c++/java;结束一个case语句都需要break,防止往下走。在switch后可以不加条件,直接case判断

switch 变量 {
    case 1:
        语句
    case 2:
        语句
    default:
        语句
}
//特殊用法  可以用作多个if判断
switch {
    case bool:
        语句
    case bool:
        语句
    default:
        语句
}
4.5 数组
var name [len]type  //数组的定义
name := [len]type{...}  //初始化
var name [len][len]type  //二维数组的定义
4.6 切片

切片就是一个可变长度的数组

name := make([]type, len)   //切片的定义
name[0] = value             //赋值
name = append(name, value)  //追加元素
copy(name1, name)     //把name复制给name1
name[begin:end]    // 切片操作
name[begin:]
name[:end]
4.7 map
name := make(map[key type]value type)
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
len(m) 获取 map 的长度
delete(m, key)  //删除指定键值对
4.8 range
nums := []int{2, 3, 4}
//遍历数组 i代表下标, num代表值 
for i, num := range nums {
    语句
}
如果不需要下标或者值可以用_标识如
for i, _ := rangs nums{
    语句
}
m := map[string]string{"a":"A", "b":"B"}
k为键,v为值
for k, v := range m {
    语句
}
4.9 函数

与c/c++/java 不一样的是可以返回多个值,类型后置

//go函数的定义 type1是传入参数的类型 type2为返回值类型
func name(value type1) type2 {
    语句
}
//多返回值
func name(value type1) (name type, name type){
    语句
}
4.10 指针
//这个方法并不会改变n的值
func add2(n int){
    n += 2
}
//这个方法会改变n的值 使用时 add2ptr(&n)
func add2ptr(n *int){
    *n += 2
}
4.11 结构体

结构体是带类型字段的集合

//结构体的定义
type name struct{
  //名称   类型
    name1 type
    name2 type
}

//使用
a := name{name1:".", name2:".."} //初始化
a.name1 = "xxx"
var d name   //变量的声名
4.12 结构体方法

类似其他语言的类成员函数

type user struct {
    name string
    password string
}

//结构体方法
func (u user) checkPassword(password string) bool {
    return u.password == password
}

//指针形式
func (u *user) resetPassword(password string) {
    u.password = password
}
4.13 错误处理

使用一个单独的返回值来传递错误信息,可以很清晰的知道哪个函数返回了错误

func name(value type) (value type, err error){
    语句
    return value, errors.New("错误")  //没有错误可以返回nil
}
4.14 字符串操作
a := hello
strings.Contains(a, "ll")  //字符串中是否包含某个子串
strings.Count(a, "l") //计算某个字符串出现的次数
fmt.Println(strings.HasPrefix(a, "he"))  //是否有前缀“he”
fmt.Println(strings.HasSuffix(a, "llo")) //是否有后缀“llo”
fmt.Println(strings.Index(a, "ll"))  //查找某个字符串出现的位置
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) //连接多个字符串变为  he-llo
fmt.Println(strings.Repeat(a, 2))  //重复某个字符串多少次
fmt.Println(strings.Replace(a, "e", "E", -1)) //替换字符e为E
fmt.Println(strings.Split("a-b-c", "-")) //切割a-b-c把-切掉
fmt.Println(strings.ToLower(a))  //全变小写
fmt.Println(strings.ToUpper(a))  //全变大写
4.15 字符串格式化
fmt.printf   类似c printf
%v //可以打印任意类型
%+v //得到更详细的结果
%#v //进一步详细
4.16 JSON处理
//把一个结构体转换为一个json格式
json, err = json.Marshal(结构体)
//使用unmarshal可以返序列化到一个结构体
json.Unmarshal(json, &结构体)
4.17 时间处理

主要使用的是time类

// 获取当前时间
now := time.Now()
// 构造一个带时区的时间
t := time.Date(年, 月, 日, 时, 分, 秒, 纳秒, 时区)
t.Year 获取年
t.Month 获取月
t.Day 获取日
t.Hour 获取时
t.Minute 获取分
//时间戳
now.Unix
4.18 数字解析

主要使用strconv库

//把字符串转换为64位精度的浮点数
strconv.ParseFloat("1.234", 64)
//把字符串转换成10进制64位精度的整数
strconv.ParseInt("111", 10, 64)
//使用atoi快速把字符串转成10进制数字
strconv.Atoi("123")
4.19 进程信息
os.Args //获取运行时的参数 如go run main.go a, b, c, d 第一个参数为二进制自身的目录加名字 剩下的则为 a, b, c, d
//获取或写入环境变量
os.Getenv("PATH")
os.Setenv("AA", "BB")
//快速启动子进程并获取其输入输出
exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()