- 01 为什么要学习Go
- 02 课上所用物料介绍
- 03 安装Go开发包
- 04 配置GOPATH
- 05 Go项目目录结构介绍
- 06 安装VSCode编辑器
- 07 编写第一个Go语言程序
- 08 变量声明
- 09 变量赋值
- 10 常量和iota
- 11 整型
- 12 浮点型复数和布尔值
- 13 fmt总结5
- 14 字符串操作
- 15 字符串修改及类型转换
- 16 if判断和for循环
- 01内容回顾
- 02switch和goto
- 03运算符
- 04数组
- 05数组练习题
- 06切片1
- 07切片的本质
- 08append和copy
- 09append再补充
- 10指针和make及new
- 11map
- 12函数
- 01今日内容概要
- 02内容回顾_运算符和数组
- 03内容回顾_切片
- 04内容回顾_map
- 05作业1_字符统计
- 06作业2_回文判断
- 07函数定义和defer
- 08作用域
- 09函数类型作为参数和返回值
- 10闭包
- 11闭包
- 12defer再讲解
- 13内置函数
- 14fmt标准库介绍
- 15本周作业介绍
- 01-今日内容概要
- 02内容回顾
- 03分金币作业
- 04递归
- 05自定义类型和类型别名
- 06结构体初识
- 07匿名结构体
- 08结构体指针和结构体初始化
- 09结构体和初始化
- 10方法和接收者
- 11值接收者和指针接收者的区别
- 12那些你遇到的问题呀
- 13函数版学生管理系统
- 14结构体的匿名字段结构体嵌套等
- 15结构体模拟实现继承
- 16结构体与JSON
- 01 结构体内容回顾01
- 02 结构体内容回顾02
- 03 结构体版学生管理系统
- 04 今日内容
- 05 初识接口类型
- 06接口的定义与实现
- 07指针接收者实现接口和值接收者实现接口的区别
- 08实现多个接口和接口嵌套
- 09空接口
- 10package相关
- 11为什么要有日志库作业
- 12打开文件读内容
- 13文件写入
- 14使用bufio获取用户输入
- 15日志库作业需求
- 01-今日内容
- 02-内容回顾
- 03在文件中间插入内容
- 04time包
- 05time包补充
- 06日志库需求分析
- 07日志库简单实现
- 08runtime.Caller
- 09记录日志时支持格式化输出
- 10实现往文件里记录日志
- 11日志文件切割
- 12日志库补充
- 13反射及附加题作业需求
- 01、今日内容
- 02、内容回顾
- 03ini配置文件解析1
- 04ini配置文件解析2
- 05strconv标准库介绍
- 06并发编程介绍
- 07创建goroutine
- 08sync.WaitGroup
- 09goroutine调度模型GMP
- 10channel初识
- 11channel练习
- 12单向通道
- 13work_pool练习
- 14select介绍
- 15作业要求
- 01今日内容
- 02内容回顾
- 03几个作业的问题
- 04异步写日志
- 05互斥锁
- 06读写互斥锁
- 07sync.Once示例
- 08sync.Map示例
- 09atomic原子性操作
- 10互联网协议介绍
- 11TCP服务端客户端开发
- 12解决粘包问题
- 13UDP客户端服务端
- 01今日分享
- 02今日内容概要
- 03内容回顾01
- 04内容回顾02
- 05http_server端
- 06http_client
- 07单元测试
- 08测试组和子测试
- 09性能基准测试
- 10性能优化简介
- 11flag包用法
- 12pprof性能调优简介
- 01今日分享面试题
- 02 内容回顾
- 03今日内容
- 04MySQL介绍
- 05使用Go语言连接MySQL
- 06查询单条记录
- 07查询多条记录
- 08插入更新和删除操作
- 09MySQL预处理
- 10MySQL事务操作
- 11sqlx的使用
- 12sql注入演示
- 13redis示例
- 14消息队列介绍
- 15nsq使用
- 01刷leetcode做题
- 02-今日内容
- 03上周作业思路
- 04go module简单介绍
- 05context初识
- 06context内容介绍
- 07上午内容复习
- 08.日志收集项目架构
- 09kafka介绍
- 10kafka启动
- 11zookeeper工作机制
- 12tail模块介绍及使用
- 13sarama模块介绍及使用
- 14logAgent实现
- 15配置文件版LogAgent
- 01~内容回顾
- 02~今日内容概要
- 03etcd介绍
- 04etcd搭建
- 05etcd操作
- 06logagent从etcd加载收集项配置
- 07logagent上午内容回顾
- 08logagent根据etcd的配置创建多个tailtask
- 09logagent实现watch新配置
- 10logagent实现新增收集任务
- 11logagent删除新配置中没有的那个任务
- 12logagent根据IP拉取自己的配置
- 01内容回顾
- 02今日内容
- 03ES介绍
- 04ES搭建及常见API示例
- 05go操作ES
- 06kafka消费示例
- 07Kibana搭建及使用
- 08logtransfer实现
- 09logstransfer优化
- 10prometheus和grafana介绍
- 11项目总结
- 01.gin的介绍
- 02.gin请求
- 03.gin路由
- 04.数据解析和绑定
- 05.gin各种渲染
- 06.重定向
- 07.中间件
- 08.中间件练习
- 09.cookie和session
- 10.中间件设计
- 11.练习
- 01.作业
- 02.内存session完成
- 03.中间库的完成
- 04.博客数据库分析
- 05.项目搭建
- 06.文章的dao实现
- 07.主页的service层
- 08.主页功能的实现和调bug
- 01.复 习
- 02.raft算法动画
- 03.raft选主实现
- 04.raft选举完成
- 05.raft分布式选举
- 06.选项设计模式
- 07.注册组件的分析
- 08.注册组件接口实现
- 09.服务组件上层架构
- 10.一个s惹的祸
- 01.面试题
- 02.服务发现的原理
- 03.gRPC
- 04.gRPC客户端服务端
- 05.go-micro介绍
- 06.go-micro HelloWorld
- 07.go-micro案例
- 08.项目搭建
- 09.go-micro项目
- 01.docker介绍
- 02.image介绍
- 03.docker image
- 04.docker container
- 05.Dockerfile语法
- 06.分享dockerImage
- 07.创建私有仓库
- 08.dockerFile案例
- 09.dockerfile案例2
- 10.docker总结
- 01.namespace命名空间
- 02.容器端口映射
- 03.多机多容器的部署
- 04.etcd和集群网络
- 05.mysql镜像
- 06.容器数据持久化
- 07.wordpress
- 08.docker-compose
- 09.复杂应用部署
- 10.docker集群
- 01.面试题1
- 02.面试题2
- 03.面试题3
- 04.面试题4
- 01.课程介绍
- 02.docker介绍
- 03.docker安装
- 04.image
- 05.创建image的方式
- 06.Dockerfile详解
- 07.搭建私有docker仓库
- 08.Dockerfile案例
- 01.docker案例
- 02.namespace
- 03.docker网络
- 04.etcd存储和overlay网络
- 05.docker数据持久化的两种方案
- 06.docker-compose引入
- 01.docker-compose安装和使用
- 02.容器扩展和负载均衡
- 03.复杂应用部署
- 04.swarm集群扩展
- 05.dockerStack的使用
- 06.dockerCloud
- 01昨日回顾
- 02.Kubernetes简介
- 02Kubernetes集群搭建之准备工作
- 03Kubernetes集群搭建之安装etcd
- 04Kubernetes集群搭建之kube-apiserver服务安装
- 05Kubernetes集群搭建之kube-scheduler-服務安裝
- 06Kubernetes集群搭建之kube-controller-服務安裝
- 07Kubernetes集群搭建之flannel服务安装1
- 08Kubernetes集群安装之flannel服务安装2
- 09Kubernetes集群安装之flannel服务安装3
- 10Kubernetes集群安装之kubelet1
- 11Kubernetes集群安装之kubelet2
- 12kubernetes集群搭建之kube-proxy
- 01 昨日内容回顾
- 02kubernetes命令式快速创建应用
- 03应用副本的动态伸缩
- 04应用的版本升级与回滚
- 05pod介绍
- 06exec探针
- 07http探针
- 08控制器简介
- 09ReplicaSet
- 10创建Deployment
- 11Deployment更新升级
- 12Deployment扩容
一 简介
Go语言出自Ken Thompson、Rob Pike和Robert Griesemer之手,起源于2007年,并在2009年正式对外发布,其实都是Google的,设计Go语言的初衷都是为了满足Google的需求。Go的主要目标是“兼具Python等动态语言的开发速度和C/C++等编译型语言的性能与安全性”,旨在不损失应用程序性能的情况下降低代码的复杂性,具有“部署简单、并发性好、语言设计良好、执行性能好”等优势。最主要还是为了并发而生,并发是基于goroutine的,goroutine类似于线程,但并非线程,可以将goroutine理解为一种虚拟线程。Go语言运行时会参与调度goroutine,并将goroutine合理地分配到每个CPU中,最大限度地使用CPU性能。
二 环境
我们玩Java的时候需要下载JDK,类似于此,用Go开发也需要下载Go,里面提供各种develop-kit、library以及编译器。在官网下载mac版本pkg后直接安装,最后用 go version 命令验证版本:
然后就是设置这两个环境变量,mac系统是在 .bash_profile 文件里面:
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
GOROOT:表示的是Go语言编译、工具、标准库等的安装路径,其实就相当于配置JAVA_HOME那样。
GOPATH:这个和Java有点不一样,Java里并不需要设置这个变量,这个表示Go的工作目录,是全局的,当执行Go命令的时候会依赖这个目录,相当于一个全局的workspace。一般还会把$GOPATH/bin设置到PATH目录,这样编译过的代码就可以直接执行了。
1 纯文本开发
编写代码,可以保存在任意地方,例如新建一个helloworld目录,创建hello.go文件:
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
然后执行 go build hello.go 就可以编译出hello文件,在./hello就可以执行了;或者直接 go run hello.go 合二为一去执行。执行这个命令并不需要设置环境变量就可以了。看起来和c差不多,但是和Java不一样,运行的时候不需要虚拟机。早期的GO工程也是使用Makefile来编译,后来有了强大的命令 go build、go run,可以直接识别目录还是文件。
2 GoLand
自动import,超爽的体验!不用按command + /了!
运行项目需要设置build config,和Android、Java的都差不多,例如创建一个hello-goland项目:
导入go module项目的时候需要勾选这项,否则无法像maven/gradle那样sync下载依赖:
3 VSCODE
直接搜索Go插件,第一个最多安装量的就是了,我还没用过所以不太清楚如何。
三 工程结构
在设置GOPATH环境变量的时候,这个目录里面又分了三个子目录bin、pkg、src,分别用于存放可执行文件、包文件和源码文件。当我们执行Go命令的时候,如果我们指定的不是当前目录的文件或者绝对路径的目录的话,就会去GOPATH目录的去找。这样在GOPATH目录创建了xxx的目录后,就可以在任意地方执行 go build xx 命令来构建或者运行了。
pkg目录应该是在执行 go install 后生成的包文件,包括.a这样的文件,相当于一个归档。
├── bin
│ ├── air
│ ├── govendor
│ ├── swag
│ └── wire
├── pkg
│ ├── darwin_amd64
│ ├── mod
│ └── sumdb
└── src
├── calc
├── gin-blog
├── github.com
├── golang.org
├── google.golang.org
├── gopkg.in
└── simplemath
这样对于我们具体项目来说并不好,没有Workspace的概念来隔离每个项目了,所以我觉得这个GOPATH目录放的应该是公用的项目,例如开源依赖的。我们在开发过程中,也会下载很多的依赖,这些依赖都下载到这个目录,和我们的项目文件混在一起了。
另外,通过IDE可以设置project的GOPATH,相当于在执行的时候给GOPATH增加了一个目录变量,也就是说,我们创建一个项目,然后里面也有bin、src、pkg这三个目录,和GOPATH一样的,本质上,IDE在运行的时候其实就是设置了一下GOPATH:
GOPATH=/Users/fuxing/develop/testgo/calc-outside:/Users/fuxing/develop/go #gosetup
Go语言在寻找变量、函数、类属性及方法的时候,会先查看GOPATH这个系统环境变量,然后根据该变量配置的路径列表依次去对应路径下的src目录下根据包名查找对应的目录,如果对应目录存在,则再到该目录下查找对应的变量、函数、类属性和方法。
其实官方提供了Go Modules的方法更好解决。
1 Go Modules
从Go 1.11版本开始,官方提供了Go Modules管理项目和依赖,从1.13版本开始,更是默认开启了对Go Modules的支持,使用Go Modules的好处是显而易见的 —— 不需要再依赖GOPATH,你可以在任何位置创建Go项目,并且在国内,可以通过 GOPROXY 配置镜像源加速依赖包的下载。也就是说,创建一个项目就是一个mod,基本上目前Go开源项目都是这样做的。其实就是类似于Maven和Gradle。
// 创建mod项目,也是可以用IDE来new一个mod项目的:
go mod init calc-mod
// 一般开源在github上面的项目名字是这样的;和maven、gradle不一样的是,开发完成根本不需要发布到仓库!只要提交代码后打tag就可以了
go mod init github.com/fuxing-repo/fuxing-module-name
// 创建一个模块:执行这个命令主要是多了一个go.mod文件,里面就一行内容:
module calc-mod
// import以后,执行下载依赖命令,不需要编辑go.mod文件。依赖会下载到GOPATH/pkg/mod目录
go list
用GoLand来打开不同的项目,显示依赖的外部库是不一样的,如果是用GOPATH创建的项目,需要用命令下载依赖包到GOPATH:
go get -u github.com/fuxing-repo/fuxing-module-name
四 语法
1 包:Package 和 Import
Java里面的包名一般是很长的,和文件夹名称对应,作用就是命名空间,引入的时候需要写长长的一串,也可以用通配符:
Go里面一般的包名是当前的文件夹名称,同一个项目里面,可以存在同样的包名,如果同时都需要引用同样包名的时候,就可以用alias区分,类似于JS那样。一般import的是一个包,不像Java那样import具体的类。同一个包内,不同文件,但是里面的东西是可以使用的,不需要import。这有点类似于C的include吧。如果多行的话,用括号换行包起来。
Go语言中,无论是变量、函数还是类属性及方法,它们的可见性都是与包相关联的,而不是类似Java那样,类属性和方法的可见性封装在对应的类中,然后通过 private、protected 和 public 这些关键字来描述其可见性,Go语言没有这些关键字,和变量和函数一样,对应Go语言的自定义类来说,属性和方法的可见性根据其首字母大小写来决定,如果属性名或方法名首字母大写,则可以在其他包中直接访问这些属性和方法,否则只能在包内访问,所以Go语言中的可见性都是包一级的,而不是类一级的。
在Java里面,只有静态,或者对象就可以使用点运算符,而且是极其常用的操作,而在Go里面,还可以用一个包名来点,这就是结合了import来使用,可以点出一个函数调用,也可以点出一个结构体,一个接口。另外区别于C,不管是指针地址,还是对象引用,都是用点运算符,不需要考虑用点还是箭头了!