这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
这里是本人学习GO基础语法的相关笔记,将供参考,本人有Java后端和c语言经验。
常见语法:
Hello world程序
package main
import "fmt"
func main() {
fmt.Printf("hello")
}
命令行工具使用
- go run xxx.go,运行xxx.go文件,后面可以跟着参数
- go build xxx.go 编译xxx.go文件会生成xxx.exe文件
基础知识点:
- 标记:键字,标识符,常量,字符串,符号
- 注释:单行和多行注释
- 标识符:字符、数字和下划线,首字母不能是数字
- 字符串+:字符串可以+连接
- 关键字:一共61个
- 格式化字符串:%d,%s等
变量使用
基本数据类型
- bool:只能是true和false
- 数字类型:整型int、浮点数float和复数
- 字符串类型:固定长度的字符序列,底层的是一个只读的byte slice
- 派生类型:指针、数组、结构体、channel、函数、切片、接口、map
变量声明:使用 var和:=和根据值判断
- var identifier type:多变量var identifier1, identifier2 type
- v_name := value
- var v_name = value
GO常量:
运行时不会被修改值,可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
const identifier [type] = value
- iota,特殊常量,新增一行计数一次,0开始。
func main() {
var a = "hello"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f)
fmt.Println(g)
const s = "hello"
const h = 1
fmt.Println(s)
fmt.Println(h, math.Sin(h))
}
常量没有类型,可以通过上下文进行自动判断
运算符:
同c和java类似,不再说明
if、switch、for
if没有()
没有while只有for
switch不用使用break;要达到强制执行下一个case,通过
func main() {
var a = 1
switch a {
case 1:
fallthrough
case 10:
println("hello")
}
}
数组
声明方式:var variable_name [SIZE] variable_type
- var balance [10] float32
初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
访问:var salary float32 = balance[9]
切片Slice
和Java的ArrayList感觉使用上很相似,底层通过数组实现,Slice长度不像普通数组一样固定,能够改变。每次扩容都是扩容为旧容量的两倍,若长度大于等于1024,扩容为原来的1/4。
创建:
- var slice1 []type = make([]type, len)
- make([]T, length, capacity) capacity为容量,可选、
相关操作:
- 切片
- append,可以往nil的切片添加数据
- copy
- len
- cap
map
声明方式:
- map_variable := make(map[key_data_type]value_data_type)
- var map_variable map[key_data_type]value_data_type
注意点:
- 不可以往nil的map中添加数据
- map没有对应key的返回值与数据类型匹配,有nil,"",false。所以在判断map中是否包含对应key的时候,不能够把默认返回值作为对比。需要使用返回的error信息作为判断。
-
- 例如 if _, ok := x["two"]; !ok { fmt.Println("key two is no entry")}
可用通过map使用空结构体做出一个set来,简单演示一下:m := make(map[string]struct{})
range
range语法,返回两个值,一个是index,一个是value
map进行range,返回k和v,只用一个,返回key,map没有index顺序。
func main() {
m := make(map[string]int)
m["k1"] = 1
m["k2"] = 3
m["k3"] = 5
for k, v := range m {
fmt.Println("key=", k, "value=", v)
}
}
函数:
func 方法名( 参数列表) 返回值类型{return 返回值列表}
init函数
init函数会在main函数之前触发,这个类似于python的__init__(我记得是)。所以这里能够做到事现注册很多东西的效果。
defer相关:
- 用于处理panic,其中的recover()不能被函数嵌套。
- 注意defer函数的作用域,在for循环中的循环变量使用
指针:
和c语言类似。
没有和java一样的this指针,对象都是通过显式进行传递,面向对象的方式不同与java和c++。
结构体:
type person struct {
name string
age int
}
func main() {
p1 := person{"wth", 21}
p2 := person{name: "wth", age: 123}
p3 := person{name: "wht"}
fmt.Println(p1)
fmt.Println(p2)
fmt.Println(p3)
}
结构体方法:
func (变量名 结构体类型) 方法名(参数,参数类型) 返回值{
}
错误处理
有异常
func 方法名(参数列表) error {
return nil
}
func 方法名(参数列表)(返回值列表){} // 返回值列表中包含error
func 方法名(a int, b int) (c int, err error) {
return a + b, nil
}
nil是空
变量作用域
- 函数内定义的变量称为局部变量
- 函数外定义的变量称为全局变量
- 函数定义中的变量称为形式参数
字符串处理:
字符串格式化:+和#具有很好的详细打印功能功能
%v表示变量的含义,类似于%d,%f,%c等的结合。
fmt.printf("%+v",str);
fmt.printf("%#v",str);
+和#具有很好的详细打印功能功能
JSON处理
结构体,变量名大写就可以。
Marshal,和Unmarshel
数字解析:
strconv.ParseInt("字符串",进制,精度)
strconv.Atoi("字符串")//字符串到数字。
总结
go语言语法比较简单,上手比较容易
- defer关键字比较特别。
- switch比较特别
- panic处理,需要在defer中直接使用recover,嵌套使用会失败。