Golang

一.Windows安装

1.下载Golang

访问Go国内镜像站下载页面 https://golang.google.cn/dl/
并在页面最上方的版本中选择你当前的系统版本,会下载最新版本的Go开发包: 

2.安装Golang

访问官方安装介绍页面 https://golang.google.cn/doc/install
按照当前系统版本执行对应的安装流程即可。

3.系统环境配置

  • $GOROOT:go的安装目录,配置后不会再更改;C:\Program Files\Go

  • $GOPATH:go项目在本地的开发环境的的项目根路径(以便项目编译,go build, go install),不同的项目在编译的时候该环境变量可以不同;D:\go

  • $PATH:需要将go的bin目录添加到系统$PATH中以便方便使用go的相关命令,配置后也不会再更改;C:\Program Files\Go\bin

  • GOMOD和GOPROXY配置

    1
    2
    
    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.cn,direct
    

4.IDE开发环境安装

Goland下载安装及使用

  • go path 配置
  • go Module 配置:GOPROXY=https://goproxy.cn
  • go fmt 配置:Tools->File Watchers->add gofmt
  • IDE代码风格配置:Editor->Code Style->Go

二.Linux安装

1.安装Go

1
2
3
4
mkdir -p /data/tools && cd /data/tools
curl -R -O https://dl.google.com/go/go1.17.6.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf /data/tools/go1.17.6.linux-amd64.tar.gz
mkdir -p /root/go

2.添加执行命令至环境变量

1
2
3
4
5
6
7
vim /etc/profile
【内容】
export GOROOT=/usr/local/go
export GOPATH=/root/go
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin

source /etc/profile

3.GOMOD和GOPROXY配置

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

4.验证安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@node1 ~]# go version
go version go1.17.6 linux/amd64
[root@node1 ~]# go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.6"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1635051452=/tmp/go-build -gno-record-gcc-switches"

三.多版本golang安装

windows 和 linux 安装方法一致

1 安装第一个Golang版本

内容如上

2 安装第二个Golang版本

1
2
3
#按自己需求修改版本号,这里以1.17.6为例
go get golang.org/dl/go1.17.6
go1.17.6 download 

3 使用两个Golang版本

1
2
3
4
#第一个版本直接使用go就行
go version
#第二个版本使用go+版本号
go1.17.6 version

4 卸载第二个Golang版本

  • GOROOT删除第二个golang

    1
    
    "go get golang.org/dl/go1.17.6" 
    

    这个命令 会在你的家目录下面 生成一个 sdk/go1.17.6 文件,这个地方就是你的 go1.17.6 的 GOROOT

    删除 go1.17.6 即可

    1
    2
    3
    4
    5
    6
    
    [root@localhost sdk]# ll
    total 4
    drwxr-xr-x. 10 root 0 4096 Mar 21 05:41 go1.17.6
    [root@localhost sdk]# pwd
    /root/sdk
    [root@localhost sdk]# rm -rf /root/sdk/go1.17.6
    
  • GOBIN删除第二个golang

    使用go env查看GOBIN位置

    1
    
    [root@localhost bin]# go env
    

    然后删除你本机 GOBIN 里面的 go1.17.6 就可以

    1
    2
    3
    4
    5
    
    [root@localhost bin]# ls
    go  go1.17.6  gofmt
    [root@localhost bin]# pwd
    /root/go/bin
    [root@localhost bin]# rm -rf /root/go/bin/go1.17.6
    

四.Golang简记

网络编程

  • 1.物理层(设备,电脑链接网络,传送0和1的电信号)(双绞线,光纤,无线电波)
  • 2.数据链路层(网卡,以太网协议及广播,数据包及MAC寻址,ARP协议获取MAC地址)(以太网,网桥)
  • 3.网络层(网络地址,IP协议,IP寻找子网络&MAC寻找目标网卡)(IP,ARP,路由)
  • 4.传输层(UDP协议和TCP协议,端口确定网络程序)(TCP UDP)
  • 5.socket抽象层(BSD UNIX的进程通信机制,通常也称作”套接字”)
  • 6.应用层(规定应用程序使用的数据格式,TCP协议之上常见的Email、HTTP、FTP等协议)(HTTP,FTP,SMTP)

会话层 表达出 应用层

面向对象

接口

  • 只有当接口存储的类型和对象都为nil时,接口才等于nil
  • 接口也可实现类似OOP中的多态,一个类型可实现多个接口
  • 接口名:接口命名习惯以 er 结尾,如有写操作的接口叫Writer,有字符串功能的接口叫Stringer等
  • 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
  • 空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口
  • 类型断言:x.(T)

零碎知识点

  • 1.new() 与 make() 的区别

new(T) 和 make(T,args) 是 Go 语言内建函数,用来分配内存,但适用的类型不同。
new(T) 会为 T 类型的新值分配已置零的内存空间,并返回地址(指针),即类型为 *T 的值。换句话说就是,返回一个指针,该指针指向新分配的、类型为 T 的零值。适用于值类型,如数组、结构体等。
make(T,args) 返回初始化之后的 T 类型的值,这个值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用。make() 只适用于 slice、map 和 channel.

  • 2.异常的捕捉
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#recover在panic之前且在defer的函数内才可生效
defer func() {
      // recover() 复活 恢复
      // 会返回程序为什么挂了
      if err := recover(); err != nil {
         fmt.Println(err)
      }
   }()
