Go 语言快速上手-基础语言(1)| 青训营笔记

173 阅读7分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。

一、简介

1.1 什么是Go语言

1.高性能、高并发

Go语言有和C++,Java媲美的性能,并且原生支持高并发

2.语法简单、学习曲线平缓 语法风格基于C语言进行大幅度的简化, 上手简单,学习期短

下面是一个简单的高并发Http服务器:

package main 

import { 
    "net/http" 
} 

func main() { 
    http.Handle("/",http.FileServer(http.Dir("."))) 
    http.ListenAndServe(":8080", nil) 
}

3.丰富的标准库

有大量功能丰富,质量完善的标准库,降低学习成本。标准库有很高的稳定性和兼容性。

4.完善的工具链

Go 语言自带 编译、代码格式化、错误检查、帮助文档、包管理、代码补充提示、单元测试框架等工具链

5.静态链接

Go 语言的编译结果默认都是静态链接的,编译出的可执行文件不需要附件任何东西即可部署运行,部署方便快捷,镜像体积小。

6.快速编译

编译速度远超C++

7.跨平台

能在Linux、Windows、MacOS等系统运行,能用来开发Android、iOS的软件,还能在路由器、树莓派等设备运行。有方便的交叉编译特性,在笔记本上编写的 Go 语言可执行文件可以直接在路由器上运行而无需配置交叉编译环境。

8.垃圾回收

自带垃圾回收功能,与Java一样。写代码时无需考虑内存的分配和释放。

1.2 为什么全面拥抱Go语言

  • 最初使用Python,由于性能问题换成了Go
  • C++不太适合在线 web 业务
  • 早期团队非Java背景
  • 性能比较好
  • 部署简单、学习成本低
  • 内部RPC和HTTP框架的推广

二、入门

2.1 变量

go语言是一门强类型语言,每一个变量都有它自己的变量类型。

常见的变量类型包括 字符串 整数 浮点型、布尔型等。

go 语言的字符串是内置类型,可以直接通过加号拼接,也能够直接用等于号去比较两个字符串。

在go语言里面,大部分运算符的使用和优先级都和 C 或者 C++ 类似,这里就不再概述。

下面讲述go语言里面的变量的声明,在go语言里面变量的声明有两种方式,一种是通过var name string = "" 这种方式来声明变量,声明变量的时候,一般会自动去推导变量的类型。如果有需要,你也可以显示写出变量类型。

常量的是把 var 改成const.

go语言里面的常量没有确定的类型,会根据使用的上下文来自动确定类型。

2.2 分支与循环

package main

import "fmt"

func main() {
   var a=2
   switch {
   case a<2:
      fmt.Println("a<2")
   default:
      fmt.Println("a>=2")
   }
}

if else后的表达式不需要小括号,但必须要跟着一个花括号 if { } 像上面这样的格式 只有for循环,没有while do while

golang的swithch可以不加表达式而直接像if else的使用方式一样

golang中的switch不需要break,执行完一个分支就会自动break

2.3 数组与切片

go的数组定义方式是var 数组名[]数组元素类型,数组的读写与c语言等是一致的,下标都是从0开始

切片是一个动态的数组,可以用make来创建,用append来对数组进行拼接,但是append需要把值重新赋值给原切片,也可以直接用:=来创建

package main

import "fmt"

func main() {

    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]
}

对于一个数组,可以很方便地取特定索引的值或者往特定索引取存储值,然后也能够直接去打印一个数组。不过,在真实业务代码里面,我们很少直接使用数组,因为它长度是固定的,我们用的更多的是切片。

2.4 map

map在其他编程语言里面,被叫做哈希或者字典。 map 是实际使用过程中最频繁用到的数据结构。

我们可以用 make 来创建一个空 map ,这里会需要两个类型,第一个是 key 的类型,这里是 string;另一个是 value 的类型,这里是 int 。 我们可以从里面去存储或者取出键值对。可以用 delete 从里面删除键值对。

golang的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序

package main

import "fmt"

func main() {
    m := make(map[string]int)
    m["one"] = 1
    m["two"] = 2
    fmt.Println(m)           // map[one:1 two:2]
    fmt.Println(len(m))      // 2
    fmt.Println(m["one"])    // 1
    fmt.Println(m["unknow"]) // 0

    r, ok := m["unknow"]
    fmt.Println(r, ok) // 0 false

    delete(m, "one")

    m2 := map[string]int{"one": 1, "two": 2}
    var m3 = map[string]int{"one": 1, "two": 2}
    fmt.Println(m2, m3)
}

2.5 range

对于一个 slice 或者一个 map 的话,我们可以用 range 来快速遍历,这样代码能够更加简洁。

range 遍历的时候,对于数组会返回两个值,第一个是索引,第二个是对应位置的值。如果我们不需要索引的话,我们可以用下划线来忽略。

2.6 函数

Golang 和其他很多语言不一样的是,变量类型是后置的。

Golang 里面的函数原生支持返回多个值。在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息。

2.7 结构体

结构体是带类型的字段的集合。我们可以用结构体的名称去初始化一个结构体变量,构造的时候需要传入每个字段的初始值。也可以用这种键值对的方式去指定初始值,这样可以只对一部分字段进行初始化。

结构体支持指针,这样能够实现对于结构体的修改,也可以在某些情况下避免一些大结构体的拷贝开销。

2.8 字符串

Go 语言在标准库 strings 包里面有很多常用的字符串工具函数,比如 contains 判断一个字符串里面是否有包含另一个字符串, count 字符串计数, index 查找某个字符串的位置, join 连接多个字符串, repeat 重复多个字符串, replace 替换字符串,需要时可以查询文档来使用。

package main

import "fmt"

type point struct {
    x, y int
}

func main() {
    s := "hello"
    n := 123
    p := point{1, 2}
    fmt.Println(s, n) // hello 123
    fmt.Println(p)    // {1 2}

    fmt.Printf("s=%v\n", s)  // s=hello
    fmt.Printf("n=%v\n", n)  // n=123
    fmt.Printf("p=%v\n", p)  // p={1 2}
    fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
    fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

    f := 3.141592653
    fmt.Println(f)          // 3.141592653
    fmt.Printf("%.2f\n", f) // 3.14
}

可以直接%v可以打印元素类型,可以用%+v进一步打印,也可以用%#v进行更近一步的打印,也可以用%f等具体的格式化符

2.9 时间库

在 go 语言里面最常用的就是time.now()来获取当前时间,你也可以用time.date去构造一个带时区的时间,构造完的时间可以用.Year()等方法获取这个时间点的 年、月、日、时、分、秒等信息。可以用.sub()去对两个时间进行减法,得到一个时间段,时间段又可以去得到它有多少小时,多少分钟、多少秒。

在和某些系统交互的时候,我们经常会用到时间戳。可以用 .UNIX 来获取时间戳。

可以用time.Format或者time.Parse去格式化一个时间。