go 从入门到了解
一,GO的安装与配置
镜像:https://golang.google.cn/dl/
1,GOPATH
GOPATH在windows上的默认值:%USERPROFILE%/go
Go1.14及之后的版本中启用了Go Module模式之后,不一定非要将代码写到GOPATH目录下,所以也就不需要我们再自己配置GOPATH了
Go1.14之前的版本GOPATH 即为工作目录:本示例设置为 E:\workgo
workgo // my-go为GOPATH目录
-- bin
-- myApp1 // 编译生成
-- myApp2 // 编译生成
-- myApp3 // 编译生成
-- pkg // 依赖包,编译后的归档文件
-- src
-- MyApp1 // 项目1
-- models
-- controllers
-- others
-- main.go
-- MyApp2 // 项目2
-- models
-- controllers
-- others
-- main.go
2,Proxy
2.1,设置代码
默认GoPROXY配置是:GOPROXY=https://proxy.golang.org,direct,
https://proxy.golang.org访问不是很可靠,常用的两个代理镜像:
代理一:go env -w GOPROXY=https://goproxy.io,direct
代理二:go env -w GOPROXY=https://goproxy.cn,direct
2.2,设置私仓库
私有库设置,不走代理
go env -w GOPRIVATE=*.gitlab.com,*.gitee.com
2.3,验证包的有效性
go mod vendor,验证包的有效性时,Get https://sum.golang.org/lookup/xxxxxx: dial tcp 216.58.200.49:443: i/o timeout
是因为 sum.golang.org 网站不能访问,可以关闭验证包的有效性
go env -w GOSUMDB=off
也可以使用国内的网站验证包的有效性
go env -w GOSUMDB="sum.golang.google.cn"
3,go环境的常用命令:
go run src/main.go
go build src/main.go
./main.exe
go version
go env
3,项目目录结构
4,开发工具:
4.1,GoLand (关键在于怎么长期使用)
GoLand 下载地址:https://www.jetbrains.com/go/download/other.html
4.2,VS Code
Vs Code 下载地址:https://code.visualstudio.com/Download
Ctrl + Shift + P 安装 go:install 相关命令
5,包管理
1.5版本之前,依赖包放在GOPATH下
1.5版本及之后,采用了vendor机制,主要解决包的版本管理
1.9版本推出了包管理工具,dep
1.11版本推出了包管理工具,modules 简称 mod
初始化一个项目的mod, go mod init <项目名>
go.mod定义:
module用来定义包名
require用来定义依赖包及版本
indirect表示间接引用
在goland中可以用alt+enter来下载依赖包
同一个项目的包引用:
"xcj.com/gose01/src/mypackage"
不同项目的包引用:
a,在go.mod里定义:
require "xcj.com/gose02" v0.0.0
replace "xcj.com/gose02" => "../gose02"
b,在使用的文件里定义:
"xcj.com/gose02/src/testpackage"
指定安装某个版本:go get package@version
例:go get github.com/astaxie/beego@v1.11.1
跨平台编译:
winows下编译linux可执行文件:
SET CGO_ENABLED=0 // 禁用CGO
SET GOOS=linux // 目标平台是linux
SET GOARCH=amd64 // 目标处理器架构是amd64
windows下编译苹果可执行文件:
SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
变量声明:
var name string
var age int
var isOk bool
var (
a string
b int
c bool = true
d float32
) // 通过用小括号包含的方式写到多行
var a, b, c int // 变量a、b、c的类型都是int 若不赋值,用零值来初始化
var x, y, z = true, 10.24, "randy" // 推导出变量x、y、z的类型分别为bool、float64、string
var f, err = os.Open(name) // 调用os.Open函数返回一个打开的文件和一个错误信息
短变量:
i, j := 0, 1 // 简短声明一组变量,用于函数内部
a,b: = 200,"hello" // 简短声明一组变量,用于函数内部
匿名变量:
定义:
func Foo(str string) (int, string) {
return 10, str
}
调用:
x, _ := mypackage.Foo("xcj")
_, y := mypackage.Foo("yy")
fmt.Println("x=", x)
fmt.Println("y=", y)
// iota是go语言的常量计数器,只能在常量的表达式中使用
// iota的行记数,只在当前const内生效
// iota在const关键字出现时将被重置为0 ,主要是用于定义枚举
// const同时声明多个常量时,如果省略了值则表示和上面一行的值相同
const (
n1 = iota
n2 = iota
n3 = 0
n4
)
const n5 = iota //0
fmt.Println(n1,n2,n3,n4,n5) // 输出结果 0 1 0 0 0
格式化输出:
var people interface{} = struct {
name string
age int
}{"sam", 20}
fmt.Printf("%v\n",people) // %v 相应值的默认格式 {sam 20}
fmt.Printf("%+v\n",people) // %+v 打印结构体时,会添加字段名 {name:sam age:20}
fmt.Printf("%#v\n",people) // %#v 相应值的Go语法表示 struct { name string; age int }{name:"sam", age:20}
fmt.Printf("%T\n",people) // %T 相应值的类型的Go语法表示 struct { name string; age int }
fmt.Printf("%v%%\n",100) // %% 字面上的百分号,并非值的占位符 100%
go的数据类型:
除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。
nil是预定义的标识符,代表指针、通道、函数、接口、映射或切片的零值,是预定义好的一个变量
// 浮点数不是一种精确的表达方式
x := 0.1
y := 0.2
res := x + y
fmt.Println(res) // 0.30000000000000004
fmt.Println(res == 0.3) // false
数组与切片:
切片可以理解成一种特殊的数组,切片可以改变存储大小,数组是值拷贝而切片是引用
// 切片添加值
//var slice []int = []int{3, 6}
//fmt.Println(slice)
//slice = append(slice, 1, 2, 3, 5, 8)
//fmt.Println(slice)
fmt.Println("数组***********************************")
var arr1 [3]int = [3]int{1, 2, 3}
var arr2 [3]int = arr1
fmt.Println(arr1, arr2)
arr2[0] = 10002
fmt.Println(arr1, arr2)
fmt.Println("切片***********************************")
var slice1 []int = []int{1, 2, 3}
var slice2 []int = slice1
fmt.Println(slice1, slice2)
slice2[0] = 10002
fmt.Println(slice1, slice2)
数组的大小是类型的一部分,数组大小不可改变
var a [4]int=[4]int{1,2,3,4}
var a =[4]int{1,2,3,4}
a :=[4]int{1,2,3,4}
interface{} 类型数组,可以包含任意类型
让编译器根据初始值的个数自行推断数组的长度
var numArray = [...]int{1, 2}
使用指定索引值的方式来初始化数组
a := [...]int{1: 1, 3: 5}
fmt.Println(a) // [0 1 0 5]
多组数组
a := [...][2]string{
{"北京", "上海"},
{"广州", "深圳"},
{"成都", "重庆"},
}
切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针(地址)、切片的长度(len)和切片的容量(cap)。
var a[9]int = [9]int{0,1,2,3,4,5,6,7,8}
fmt.Println(a)
var b[]int = a[1:2] // 使用数组构建切片
fmt.Println(b)
fmt.Println(len(b))
fmt.Println(cap(b))
a := make([]int, 2, 10)
fmt.Println(a) //[0 0]
var b []int = make([]int, 3)
var citySlice []string
citySlice = append(citySlice, "北京")
流程控制:
// if 用法
if score := 65; score >= 90 {
fmt.Println("A")
} else if score > 75 {
fmt.Println("B")
} else {
fmt.Println("C")
}
// for
// for循环可以通过break、goto、return、panic语句强制退出循环。
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 循环数组
//names:=[4]string{"张三","李四","王五"}
//for i,v:=range names{
// fmt.Println(i,v)
//}
// 循环切片
//names:=[]string{"张三","李四","王五"}
//for i,v:=range names{
// fmt.Println(i,v)
//}
// 循环字符串
//for i,v:=range "hello你好"{
// fmt.Printf("%d %q\n",i,v)
//}
// map返回键和值
//ages:=map[string]int{
// "张三":20,
// "李四":30,
//}
//for i,v:=range ages{
// fmt.Println(i,v)
//}
fallthrough 语法可以执行满足条件的case的下一个case,无条件执行下一个case(穿透)是为了兼容C语言中的case设计的。
s := "a"
switch {
case s == "a":
fmt.Println("a")
fallthrough // 无条件执行下一个case(穿透)
case s == "b":
// 上一个条件满足之后会执行这条语句 fallthrough
fmt.Println("b")
case s == "c":
fmt.Println("c")
default:
fmt.Println("...")
}
goto跳转:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 设置退出标签
goto breakTag
}
fmt.Printf("%v-%v\n", i, j)
}
}
return
// 标签
breakTag:
fmt.Println("结束for循环")
函数作为参数传递:
x11 :=calc(calc(10,20), calc(20,30))
print(x11)
func calc(x, y int) (int) {
sum := x + y
return sum
}
func intSum(x ...int) int {
fmt.Println(x) //x是一个切片
sum := 0
for _, v := range x {
sum = sum + v
}
return sum
}
我们可以使用type关键字来定义一个函数类型
type calculation func(int, int) int
func add(x, y int) int {
return x + y
}
func sub(x, y int) int {
return x - y
}
函数作为参数:
func add(x, y int) int {
return x + y
}
func calc(x, y int, op func(int, int) int) int {
return op(x, y)
}
ret2 := calc(10, 20, add)
fmt.Println(ret2) //30
闭包指的是一个函数和与其相关的引用环境组合而成的实体
func adder() func(int) int {
var x int
return func(y int) int {
x += y
return x
}
}
func main() {
var f = adder() // f = func(y int) int{...}
fmt.Println(f(10)) //10
fmt.Println(f(20)) //30
fmt.Println(f(30)) //60
f1 := adder()
fmt.Println(f1(40)) //40
fmt.Println(f1(50)) //90
}
defer延迟处理,异步处理,最后被defer的语句,最先被执行。
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")
start
end
3
2
1
Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)
Go语言中使用&字符放在变量前面对变量进行“取地址”操作。
int、float、bool、string、array、struct
*int、*float、*bool、*string、*array、*struct
//指针取值
a := 10
b := &a // 取变量a的地址,将指针保存到b中
fmt.Printf("type of b:%T\n", b) // type of b:*int
c := *b // 指针取值(根据指针去内存取值)
fmt.Printf("type of c:%T\n", c) //type of c:int
fmt.Printf("value of c:%v\n", c) //value of c:10
func modify1(x int) {
x = 100
}
func modify2(x *int) {
*x = 100
}
func main() {
a := 10
modify1(a)
fmt.Println(a) // 10
modify2(&a)
fmt.Println(a) // 100
}
// 结构体名字or结构体中的字段名字首字母大写表示公开的、可以被其他包导入,小写表示私有、仅在定义当前结构体的包中可访问
// 使用type和struct关键字来定义结构体
// 方法与函数的区别是, 函数不属于任何类型, 方法属于特定的类型。
//Person 结构体
type Person struct {
name string
age int8
}
//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
return &Person{
name: name,
age: age,
}
}
//Dream Person做梦的方法
func (p Person) Dream() {
fmt.Printf("%s的梦想是学好GO!\n", p.name)
}
func main() {
p1 := NewPerson("路人A", 25)
p1.Dream()
}
go 从入门到了解的更多相关文章
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
随机推荐
- Seaborn结构化图形绘制(FacetGrid)
结构化图形绘制(FacetGrid) 可实现多行多列个性化绘制图形. sns.FacetGrid( data, row=None, col=None, hue=None, col_wrap=None, ...
- Qt使用https协议发送带参数的post请求
背景: 现在公司项目需要做一个检测更新的功能,通过访问后台接口,判断是否需要更新. 后台接口是 https 协议的,接口需要post请求,需要带参数,来判断是哪个软件需要做检测更新的操作. 客户端软件 ...
- openGauss/MogDB数据库安装部署之xlog目录设置
openGauss/MogDB 数据库安装部署之 xlog 目录设置 本文出处:https://www.modb.pro/db/176915 关于 xlog xlog 文件是一个记录事务日志的文件,它 ...
- 如何使用 Grafana 监控文件系统状态
当 JuiceFS 文件系统部署完成并投入生产环境,接下来就需要着手解决一个非常重要的问题 -- 如何实时监控它的运行状态?毕竟,它可能正在为关键的业务应用或容器工作负载提供持久化存储支持,任何小小的 ...
- maven 设置阿里镜像[二]
前言 因为我们在国内,网速很慢,所以最好设置一下阿里镜像. 1.在maven中的conf下的setting 修改为: <mirror> <id>alimaven</id& ...
- c# 优化代码的一些规则——判断null值得不同写法[六]
前言 先来看一个例子: 假设updated 是一个委托: if(updated!=null) { updated(); } 请问上面写法在多线程中安全吗?如果不安全会抛出什么异常呢? 正文 上面的答案 ...
- MMDeploy部署实战系列【第五章】:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理
MMDeploy部署实战系列[第五章]:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理 这个系列是一个随笔,是我走过的一些路,有些地方可能不太完善 ...
- 在Windows电脑上快速运行AI大语言模型-Llama3
概述 近期 Meta 发布了最新的 Llama3 模型,并开源了开源代码.Meta Llama 3 现已推出 8B 和 70B 预训练和指令调整版本,可支持广泛的应用程序. 并且 Llama 3 在语 ...
- 力扣560(java&python)-和为k的子数组(中等)
题目: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 . 示例 1: 输入:nums = [1,1,1], k = 2输出:2示例 2: 输入:n ...
- 【pytorch学习】之线性代数
3 线性代数 3.1 标量 如果你曾经在餐厅支付餐费,那么应该已经知道一些基本的线性代数,比如在数字间相加或相乘.例如,北京的温度为52◦F(华氏度,除摄氏度外的另一种温度计量单位).严格来说,仅包含 ...