// 自己抛
panic("半径不能为负")
  • 3.转换小写字母
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//转换成小写字母
func toLowerCase(str string) string {
    rune_arr := []rune(str)
    for i, _ := range rune_arr {
        if rune_arr[i] >= 65 && rune_arr[i] <= 90 {
            rune_arr[i] += 32
        }
    }
    return string(rune_arr)
}
  • 4.Golang 解决 golang.org/x/ 下包下载不下来的问题

由于众所周知的原因,golang在下载golang.org的包时会出现访问不了的情况。尤其是x包,很多库都依赖于它。由于x包在github上都有镜像,我们可以使用从github.com上把代码clone到创建的golang。org/x目录上就OK了

新人易犯58个错误

  • 1.左大括号 { 不能单独放一行
  • 2.未使用的变量:全局变量声明但不使用是可以的
  • 3.未使用的 import:可以使用 _下划线符号作为别名来忽略导入的包
  • 4.简短声明的变量只能在函数内部使用
  • 5.使用简短声明来重复声明变量
  • 6.不能使用简短声明来设置字段的值
  • 7.不小心覆盖了变量:短声明在函数中覆盖了全局变量
  • 8.显式类型的变量无法使用 nil 来初始化
  • 9.直接使用值为 nil 的 slice、map:需使用make分配内存
  • 10.map 容量:不能用 cap() 来检测分配空间的大小
  • 11.string 类型的变量值不能为 nil
  • 12.Array 类型的值作为函数参数:此时只是作为副本;如果需要修改原始数据,使用指针或切片
  • 13.range 遍历 slice 和 array 时混淆了返回值:第一个是元素索引,第二个是元素的值
  • 14.slice 和 array 其实是一维数据
  • 15.访问 map 中不存在的 key:检查返回的第二个参数即可
  • 16.string 类型的值是常量,不可更改:将 string 转为 rune slice(此时 1 个 rune 可能占多个 byte),直接更新 rune 中的字符
  • 17.string 与 byte slice 之间的转换
  • 18.string 与索引操作符:对字符串用索引访问返回的不是字符,而是一个 byte 值
  • 19.字符串并不都是 UTF8 文本:判断字符串是否是 UTF8 文本,可使用 “unicode/utf8” 包中的 ValidString() 函数
  • 20.字符串的长度:可使用 “unicode/utf8” 包中的 RuneCountInString
  • 21.在多行 array、slice、map 语句中缺少 , 号
  • 22.log.Fatal 和 log.Panic 不只是 log
  • 23.对内建数据结构的操作并不是同步的:goroutine 和 channel 是进行原子操作的好方法,或使用 “sync” 包中的锁。
  • 24.range 迭代 string 得到的值:应将 string 保存为 byte slice 再进行操作
  • 25.range 迭代 map:重新编译每次排序不一样
  • 26.switch 中的 fallthrough 语句:也可以改写 case 为多条件判断
  • 27.自增和自减运算:只作为运算符而非表达式
  • 28.按位取反:很多编程语言使用 ~ 作为一元按位取反(NOT)操作符,Go 使用 ^
  • 29.运算符的优先级:优先级另当别论
  • 30.不导出的 struct 字段无法被 encode:以小写字母开头的字段成员是无法被外部直接访问
  • 31.程序退出时还有 goroutine 在执行:使用 channel 关闭 goroutine
  • 32.向无缓冲的 channel 发送数据,只要 receiver 准备好了就会立刻返回
  • 33.向已关闭的 channel 发送数据会造成 panic
  • 34.使用了值为 nil 的 channel
  • 35.若函数 receiver 传参是传值方式,则无法修改参数的原有值
  • 36.关闭 HTTP 的响应体:新手很容易忘记手动关闭,或者写在了错误的位置
  • 37.关闭 HTTP 连接
  • 38.将 JSON 中的数字解码为 interface 类型
  • 39.struct、array、slice 和 map 的值比较
  • 40.从 panic 中恢复
  • 41.在 range 迭代 slice、array、map 时通过更新引用来更新元素
  • 42.slice 中隐藏的数据:新 slice 会引用原 slice 的底层数组
  • 43.Slice 中数据的误用:重新分配新的 slice 并拷贝你需要的数据
  • 44.旧 slice:二者的数据指向相同的底层数组
  • 45.类型声明与方法
  • 46.跳出 for-switch 和 for-select 代码块
  • 47.for 语句中的迭代变量与闭包函数
  • 48.defer 函数的参数值
  • 49.defer 函数的执行时机
  • 50.失败的类型断言:断言失败则会返回目标类型的“零值”,断言变量与原来变量混用可能出现异常情况
  • 51.阻塞的 gorutinue 与资源泄露
  • 52.使用指针作为方法的 receiver:map 类型的元素、通过 interface 引用的变量不可寻址
  • 53.更新 map 字段的值:因为 map 中的元素是不可寻址的。需区分开的是,slice 的元素可寻址
  • 54.nil interface 和 nil interface 值:interface 类型的变量只有在类型和值均为 nil 时才为 nil
  • 55.堆栈变量:你并不总是清楚你的变量是分配到了堆还是栈
  • 56.GOMAXPROCS、Concurrency(并发)and Parallelism(并行):GOMAXPROCS 可以超过执行 goroutine 的 CPU 核心数
  • 57.读写操作(goroutine 中操作)的重新排序:以使用 channel 或 sync 包中的锁机制来固定输出排序
  • 58.优先调度:可以使用 runtime 包中的 Gosched() 来 手动启动调度器