学习go的安装环境和基本配置还有基础知识
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。
一、go安装和环境配置
1. 安装
方式一:软件包安装
进入官网:https://go.dev/dl/,选择自己的电脑系统,下载软件包安装
方式二: Mac电脑中使用brew
terminal
brew install go
windows略
2. 查看和配置环境
terminal
// 查看go的环境配置变量,主要看GOPATH、GOROOT、GOBIN
go env
// 如果不想使用默认的GOPATH配置路径,可自行设置GOPATH
go env -w GOPATH=xxxx // xxxx为路径,比如/usr/local/go
// GOBIN也需要设置一下,使用GOPATH路径下的bin目录即可
- src // 这里面存放我们自己编写的go项目,往往以域名为文件夹名,然后以项目名作为二级文件夹名
比如:src/baidu.com/baidu_cloud(baidu.com为域名,下面有一个baidu_cloud的工程项目) - pkg // 见后面介绍
- bin // 见后面介绍
3. 修改go镜像
由于墙,国内推荐使用七牛云的镜像服务,查看其官网指南:https://goproxy.cn/

4. 代码编辑器IDE
对于go,官方IDE是goland,可以到官网下载:官网IDE下载
我个人推荐使用vscode,在vscode中安装使用几个好用的扩展:

二、go程序基本框架
1. GOPATH解释
1.src文件夹:存放源码;
2.bin文件夹:存编译出的产物;
3.pkg文件夹:存缓存的库。
- 应该放在GOPATH指向的目录
terminal
// 查看GOPATH指向的目录位置
go env | grep GOPATH
-
补充
GOROOT:go编译源码根目录;
GOPATH: go工程的根目录;GOPATH下应该要有src、bin、pkg这3个文件夹(没有的话可以新建这几个文件夹),编写的工程代码需放在src中,比如go项目工程go_test,目录应该如: $GOPATH/src/go_test。
GOBIN: go工程的bin目录,存放二进制可执行文件; -
每一个go文件,都以go为扩展名;
-
go文件中都有一个包名,作为命名空间:
test.go
pacakage main
func main() {
}
2. 代码工程 & mod
- 程序的入口文件都是main.go
- 然后可以新建其他的文件夹,比如controller、model、services、utils等
- 初始化mod,mod中有我们自己项目中所需引入的库,类似于依赖配置文件。
打开命令行终端,进入在main.go同级目录,执行以下命令:
terminal
go mod init baidu_cloud //这里以baidu_cloud为工程名字作为示例
- 生成mod文件后,之后基本不用管mod
3. 引入包
xxx.go
import "fmt" // 在go文件中引入标准库
当需要引入其他框架时,比如gorm框架,需要在项目根目录,即mod所在目录下,执行终端命令:
terminal
go get -u gorm.io/gorm
执行命令成功后,mod文件中会自动引入这个库版本等信息,工程中就可以直接引用使用。
其他go框架,参照其对应的github使用方式即可。
4. go常用命令
terminal
go run xxx.go // 编译运行某个文件
go run *.go // 所有go文件
go build -o xxx.exe xxx.go // 编译成windows上的程序
go env // 查看go的环境配置信息
go env -w GOPATH=/usr/local/go // 修改env中某个配置变量的值,这里以GOPATH为示例
三、基本语法
- 变量声明:
xxx.go
// 自动类型推断
name := "自动类型推断,所有语句不需要分号结尾"
age := 14
list := [10]int{1, 2, 3}; // 固定长度数组
arr := []int{}; // 可变长度数组
// 先声明,后赋值
var nickname: string
nickname = "可以声明了再赋值"
// 声明多个并赋值
name, age := "姓名", 14
// 可以不用加小括号
// 大括号的 { 要紧跟在代码行右侧,再换行写大括号中的代码
con := 4
if con > 3 {
fmt.println("true")
}
// 数字变量,只有后置运算符,没有c语言中的前置运算符
iterator := 1 // 声明了一个1
iterator++ // 这行必须单独一行,不能放在if或者其他代码行中
++iterator // 会报错
- 数组
xxx.go
list := []str{"元素1", "元素2"}
// 获取数组长度
fmt.printf("数组长度:%d", len(list))
// 第一种常规循环
for i:=0; i<len(); i++ {
}
// 第二种循环 for - range
for key, value := range list {
fmt.printf("数组长度:%c", key, ", 值是:%c", value)
}
// 如果要忽略其中某一个值,使用_下划线代替即可
for _, value := range list {
fmt.printf("值是:%c", value)
}
- 数组的length和capacity(长度len和容量cap)
xxx.go
list := []int{1, 2}
println("长度是:", len(list)) // 2
println("容量是:", cap(list)) // 2
// 数组添加
list = append(list, [3, 4, 5])
fmt.println("长度是:", len(list)) // 4
fmt.println("容量是:", cap(list)) // 8
当数组新增加的数量,超过初始容量时,可变数组的容量会增加为初始容量的2倍,当容量越来越大时,可能到不了2倍
- 数组切片
xxx.go
list := []int{1, 2, 3, 4}
sliceList = list[0:2] // 取list的第0位到第2位的元素,半闭合数组 0<= slice <2
sliceList2 = list[:4] // 默认为 0 <= ... <4
sliceList2 = list[2:] // 默认为 2 <= ...
// warning:当修改切片中的某一个数据时,会影响到原数组。
// 想要切片独立于原数组,那么需要使用copy函数
welString := "hello world"[6:]
for i:=0; i<len(welString); i++ {
}
copy操作:
xxx.go
list := []int{1, 2, 3, 4}
list_copy := make([]int, len(list))
copy(list_copy, list[:]) // 表示把list全长的切片,拷贝到list_copy,
// 因为copy函数第二位要求是切片类型
make创建指定length和capacity的切片:
xxx.go
str := make([]string, 10, 15) // 创建一个默认长度为10,容量为15的切片,
// 15所代表的第3个形参不是必须填写的,如果没写cap,默认和len一样
- 函数声明
xxx.go
// 不带返回值
func main() {
}
// 带返回值
func doSomething() string {
return "返回值是xxxxx"
}
- 指针
xxx.go
// 指针操作
name := "Li lei"
namePtr = &name
fmt.println("指针指向的内容是:", *namePtr)
// 不同于c语言,go还可以取到栈空间的指针
func test() *int {
num := 1
return &num // 一般情况下,程序执行完毕,栈空间中的变量会被释放掉,
// 但是go会判断如果是需要使用到的栈变量,会把变量存到堆上
}
fmt.println("指针的内容是:", *test()) // 1
- map字典
xxx.go
// 推断式声明 - 推荐使用
dict := make(map(int)string)
// 或者
dict := make(map(int)string, 10) // 给定长度
// 先声明,再赋值
var dict map(int)string
dict = make(map(int)string)
// 赋值
dict[0] = "first"
dict[1] = "second"
// 读取
fmt.println("值是:", dict[0]) // first
fmt.println("超过容量的值是:", dict[100]) // 空,当读取的key不在容量内时,返回空,不报错
// 循环
for key, value := range dict {
fmt.println("key是:", key, ", value是:", value)
}
// 判断map中是否有这个key存在(由于读取不存在的key也不报错)
value, ok := dict[0]
if ok {
fmt.println("value是:", value) // first
} else {
fmt.println("value是:", value) // 空
}
// 删除某一个值
delete(dict, 0)
delete(dict, 100) // 删除不存在的,也不会报错
fmt.Println("删除后:", dict) // map[1 : second]
// 并发任务处理的时候,需要对map上锁
发布于2024-01-26 14:19:32
浏览量69·
暂无评论,快来发表第一条评论吧