这个主题的博客主要用来记录学习Go的过程,此篇记录初学时我了解的知识和工具,不会从头开始,但是会给一些路线。后续这个系列的博客也只是记录我经过思考才能明白的问题!
Go教程我选的是社区推荐的《The way to go》,用来了解基础的语法,如果有其他语言基础,可以粗略过一遍,遇到问题再回看;新手的话建议结合菜鸟教程一起看,把细节都理解清楚。
《The way to go》:https://www.cntofu.com/book/14/readme.html
初级教程过后可以看《Go语言高级编程》,这本书可以让你对Go的细节更清晰。
《Go语言高级编程》:http://books.studygolang.com/advanced-go-programming-book/
编写工具推荐:
根据自己使用工具的习惯来
初学者、Idea使用者(jetbrains家的idea、Pycharm等)推荐Goland
我用的是VSCODE配置难度会高些
大神的话记事本、Vim…都可
基础知识这里不提及,仅仅记录个人记录的知识点,欢迎大家补充到评论
golang设计目标:
1.工程开发迅速
2.适应现代计算机多核的特点
3.适应现代计算机网络发达的特点
4.让人享受开发过程
结合Python、Ruby动态语言及Java、C的高性能和安全
Go编程规范:https://golang.org/ref/spec
语言特性:
1.拥有明确的编码规范,所以可以选用不同的编译器
2.go中用interface替代C++、Python、Java…中的类型层级
3.go中函数为基本构件,使用方法灵活
4.go和其他强制类型语言一样,不接受隐式类型转换
5.从源码到字符串都使用UTF-8,真正国际化的编程语言
什么是交叉编译
交叉编译是在一个平台上生成另一个平台上的可执行代码。
通常在开发单片机、安卓系统软件等地方会用到交叉编译,因为用主机编译(也就对应单片机、安卓)上不方便。
1.初代GOPATH,所有依赖包都到src下,在开发多个项目时不方便
2.vender,中间代的包管理工具,可以部分解决项目依赖问题
3.go.mod,官方亲儿子,可以自动化的管理项目依赖问题
● ""双引号用来创建可解析的字符串字面量(支持转义,但不能用来引用多行)
● ``反引号用来创建原生的字符串字面量,这些字符串可能由多行组成(不支持任何转义序列),原生的字符串字面量多用于书写多行消息、HTML以及正则表达式
● ''而单引号则用于表示Golang的一个特殊类型:rune,类似其他语言的byte但又不完全一样,是指:码点字面量(Unicode code point),不做任何转义的原始内容。
推迟执行语句,在函数返回前(return语句之后),执行指定的语句
可以注册多个defer语句,按照注册顺序逆序执行
go函数返回值的变量名,有用
示例:
func f() (ret int) {
ret = 5
fmt.Println("ret1:", ret)
defer func() {
fmt.Println("ret2:", ret)
ret++
}()
fmt.Println("ret3:", ret)
return 1
}
func main() {
fmt.Println(f())
}
结果:
ret1: 5
ret3: 5
ret2: 1
2
数组,一组固定顺序,可按照编号访问,固定长度,内存地址分配连续的数据结构
指定大小或自动计算长度定义的是数组
数组包含数据、长度、类型,两个数组比较时长度也会被比较,数组可用==和!=比较
var varname [length]type
var varname = [length]type{value1,value2,value3}
var varname = [...]type{index1:value1,value2,index2:value3}
varname := [5]type{value1,value2}
varname := [...]type{value1,value2}
// 猜想 这种格式定义方法会生成两个数组对象,只是等号后的是匿名的,生成后将值复制给ai
// 所以这种创建方法 不推荐 浪费内存
var ai [4]int = [4]int{1,2,4,5}
切片,数组的引用,获得数组连续编号的一个子集
// 定义切片
var varname []type
varname:=[] int{}
// 来源于数组
varname:=arrvar[3,6]
varname:=arrvar[3:6]
// 使用make创建
varname:=make([]type,5,10)
使用make的切片和用已有数组生成的切片有差别,实验如下
用数组生成的是数组的引用,可以修改原数组的值,而指向匿名数组影响就小很多,不容易出问题
使用数组生成的切片:
var aa = [5]int{2,2,88,99,2}
var as = aa[2:4]
as[0]=8888
fmt.Println("first aa:",aa)
fmt.Println("first as:",as)
as=append(as,1,2,3)
as[0]=1111
fmt.Println("second aa:",aa)
fmt.Println("second as:",as)
result:
first aa: [2 2 8888 99 2]
first as: [8888 99]
second aa: [2 2 8888 99 2]
second as: [1111 99 1 2 3]
使用make生成
var ks = make([]int, 5, 7)
ks[0] = 9999
ks[4] = 8888
fmt.Println(ks)
ks = append(ks, 1, 1, 1)
ks = append(ks, []int{2, 2}...)
fmt.Println(ks)
result:
[9999 0 0 0 8888]
[9999 0 0 0 8888 1 1 1 2 2]
数组是值类型,切片、map是引用类型
go中没有类的概念,只有结构体和方法,使用私有结构体加"构造"方法可以实现
make new copy append len cap delete
append 在切片中用处很多,能够做到增删改(单个元素或一段元素)
go中的结构体存在tag的概念,一般使用中无法获取,在用reflect时可以获取到,在构造框架时是个好工具
type Boy struct{
int age "age-tag"
string name "name-tag"
}
boy:=Boy{15,"Shuaen"}
ttType:=reflect.TypeOf(boy)
fmt.Println("name-tag:",ttType.Field(2).Tag)
const aa=0.0 通常会描述为无类型浮点常量
go中不建议用self、this、me来做receiver变量名
可能最大的问题就是会存在歧义,尤其是值传递、引用传递容易混淆;第二就是receiver是方法的第一个参数,是一种语法糖,使用self、this、me来做变量名始终不合适。
go中相对地址问题
在go工程开发时,使用go run容易找不到相对地址下的资源,这是因为使用go run时会临时生成/tmp/下项目,导致找不到相对路径
执行命令
使用os.exec模块,或者使用syscall;其实底层也是调用了process相关的模块
go中使用error来做错误处理,此类错误被认为是不导致程序终止的错误,只需要合理的处理即可;当发生或使用panic时,程序才会退出
通常有must错误检查方法的,发生error时进程会退出,也就是会引发panic;但是panic可以在deffer中用receiver获取
go非常类似线程,但是比线程更轻,由go自己维护;
可以存在一个线程上,也可以存在在多个线程;
协程可以利用计算机多核的特点,用于提高运算速度;
当然协程随着派发它的线程消亡而消亡,而且是立刻消亡。
go中的协程叫goroutines,与python或其他语言中的coroutines存在两点不同:
● Go 协程意味着并行(或者可以以并行的方式部署),协程一般来说不是这样的
● Go 协程通过通道来通信;协程通过让出和恢复操作来通信
基本使用(作用于函数):
go func(){}()
https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/14.2.md
通道作用对象:协程间
作用目的:值交换、同步
通道分为入和出,一端放入数据一端读取数据,关键字chan,使用make定义,使用ch <- value和varable =<- ch(入和出)的方式交互;通道可以使用带缓冲的通道make(chan string, buf)
注意事项: