这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
前言
笔者并无任何Java基础以及其他后端开发基础,如有错误或不当之处,欢迎dalao批评、指正,期待与大家交流!
前面几天的学习笔记都鸽了,是因为笔者有数模训练和***比赛很懒,而且开发的基础不是很好,需要一定时间理解和学习。接下来我会以一种很low通俗的语言风格,将此次青训营中学习感悟到的与大家分享。
1.15 day1重点
主要学习了一些Go语言的背景、环境的配置以及基础语法
1.介绍与安装(略)、基础语法
优点:高性能、高并发,语法简单、学习曲线平缓,标准库丰富,工具链完善,静态链接,快,跨平台,自动垃圾回收
语法:
1.几种基本类型
string int bool float byte array
复制代码
2.其它类型
struct map slice tup channel
复制代码
3.int若是64位系统则是int64,
范围-9223372036854775808~9223372036854775807
4.float(默认float64)其实是double
5.前几种类型很好理解, map 的话c++,java等大多数语言里也有类似的概念
6.slice 为数组的切片,可以看成取一部分
7.channel 是go里特有的类型, 可能比较难理解, 可以理解为 一个通道。 数据(变量, 函数等可以在通道里传输)
一、几个注意的点
- 结尾习惯上不加分号(加编译器也不会报错)
- 所有变量的类型后置, 即变量的名称在变量类型的前面
比如一个int声明
var x int
复制代码
而不是
var int x
复制代码
- 变量, 函数名等的命名习惯上用小驼峰命名法, 比如:
aVar, someFunc
复制代码
- go中使用首字母是否大小写 来进行访问控制
如果首字母大写,则可以被外部包访问,反之则不可以。 结构体中的字段名若首字母小写,则无法被外部包访问和解析,像json解析
- go中的基本类型都有默认的初始值
string是"", int是0, bool是false, 数组是对应元素类型的默认值的集合...
二、函数、结构体等
- 变量声明、初始化和赋值
var x int = 32 // 用 var 关键字声明并初始化一个变量
var x = 32 // 编译器能帮你自动推断类型
// 在函数内可以选择用海象运算符简写
func xxx() {
x := 32
}
复制代码
- function
以 func 关键字开头, 后面跟函数名称, 小括号, 内部是参数, 最后是返回值(可命名)
func funcName(parm1 type1, parm2 type2) sometype {
// func body
// return xxx // if you have a value to return
}
复制代码
- struct
类似c的结构体
Point是结构体名, 在struct关键字之前(和类型后置差不多
type Point struct {
x int
y int
}
复制代码
- 创建实例
var p = Point{
x: 3,
y: 4,
}
// 按字段顺序可以省略名称
var p = Point{3, 4}
// 通过 点号 进行访问
fmt.Printf("%d, %d", p.x, p.y)
复制代码
- array
和c中的数组类似
// 用array literal初始化
var arr = [3]int{5, 7, 9}
// 声明(其实进行了默认初始化)
var arr [3]int
arr[1] = 5
fmt.Printf("arr[1]: %d", arr[1])
复制代码
- map
map 是一个键值对结构 以key: value的形式存取, 对大多数语言来说应该并不陌生
map用 map[key类型]value类型 的形式进行声明
可以用map literal进行初始化
var m = map[string]string{
"abc": "hello",
"def": "world",
}
// 或者使用make初始化一个空的map
var m = make(map[string]string)
// 然后添加元素
m["abc"] = "hello"
// 通过类似索引的形式访问
fmt.Printf("abc: %s, def: %s", m["abc"], m["def"])
复制代码
- slice
slice其实很好理解, 可以看成是数组的一部分, 实质也就是对数组的指针加大小。
同map, 可以使用make进行初始化, 并设置size
make对于不同的类型参数具有不同的意义
对于slice来说第二个参数是size, 第三个参数是capability(这个可以自己查阅资料查看实际含义
var s = make([]string, 5, 10)
s[2] = "hello"
fmt.Printf("s[2]: %s", s[2])
// 或者使用slice literal
var s = []string{"hello",}
fmt.Printf("s[0]: %s", s[0])
复制代码
slice可以通过 范围 访问一段数据, 得到一个基于原来slice的slice(实质是同一个底层数组
规则: s[start:stop]
start 默认是0, stop默认是索引的size
得到新切片的范围是 索引从start到stop-1所对应的内容
var s1 = s[1:3] // 访问索引为1到2的数据
var s2 = s[:4] // 访问索引为0到3的数据
复制代码
三、 控制流程
if语句, 和c基本一样, 只是没有括号
if s > 3 {
// do something
}else if s == 3 {
//do sth
}
复制代码
go可以在if语句中进行变量的初始化操作, 该变量的作用域在if内, 出了if便无法访问(限制了作用域的大小,挺好的 常常用于错误处理
if err := someFunc(); err != nil {
// err handling
}
复制代码
- for 语句
go中没有while, 循环只靠for
// 无限循环
for {
// do something
}
// 类c的条件循环
for i := 3; i < 5; i++ {
// do something
}
// range 循环 (python或rust等语言里也有类似的概念)
s := [3]int{1, 5, 9} // 长度为3的数组
for i := range s {
fmt.Println(i)
}
复制代码
/////////////////////////////////////////////////
/////////////////////////////////////////////////
复制代码
四、 channel
感觉可能不太好理解..
可以和goroutine结合来看
channel是个比较特殊的类型, 主要是为goroutine (go中最核心的概念之一)服务的
简单来说, 是为了在多个协程之间传输(共享)数据用的
使用channel之前需要用make初始化, 其中, 第二个参数是bufsize
var c chan int = make(chan int, 3)
复制代码
另外,课程中还飞快地过了一遍:错误处理、字符串操作、json处理、时间处理、数字解析、进程信息等知识
错误处理:
go语言的处理方式,能够很清晰地知道哪个函数返回了错误,并且能用简单的if else来处理错误。在函数里面,我们可以在那个函数的返回值类型里面,后面加一个error,就代表这个函数可能会返回错误。
那么在函数实现的时候,return需要同时 return两个值,要么就是如果出现错误的话,那么可以return nil和一个error。如果没有的话,那么返回原本的结果和nil。
字符串操作:
在标准库strings包里面有很多常用的字符串工具函数,比如 contains 判断一个字符串里面是否有包含另一个字符串,count字符串计数, index查战某个字符串的位置。join连接多个字符串,repeat重复多个字符串,replace替换字符串。
字符串格式化,在标准库的FMT包里面有很多的宇符串格式相关的方法,比如 printf这个类似于C语言里面的printf函款。不同的是,在go语言里面的话,你可以很轻松地用%v来打印任意类型的变量,而不需要区分数字字符串。你也可以用%+v打印详细结果,%#v则更详细。
json处理:
go语言里面的JSON操作非常简单,对于一个已有的结构体,我们可以什么都不做,只要保证每个字段的第一个字母是大写,也就是是公开字段。那么这个结构体就能用JSON.marshaler去序列化,变成一个JSON的字符串。
序列化之后的字符串也能够用JSON.unmarshaler去反序列化到一个空的变量里面。
默认序列化出来的字符串的话,它的风格是大写字母开头,而不是下划线。我们可以在后面用json tag等语法来去修改输出JSON结果里面的字段名。
时间处理:
在go语言里面最常用的就是 time.now()来获取当前时间,然后你也可以用time.date去构造一个带时区的时间。有很多方法获取时间的年、月、日、小时、分钟、秒,然后也能用.sub去对两个时间进行减法,得到一个时间段。时间段又可以去得到它有多少小时,多少分钟、多少秒。
在和某些系统交互的时候,我们经常会用到时间戳。那您可以用.UNIX来获取时间戳。
数字解析:
在go语言当中,关于字将串和数字类型之间的转换都在STR conv这个包下,这个包是string comvert这两个单词的缩写。我们可以用parselnt 或者parseFloat来解析一个字符串。
我们可以用Atoi把一个十进制字符串转成数字。可以用itoA把数字转成字符串。如果输入不合法,那么这些函数都会返回error
进程信息:
在go里面,我们能够用os.argv来得到程序执行的时候的指定的命令行参数。
比如我们编译的一个二进制文件,command。后面接abcd来启动,输出就是os.argv会是一个长度为5的slice ,第一个成员代表二进制自身的名字。我们可以用so.getenv来读取环境变量。
2.实战
1.猜谜游戏(好像没啥东西
2.在线词典(调用了一下彩云小译,然后处理一下返回的json)
3.SOCKS5代理(TCP echo server->auth->请求->relay,跟着走一遍应该没什么问题)
3.个人总结
看了贺兰等大佬详尽、规范的笔记,体会是要多向优秀的人学习,并不断改进自己。
我这匆匆rework+cv写的笔记毫无可读性和可比性,后续慢慢修改完善吧,事情确实有一点小多~人也确实菜-呜呜
引用
- 字节内部课:Go 语言上手 - 基础语法
- SAST-go引入(大二讲师笔记)