这是我在青训营写的第一篇笔记,因为之前有学习过其他编程语言,过于基础的便没有过多研究,用笔记的形式记录自己的成长以及进行查漏补缺,希望能不断进步。
一、
var(声明变量), const(声明常量), type(声明类型) ,func(声明函数)
-
开头package xxx 例:package main
-
import声明(导入包) 例:import "fmt"
-
不存在分隔符";"
-
{不能单独在一行 ,例:可以func main() {
-
Go源文件以“go”为扩展名
-
Go应用程序的执行入口是main()函数
-
Go语言严格区分大小写
-
Go编译器是一行行进行编译的,我们最好一行就写一条语句,不能把多条语句写在同一行,否则报错
-
Go语言定义的变量或者
import的包如果没有使用到,代码就不能编译通过 -
大括号是成对出现的,缺一不可
二、
1.变量
/*var name string
var age int
var m bool */
var name = "tom"
var age =20
var b =ture
/类型可舍去/
var(
name string
age int
b bool
)
/可统一写在()内/
//前括号里为参数,后括号里为返回值
func getNameAndAge() (string , int){ return "老郭" , 30 }/* ···+enter 代码区块快捷键 **/
1.1 变量的作用域
根据变量定义位置的不同,可以分为以下三个类型:
- 函数内定义的变量称为局部变量
- 函数外定义的变量称为全局变量
- 函数定义中的变量称为形式参数
2.常量
func main(){
const PI float64 = 3.14
const PI2 = 3.1415 //可以省略类型
}
2.1 定义常量
const:定义常量的关键字
constantName:常量名称
type:常量类型(可省略)
value:常量的值
3.字符串类型的做索引
func f3(){
//key:value
m:=make(map[string]string,0)
m["name"]="tom"
m["age"]="20"
m["email"]="xgaxz@gmail.com"
for key,value:= range m{
fmt.printf("%v:%v",key,value)
}
}
4.map及map的遍历
4.1代码案例
m1:=make(map[stirng]string)
m1["name"]="tom"
m1["age"]="20"
m1["email"]="tom@gmail.com"
fmt.printf("m1:%v\n",m1)
m2:=map[string]string{
"name":"kite",
"age":"20",
"email":"kite@gmail.com"
}
/两种格式 /
func test01(){
var m1=map[string]string("name:""tom","age":"20","tom@gmail.com")
var k1="name"
var k2="age1"
v,ok:=m1[k1]
fmt.Printf("v:%v\n",v)
fmt.Printf("ok:%v\n",ok)
fmt.Println("----------")
v,ok = m1[k2]
fmt.printf("v:%v\n",v)
fmt.Printf("ok:%v\n",ok)
}
4.2
/15行代码这有两部分,a对应的value返回两个值,如果成功取到则赋值给v,第二部分是要判断的条件/
package main(){
import(
"fmt"
)
func main(){
var m map[string]int
//m=make(map[string]int,100)
m=map[sting]int("a":3,"b":6)
m["c"]=1
m["a"]=3
fmt.Println(m["a"])
delete(m,"a")
fmt.Println(m["a"])
if v,exist:=m["a"];exist{
fmt.Println(v)
}else{
fmt.Println("map中不存在a这个key")
}
for k,v:=range m{
fmt.Println(k,v)
}
}
}
4.3
Go语言中 map的定义语法如下:
map[KeyType]ValueType
其中,
- KeyType:表示键的类型。
- ValueType:表示键对应的值的类型。
4.4判断某个键是否存在
Go语言中有个判断map中键是否存在的特殊写法,格式如下:
value, ok := map[key]
4.5 for range
可以使用for range遍历map
5.切片(slice)
以下是切片的结构定义:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
- Data 是指向数组的指针
- Len 是当前切片的长度
- Cap 是当前切片的容量,即Data数组的大小
6.defer
1.关键字defer用来注册延迟调用,调用直到return前才被执行
2.类似栈,多个defer语句,先进后出
3.defer语句中的变量,在defer声明时便决定了。
7.init函数
1.不被其他函数调用,先于main函数自动执行 //加粗 ctrl+b
2.无参数,无返回值
3.每个包可以有多个init函数,包的每个源文件也可以有多个init函数(同一个包的init执行顺序,golang没有明确定义)
4.不同包的init函数按照包导入的依赖关系决定执行顺序
8.高阶函数
8.1
//11行代码左括号里为参数,右边返回值,此时为返回一个函数
package main
import "fmt"
func add(x int,y int)int{
return x+y
}
func mul(x int,y int)int{
return x-y
}
func cal(operator string) func(int,int)int{
switch operator{
case "+":
return add
case "-":
return mul
default:
return nil
}
}
func main(){
r:=cal("+")
f:=r(1,2)
fmt.Printf("the result is %v\n",f)
}
8.2
当有多个值返回的情况。 在声明返回值类型时,可以不指定名称,也可以指定名称
func Fun1(arg1 T, arg2 T)(T, T){
...
return r1, r2
}
8.3
函数也可以没有返回值,这个时候就无需 return 关键字。例如: main() 入口函数、 init() 初始化函数。
以下为一个有参数无返回值的情况:
//13行代码参数的赋值方式不同
package main
import "fmt"
func main() {
sayNum(1)
sayNum2(2, 3)
sayNum2(4, 5)
}
func sayNum(a int) {
fmt.Println("a=", a)
}
func sayNum2(a int, b int) {
fmt.Printf("a=%d\n b=%d\n", a, b)
}
func sayNum3(a, b int) {
fmt.Printf("a=%d\n b=%d\n", a, b)
}
8.4
//14行代码 --这里是三个参数
//18行--故从这里传三个参数
package main
import "fmt"
func add(x, y int) int {
return x + y
}
func mul(x, y int) int {
return x * y
}
func calc(x, y int, op func(int, int) int) int {
return op(x, y)
}
func main() {
res := calc(10, 20, add)
fmt.Println(res) // 30
resP := calc(10, 20, mul)
fmt.Println(resP) // 200
}
9.os模块
10.ioutil包
10.1读取
/第一句是读取,第二句为上传/
10.2读取(打开文件的方式)
//打开文件后要关闭,即defer f.close()这句
10.3读取目录
/ (”.“)...v为单个文件,v为文件目录,依次输入单个文件/
10.4写文件
10.5创建临时文件
(官网)
11.bufio
带缓冲的写入
12.json
//shift+tab 回退一个tab
把对象转变为一个二进制的流(byte切片)因为只有把它转为一个二进制流之后才可以执行i/o的存储或者是网络的传输,因为写在磁盘里面的或者网络传输的本质上都是一个二进制流,而不是一个结构体。所以需要把结构体转变为二进制流。
12.1序列化
最后打印是用到字符串(即这个byte字节流转换为string类型)
12.2反序列化
将它反序列化时声明一个c2结构体用来承接,需要一个取地址,因为在unmarshal内部给成员变量赋值,必须传指针,否则这个修改仅在函数内部生效而对外部结构体不影响。
字节跳动的sonic库,更快速,另外引用第三方库,需要配置一下 。
13.命名规范
go中根据首字母的大小写来确定可以访问的权限。
无论是方法名、常量、变量名还是结构体的名称,若首字母大写,则可以被其他的包访问;若首字母小写,则只能在本包中使用。
即首字母大写是公有的,首字母小写是私有的。
14.注释
单行注释的格式如下所示
//单行注释
多行注释的格式如下所示
/* 第一行注释 第二行注释 … */
15.指针
- 对变量进行取地址操作使用
&操作符,可以获得这个变量的指针变量。 - 指针变量的值是指针地址。
- 对指针变量进行取值操作使用
*操作符,可以获得指针变量指向的原变量的值。
16.数据类型转换
由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明:
valueOfTypeB = typeB(valueOfTypeA)
类型 B 的值 = 类型 B(类型 A 的值)
示例:
a := 1.0 b := int(a)
17.字符串格式化时常用动词及功能
| %v | 按值的本来值输出 |
| %+v | 在 %v 基础上,对结构体字段名和值进行展开 |
| %#v | 输出 Go 语言语法格式的值 |
| %T | 输出 Go 语言语法格式的类型和值 |
| %% | 输出 % 本体 |
| %b | 整型以二进制方式显示 |
| %o | 整型以八进制方式显示 |
| %d | 整型以十进制方式显示 |
| %x | 整型以十六进制方式显示 |
| %X | 整型以十六进制、字母大写方式显示 |
| %U | Unicode 字符 |
| %f | 浮点数 |
| %p | 指针,十六进制方式显示 |
参考课程地址: