Go基础语言|青训营笔记

70 阅读5分钟

Go基础语言|青训营笔记

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

1. 开发环境

go语言特点

  1. 高性能、高并发
  2. 丰富的标准库
  3. 完善的工具链
  4. 静态链接
  5. 快速编译
  6. 跨平台
  7. 垃圾回收

1.1 安装Golang

  1. go.dev
  2. studygolang.com/dl
  3. goproxy.cn/

1.2 选择集成开发环境

  1. vscode(需要安装go插件)
  2. goland

2. 基础语法

1.学习一门语言第一个程序输出helloworld

1. package

声明该文件所属的包,package main 程序的入口包

2. import

导入包

import(
    "fmt"
)

导入标准库"fmt"包,输入输出格式化字符串

3. func main()

main函数

func mian(){
    fmt.Println("hello world")
}

主函数,输出hello world

4.编译执行命令

  1. go run执行.go文件
  2. go build编译成二进制

2. 变量

func main() {
    var a = "initial"
    var b, c int = 1, 2
    var d = true
    var e float64
    f := float32(e)
    g := a + "foo"  
}

go的string是内置类型,可用加号连接用等号比较,var 变量名=变量值变量名:=变量值

3. 判断

if后面没有括号,if后面接大括号,语句从下一行起

if 7%2==0{
    fmt.Println("7 is even")
} else {
    fmt.Println("7 is odd")
}

4. 循环

for{
    //死循环
}
for i:=0;i<9;i++{
    //和C一样
}
i:=0
for i<=3{
    i=i+1
}

5. switch

a:=2//a可以是任何类型
switch a{
    case 1:
    //不需要写break
    case 2:
    //
    default:
    //其他情况
}

6. 数组

    var a [5]int
    a[4] = 100
    b := [5]int{1, 2, 3, 4, 5}
    var twoD [2][3]int
    fmt.Println("get:", a[2])
    fmt.Println("len:", len(a))
    for i := 0; i < 2; i++ {
        for j := 0; j < 3; j++ {
            twoD[i][j] = i + j
        }
    }

较少使用,主要使用切片

7. 切片

    s := make([]string, 3)
    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("get:", s[2])   // c
    fmt.Println("len:", len(s)) // 3
​
    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println(s) // [a b c d e f]
​
    c := make([]string, len(s))
    copy(c, s)
    fmt.Println(c) // [a b c d e f]
​
    fmt.Println(s[2:5]) // [c d e]
    fmt.Println(s[:5])  // [a b c d e]
    fmt.Println(s[2:])  // [c d e f]
​
    good := []string{"g", "o", "o", "d"}
    fmt.Println(good) // [g o o d]

切片可以理解为可变长度的数组,可以更改长度,使用make创建切片,可用append追加元素,返回新的切片,可以访问任意位置,任意区间内的元素

8. map

m:=make(map[string]int)
m["one"]=1
r,ok:=m["pow"]
m2 := map[string]int{"one": 1, "two": 2}

map完全无序,遍历及不按照字母顺序,也不按照插入顺序,delete(m,"one)删除该组元素

9. range

可快速遍历 slice或map

  1. 遍历slice时返回两个值,第一个值是索引,第二个值是该索引位置上的值
  2. 遍历map时候,返回的第一个值是key(键),第二个值是该键对应的值.
    for i, num := range nums {
        sum += num
        if num == 2 {
            fmt.Println("index:", i, "num:", num) // index: 0 num: 2
        }
    }
    for k, v := range m {
        fmt.Println(k, v) // b 8; a A
    }
    for k := range m {
        fmt.Println("key", k) // key a; key b
    }

10. 函数

golang函数支持返回多个值,参数类型后置,一般情况下,函数返回值中会有一个"错误"的返回值,判断该函数执行是否存在错误。

func exists(m map[string]string, k string) (v string, ok bool) {
    v, ok = m[k]
    return v, ok
}

11. 指针

指针的主要用途是对传入的参数进行修改

func add2(n int) {
    n += 2
}
func add2ptr(n *int) {
    *n += 2
}
func main() {
    n := 5
    add2(n)
    fmt.Println(n) // 5
    add2ptr(&n)
    fmt.Println(n) // 7
}

12. 结构体

带字段的集合,结构体作为参数的时候可以传指针,可以避免较大结构体在传参时进行拷贝的开销

package main
​
import "fmt"type user struct {
    name     string
    password string
}
​
func main() {
    a := user{name: "wang", password: "1024"}
    b := user{"wang", "1024"}
    c := user{name: "wang"}
    c.password = "1024"
    var d user
    d.name = "wang"
    d.password = "1024"
​
    fmt.Println(a, b, c, d)                 // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
    fmt.Println(checkPassword(a, "haha"))   // false
    fmt.Println(checkPassword2(&a, "haha")) // false
}
​
func checkPassword(u user, password string) bool {
    return u.password == password
}
​
func checkPassword2(u *user, password string) bool {
    return u.password == password
}
​

结构体函数,类似成员函数,*把func改为func (u user)或func (u user) ,传指针可对结构体进行修改

13. 错误处理

使用单独返回值进行错误信息,能很清晰知道哪里出现了错误,并且使用if else进行错误处理,在函数返回值类型加error类型,表示该函数会返回一个错误类型,如果出现错误,返回原本结果和错误信息,如果没有出现错误可返回原本结果和nil值,表示错误为空,也就是没有错误。在接收返回值有错误信息的函数时,需要用一个变量来单独接受错误信息,如果该变量不为空,则需进行错误处理,如果不需要错误信息可用下划线_来表示忽略错误信息的接收

func findUser(users []user, name string) (v *user, err error) {
    for _, u := range users {
        if u.name == name {
            return &u, nil
        }
    }
    return nil, errors.New("not found")
}
func main() {
    u, err := findUser([]user{{"wang", "1024"}}, "wang")
    if err != nil {
        fmt.Println(err)
        return
    }
    x, _ := findUser([]user{{"wang", "1024"}}, "wang")
}

14. 字符串操作

    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
    b := "你好"
    fmt.Println(len(b)) // 6

15. 字符串格式化

  1. %v任意格式都可以打印出来
  2. %+v字段名称和值
  3. %#v类型名称字段名称和值

16. JSON处理

已有一个结构体

  1. 字段首字母大写
  2. 字段类型后加 json:"age"可将json序列化后的字段名修改为小写age
  3. json.Marshal() 序列化结构体为十六进制编码(用string()强制转换即可)
  4. json.Unmarshal(序列化后的十六进制,空结构体变量) 反序列化

17. 时间处理

  1. time.Now()快速获取当前时间,具体操作见代码
  2. time.Date根据时区构造时间对象
  3. t.Sub(t1)求时间差
  4. t.Format("2006-01-02 15:04:05")解析时间格式
  5. t.Unix()获取时间戳

18. 字符串和数字之间转换

返回值有两个,一个为结果,一个为错误信息

  1. strconv.ParseInt("字符串",“进制/0是自动推测”,64)//64位整数
  2. strconv.Atoi("123")//快速将十进制字符串转换为数字

19. golang进程信息

  1. os.Args获取运行时参数
  2. os.Getenv("PATH")获取环境变量
  3. os.Setenv("AA","BB")写入环境变量
  4. exec.Command("grep","127.0.0.1","/etc/hosts").CombinedOutput()快速启动子进程并且获取输入输出

案例代码:GitHub - wangkechun/go-by-example